diff options
Diffstat (limited to 'doc')
117 files changed, 93174 insertions, 0 deletions
diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 000000000..ecbb7fc6d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +stamp-vti diff --git a/doc/BUGS b/doc/BUGS new file mode 100644 index 000000000..736edaace --- /dev/null +++ b/doc/BUGS @@ -0,0 +1,13 @@ + +Known Guile documentation bugs -*- outline -*- + +* The building of HTML docs is dependent on GNU Make + +This is because the Makefile.am's for the Guile reference manual and +tutorial use a $(shell ...) command to list the set of HTML files to +install. + +Probably this will not be fixed until Automake gains proper HTML doc +support. On the other hand, if we've overlooked a more +version-independent way of achieving the same thing, please let us +know. diff --git a/doc/ChangeLog-2008 b/doc/ChangeLog-2008 new file mode 100644 index 000000000..4153ad873 --- /dev/null +++ b/doc/ChangeLog-2008 @@ -0,0 +1,996 @@ +2008-04-26 Ludovic Courtès <ludo@gnu.org> + + * Makefile.am (EXAMPLE_SMOB_FILES): Remove `COPYING'. + +2008-01-22 Neil Jerram <neil@ossau.uklinux.net> + + * COPYING: Removed. + + * oldfmt.c: Update copyright statement to LGPL. + +2002-09-14 Rob Browning <rlb@defaultvalue.org> + + * .cvsignore: add stamp-vti.1 + +2002-08-24 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (EXTRA_DIST): Do not distribute guile-api.alist, it + can't be built currently. + +2002-05-13 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am (EXTRA_DIST): New var. + +2002-05-11 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am: Include ../am/maintainer-dirs (in MAINTAINER_MODE). + (guile-api.alist, guile-api.alist-FORCE): + New rules (in MAINTAINER_MODE). + +2002-05-09 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * groupings.alist: Add copyright and commentary. + + (favorite): Delete this example composite. + (embedded-libltdl, gdb, coop, gh, g-fdes, r-fdes, scm, k, POSIX, + guile-C-API): New groups. + +2002-05-08 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * groupings.alist: New file. + +2002-04-23 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * guile-api.alist: Update. + +2002-04-16 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (dist-hook): Simplified to not use "cd"; now it + works for relative pathnames in $(distdir). + +2002-04-10 Rob Browning <rlb@defaultvalue.org> + + * .cvsignore: add version-tutorial.texi, version.texi, and + stamp-vti1. + +2002-03-01 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * guile-api.alist: Update. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + * mltext.texi (Guile Character Properties): Fix `hexidecimal' + spelling errors (merge from stable branch). + + * AUTHORS: Removed. Authorship information for each manual is now + in the top-level Texinfo file for that manual. + +2001-08-24 Neil Jerram <neil@ossau.uklinux.net> + + * Makefile.am: Split documentation into per-manual subdirectories. + +2001-08-22 Mikael Djurfeldt <mdj@linnaeus.mit.edu> + + * scheme-options.texi (Evaluator trap options): Splitted + section "Evaluator options". + + * scheme-evaluation.texi (Evaluator Behaviour): Typo "reader + options" --> "evaluator options". + +2001-08-17 Rob Browning <rlb@defaultvalue.org> + + * Makefile.am (guile_tut_TEXINFOS): remove guile-tut.texi. It's + already in info_TEXINFOS. + + * .cvsignore: rename stamp-vti1 to stamp-vti.1. Of course this + only matters once you fix the bug in automake. + +2001-08-02 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-debug.texi (Debugging): Improve `make-stack' doc by + explaining cutting args. + +2001-07-19 Rob Browning <rlb@defaultvalue.org> + + * posix.texi (Signals): add docs for setitimer and getitimer. + +2001-07-11 Gary Houston <ghouston@arglist.com> + + * scheme-evaluation.texi: Added `load-from-path'. Corrected `load': + it doesn't use the load paths. + +2001-07-04 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Hook Reference): Removed documentation for + `make-hook-with-name', which does note exist. Added note about + unspecified return values to all procedure documentation + +2001-07-02 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-modules.texi (SRFI-1 Fold and Map): Documented extended + versions of `map' and `for-each'. + +2001-06-30 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * preface.texi (Manual Conventions): Added description of + @result{} and @print{}. + + * scheme-data.texi (Hash Table Examples): New subsubsection. + +2001-06-30 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Hash Tables): Added docs for + `make-hash-table'. + +2001-06-29 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * misc-modules.texi: New file. + (Pretty Printing): New chapter. + (Formatted Output): New chapter. + + * Makefile.am (guile_TEXINFOS): Added misc-modules.texi. + + * guile.texi (Top): Added inclusion of misc-modules.texi. + + * scheme-modules.texi (Included Guile Modules): Added (srfi + srfi-4) and (ice-9 rw) modules. + (Module System Quirks): Removed note that `module-export!' must be + called via gh_eval_str, now that we have scm_c_export. + + * repl-modules.texi (Loading Readline Support, Readline Options): + New nodes. + +2001-06-27 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Network Sockets and Communication): Grammar fix - + thanks to Christopher Cramer! + +2001-06-27 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-modules.texi (SRFI-4): Added documentation for the new + module (srfi srfi-4). + +2001-06-26 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (scm transition summary): Refer to scm_mem2string + instead of scm_makfromstr. + +2001-06-26 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * oldfmt.c (scm_oldfmt): Use scm_mem2string instead of + scm_makfromstr. + +2001-06-25 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (GH deprecation): Remove paragraph about portability. + + * extend.texi (Libguile Intro): Updated following Marius' + suggestions. + +2001-06-25 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (version.texi, version-tutorial.texi): Removed + kluges to build them unconditionally. + +2001-06-22 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (scm transition summary): New node for summary of how to + transition from GH to scm interface. + (GH): Link to new node. + (Calling Scheme procedures from C): Remove doc for gh_set_car and + gh_set_cdr, which don't actually exist. + (Data types and constants defined by gh): Correct + SCM_UNSPECIFIED/SCM_UNDEFINED confusion. + (Calling Scheme procedures from C): Correct SCM_EOL/SCM_UNDEFINED + confusion. + +2001-06-20 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi (Top): Move GH chapter to end of Part V. + + * extend.texi (Libguile Intro), gh.texi (GH deprecation): Explain + deprecation of GH and broad plan for documentation of scm + interface. + +2001-06-18 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-modules.texi (SRFI-1): Completed procedure documentation. + + * scheme-data.texi (List Constructors): Added make-list. + Added type index entries for all data types. + +2001-06-15 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-modules.texi (SRFI-1): New section documenting the SRFI-1 + module. + +2001-06-14 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-modules.texi (Included Guile Modules): Added reference to + (srfi srfi-1) module. + +2001-06-16 Marius Vollmer <mvo@zagadka.ping.de> + + * posix.texi (Conventions): Use `system-error-errno' instead of + explicit code + +2001-06-04 Gary Houston <ghouston@arglist.com> + + * scheme-io.texi (Block Reading and Writing): added + write-string/partial, updated read-string!/partial. + +2001-05-30 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * General: A lot of typo, texinfo markup and layout corrections. + + * scheme-data.texi (Arithmetic): Clarified docs for - and /. + (String Modification): Removed docs for C functions + (scm_substring_move_right_x etc.) + (Keyword Procedures): New section documenting the keyword + procedures from boot-9.scm. + (Vectors): Moved the section before the non-standard data types. + + * data-rep.texi (Defining New Types (Smobs)): Adapted description + of smobs and proocedure creation to new terminology. + (Describing a New Type): Removed mentioning of + scm_make_smob_type_mfpe from smob function list and added + deprecation notice for this function. + (Creating Instances): Added description and macro docs for smobs + with 2 or 3 data cells. + (Garbage Collecting Smobs): Removed old docs for SCM_GCTYP16. + (Garbage Collecting Simple Smobs): Added some clarification about + usage and usefulness. + (Non-immediate Datatypes): Changed R4RS reference to R5RS. + (Vector Data): Document type-specific accessors. + + +2001-05-23 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * guile.texi: Commented out menu entry and inclusion of Tcl/Tk + stuff. + + * indices.texi: Users are advised to look under C and Scheme + names, xref to transformation rules added. + + * intro.texi, scheme-modules.texi, scheme-ideas.texi, + scheme-evaluation.texi, scheme-data.texi, scheme-procedures.texi: + Fixed most REFFIXMEs. + + * srfi-modules.texi (About SRFI Usage): New node. + (SRFI-0): Extended. + Fixed all REFFIXMEs. + +2001-05-19 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Networking): Split existing material into new nodes + `Network Address Conversion' and `Network Databases'. + + * scheme-control.texi (Lazy Catch): Update doc for new constraint + that lazy-catch handlers are not allowed to return. + +2001-05-16 Rob Browning <rlb@cs.utexas.edu> + + * scheme-options.texi (Install Config): fixed minor-version docs + and added micro-version docs. + +2001-05-16 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi, srfi-modules.texi (SRFI-14 Iterating Over + Character Sets), scheme-io.texi (Block Reading and Writing), + scheme-control.texi (Lazy Catch), scheme-procedures.texi (Internal + Macros): Add @bullet to @itemize usages. (Thanks for Masao + Uebayashi for the bug report!) + +2001-05-15 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scripts.texi (Invoking Guile): Added docs for --use-srfi. + + * expect.texi, repl-modules.texi: Start the chapters with a new + page. + + * srfi-modules.texi (SRFI-0): Added note about supported feature + identifiers and an example. Start the chapter with a new page. + + * srfi-modules.texi, scheme-data.texi, scheme-control.texi, + scheme-binding.texi, repl-modules.texi, posix.texi, intro.texi, + scheme-utility.texi: Change `--' to `-' throughout. + +2001-05-14 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-13-14.texi: Removed. + + * srfi-modules.texi (SRFI-13): Merged SRFI-13 docs into SRFI + chapter. + (SRFI-14): Merged SRFI-14 too. + + * guile.texi (Top): Remove inclusion of obsolete SRFI-13/14 file. + + * srfi-modules.texi (SRFI-0): New section. + (SRFI-16): New section. + + Change `--' to `-' throughout. + +2001-05-13 Thien-Thi Nguyen <ttn@revel.glug.org> + + * intro.texi, scheme-modules.texi, scheme-procedures.texi: + Fixup some module-related references. + + * scheme-modules.texi (Modules): Remove "babbling" fixme. + (The Guile module system): Rewrite intro. + (General Information about Modules): Rewrite some parts. + Move problems to "Module System Quirks". + (Using Guile Modules): Renamed from "Loading Guile Modules". + Rewrite most parts. + Remove reivewme comment. + (Creating Guile Modules): Review, touch up. + Remove "Tkintr" comment. + (Module System Quirks): New node/subsection. + +2001-05-06 Thien-Thi Nguyen <ttn@revel.glug.org> + + * intro.texi (Using Guile Modules): Review; remove reviewme + comment. Expand `GUILE_LOAD_PATH' blurb; add small example. + (Reporting Bugs): Review; remove reviewme comment. + Reword some phrases; add texi markup. + Add suggestion to include `guile-config info' output. + Update gdb invocation; add fixme question. + +2001-05-05 Neil Jerram <neil@ossau.uklinux.net> + + * AUTHORS: Added Martin Grabmueller. + + * scheme-procedures.texi (Macros, Syntax Rules, Internal Macros): + New material. + (Syntax Case): New node, but currently empty. + + * scheme-data.texi (Booleans, Symbols): Supply cross-references. + +2001-05-04 Neil Jerram <neil@ossau.uklinux.net> + + * new-docstrings.texi, posix.texi, scheme-control.texi, + scheme-data.texi, scheme-debug.texi, scheme-evaluation.texi, + scheme-io.texi, scheme-memory.texi, scheme-procedures.texi: + Automatic docstring updates (mostly argument name updates and + blank lines). + + * scheme-modules.texi: Change double hyphens to single. + + * scheme-control.texi (Lazy Catch): Completed. + + * posix.texi (Network Databases and Address Conversion): New + subsubsection `IPv6 Address Conversion'. + +2001-05-04 Thien-Thi Nguyen <ttn@revel.glug.org> + + * preface.texi (iff): Use proper texi markup. + Thanks to Florian Weimer. + +2001-05-04 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-io.texi (Block Reading and Writing): Moved the + documentation for read-string!/partial from the node `Reading'. + + * scheme-data.texi (List/String Conversion): Added docstring for + `string-split'. + +2001-05-02 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-13-14.texi: Added @bullet to various @itemize lists. + + * srfi-modules.texi (SRFI Support): New file and chapter. + + * Makefile.am (guile_TEXINFOS): Added repl-modules.texi and + srfi-modules.texi. + + * guile.texi (Top): New menu entries for the new chapters. + (Top): @includes for the new chapters. + (Top): New menu entry for `SRFI Support', @include for + `srfi-modules.texi'. + + * repl-modules.texi: New file. + (Readline Support): New chapter for (ice-9 readline). + (Value History): New chapter for (ice-9 history). + +2001-05-02 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-modules.texi (Dynamic Libraries): Renamed from `Dynamic + Linking from Marius''. + (The Guile module system): Removed obsolete naming convention. + (Loading Guile Modules, Creating Guile Modules), + (More Module Procedures, Included Guile Modules): New nodes, split + from `The Guile module system'. + (The Guile module system): Changed references to (ice-9 slib) to + (ice-9 popen), because note everybody has SLIB installed. + (Included Guile Modules): Added a bunch of modules shipped with + Guile. + + (Dynamic Libraries): (old version) Removed. + + * scheme-io.texi (Block Reading and Writing): Corrected + capitalization, so it builds again. + +2001-05-01 Gary Houston <ghouston@arglist.com> + + * scheme-io.texi: Removed obsolete section Binary IO. Added + new section Block Reading and Writing. Updated section + Line/Delimited with module usage. + +2001-04-29 Neil Jerram <neil@ossau.uklinux.net> + + * deprecated.texi (Tags): Removed - deprecation expired. + + * scheme-io.texi (Random Access): Removed `fseek' - deprecation + expired. + + * guile.texi (Top): Add menu entry for Manual Conventions node. + +2001-04-28 Neil Jerram <neil@ossau.uklinux.net> + + * THANKS: Move authorship bit into AUTHORS, simplify structure, + add Dirk Herrmann. + + * AUTHORS, guile.texi, guile-tut.texi, goops.texi, Makefile.am: + Consolidate authorship information in AUTHORS file, and @include + AUTHORS from the top level source file for each manual. + +2001-04-28 Thien-Thi Nguyen <ttn@revel.glug.org> + + * preface.texi (Manual Conventions): New chapter. + +2001-04-26 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-13-14.texi (Reverse/Append): Updated procedure names for + string-concatenate-reverse[/shared]. + (Reverse/Append): Document the parameter `end' to + string-concatenate-reverse. + +2001-04-26 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi (Defining New Types (Smobs)): Use non-deprecated + smob interface. Thanks to Masao Uebayashi for the patch! + (Creating Instances): Don't need SCM_NIMP anymore. + +2001-04-25 Marius Vollmer <mvo@zagadka.ping.de> + + * guile.1: New file, from Robert Merkel and Rob Browning. + * Makefile.am (man_MANS, EXTRADIST): Added, but still commented + out: install and distribute the manpage. It is not yet installed + or distributed since we don't have Robert's papers yet. + +2001-04-24 Neil Jerram <neil@ossau.uklinux.net> + + * guile-tut.texi: Include version-tutorial.texi rather than + version.texi. + + * Makefile.am ($(srcdir)/version-tutorial.texi): New target, to + avoid having two files both include version.texi. + +2001-04-24 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * Makefile.am (guile_TEXINFOS): Added srfi-13-14.texi. + + * srfi-13-14.texi: New file documenting SRFI-13/14. + + * guile.texi (Top): Added the SRFI-13/14 menu entry and @include. + +2001-04-22 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Network Sockets and Communication): Automatic + docstring updates for `socket' and `connect'. (For IPV6 support.) + + * scheme-io.texi: Remove old docstring comments referring to + r4rs.scm. + + * appendices.texi (The Basic Guile Package, Packages not shipped + with Guile), env.texi (Switching to Environments), format.texi + (Format Specification), gh.texi + (Executing Scheme code, Calling Scheme procedures from C), + guile-tut.texi (How to characterize Guile), scheme-data.texi + (Symbols, Keywords, Keyword Read Syntax, Append/Reverse), + scheme-evaluation.texi (Delayed Evaluation), scheme-modules.texi + (Scheme and modules), scheme-io.texi (Soft Ports): Change R4RS + references to R5RS. + + * r4rs.texi: Removed. + + * Makefile.am (info_TEXINFOS): Remove r4rs. + + * README: Note removal of r4rs, and provide a reference. + + * scheme-control.texi (Exceptions): Extended documentation. + (Continuations): Correct "except" typo, and fix reference to + Exceptions node. Plus minor review changes. + +2001-04-20 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-control.texi (Exceptions): Reorganized and extended + existing documentation; more to come. + +2001-04-20 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-evaluation.texi (Comments): Document normal comments and + comment conventions. + (Block Comments): Documented multiline comments. + (Case Sensitivity): Documented R5RS and Guile behaviour and how to + switch it off. + + * scheme-control.texi (Continuations): Added some documentation + for call/cc. + (Exceptions): Added xref to `Continuations'. + + * scheme-binding.texi (Binding Reflection): Typo fix. + +2001-04-20 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (Executing Scheme code): gh_eval_file returns + SCM_UNSPECIFIED. Thanks to Dirk for the report! + + * data-rep.texi (Non-immediate Datatypes, Immediates vs + Non-immediates): Emphasize current rather than pre-1.4 practice + when talking about not needing to call SCM_NIMP. + + * recipe-guidelines.txt: New file: guidelines for contributions to + the Guile Recipes manual. + +2001-04-20 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * intro.texi (Using Guile Modules): Wrote intro to using modules. + (Writing New Modules): New intro for writing modules. + (Reporting Bugs): Added info about what is a bug and what to + include in a bug report (taken and adapted from the Emacs + Reference Manual). + +2001-04-19 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-control.texi (while do): Added documentation for named + let. + + * scheme-binding.texi (Internal Definitions): New explanation of + `Internal Definitions'. + (Top Level): Documented behaviour of top level definitions. + (Binding Constructs): New introductory text. + (Local Bindings): Explain concept of local bindings. Document + let, let* and letrec. + +2001-04-18 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-modules.texi (Modules): Added menu descriptions. + (Scheme and modules, The Guile module system): Some whitespace + cleanup + (The Guile module system): Layout fixes, docstring fix for + `define-module'. + +2001-04-17 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-control.texi (Multiple Values): Documented concept of + multiple values, added docs for `receive'. + (begin): Documented `begin'. + (if cond case): Documented `if', `cond' and `case'. + (and or): Documented `and' and `or'. + (while do): Documented `do' and `while'. + + * scheme-procedures.texi (Optional Arguments): Split the node, + added introductory text, added menu for subsections. + (let-optional Reference, let-keywords Reference), + (lambda* Reference, define* Reference): Added syntax documentation + for all exported procedures from (ice-9 optargs). + +2001-04-17 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-utility.texi (General Conversion): New node, added + `object->string'. + (Equality): Added definition and explanation of `sameness'. + + * posix.texi (System Identification): Added `gethostname' and + `sethostname'. + (Processes): Added `setpriority' and `getpriority'. + (User Information): Added `cuserid' and `getlogin'. + (Ports and File Descriptors): Added `flock'. + (Processes): Added `chroot'. + (File System): Added `mkstemp!'. + (Encryption): New node, added `crypt' and `getpass'. + + * new-docstrings.texi: Moved several docstrings over to the + reference manual (see above which). + + * scheme-data.texi (Data Types), (Numerical Tower): Add explicit + @bullet to @itemize to satisfy older `makeinfo'. + +2001-04-16 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi (Signalling Type Errors): Update SCM_ASSERT doc + for recent changes to disallow passing a string parameter as the + `pos'. Thanks to Dirk Herrmann for the patch! + +2001-04-13 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi (Unpacking the SCM type): New section, taken from + Dirk Herrmann's description of SCM and scm_bits_t in api.txt. + (Immediate Datatypes, Non-immediate Datatypes): Remove obsolete + notes about needing to call SCM_NIMP. + +2001-04-11 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-procedures.texi (Procedures with Setters): Fix dvi + building syntax error. Thanks to Dale P. Smith for the report and + patch. + +2001-04-11 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-scheduling.texi (Arbiters): New explanatory text. + (Asyncs): New explanations and documentation. + (Scheduling): Added menu entry descriptions. + (Fluids): New documentation. + +2001-04-11 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-procedures.texi (Lambda): Documented the lambda form. + (Procedure Properties): Concept and usage explanation added. + (Procedures with Setters): Explain by example, introduce + definitions. + + * scheme-data.texi (Symbols and Variables): Split and reorganized + this section. + (Symbols): New introductory text. + (Characters): Added char-ci* procedures to rn index. + +2001-04-10 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (Handling Errors): Improve Texinfo markup. Thanks to + Dale P. Smith for the patch! + + * api.txt (Accessing Cell Entries): Fix typo. + +2001-04-09 Neil Jerram <neil@ossau.uklinux.net> + + * deprecated.texi (Shared And Read Only Strings): New section for + deprecated string stuff. I've also updated the text a bit to + reflect current usage of "read only" strings. + + * scheme-data.texi (Shared Substrings, Read Only Strings): Moved + to deprecated.texi. + + * deprecated.texi, posix.texi, scheme-binding.texi, + scheme-control.texi, scheme-data.texi, scheme-debug.texi, + scheme-evaluation.texi, scheme-io.texi, scheme-memory.texi, + scheme-modules.texi, scheme-options.texi, scheme-procedures.texi, + scheme-scheduling.texi, scheme-translation.texi, + scheme-utility.texi: Remove `@c docstring' comments, since they + aren't used any more by the docstring tracking utilities. + +2001-04-09 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Pairs): New data type and procedure + description. + (Lists): Added new subsections for grouping the list procedures. + (Hooks): Added new nodes for hook subsections. + (String Syntax): New node, factoring out read syntax. + (Strings): Some blurb about allowed characters, zero-termination + etc. + (Keywords): Added menu descriptions. + +2001-04-08 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-indices.texi (R5RS Index): Print index `rn', not `r5'. + + * guile.texi: The index formerly known as `r5' is now called `rn'. + + * scheme-utility.texi, scheme-procedures.texi, scheme-io.texi, + scheme-evaluation.texi, scheme-control.texi, scheme-data.texi: + Changed all @r5index entries to @rnindex. + +2001-04-06 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Hooks): Added hook description and + constraints. + +2001-04-06 Thien-Thi Nguyen <ttn@revel.glug.org> + + * scheme-scheduling.texi (Higher level thread + procedures): Replace some instances of `@var' with `@code'. + + * scheme-scheduling.texi (Higher level thread + procedures): Rewrite. + +2001-04-04 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Alphabetic Case Mapping), + (String Comparison): Rearranged function order. + (Vectors): Reorganized, new introductory text, docs about read + syntax. + +2001-04-03 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-options.texi, scheme-procedures.texi, + scheme-modules.texi, scheme-memory.texi, scheme-control.texi, + scheme-utility.texi, scheme-io.texi, scheme-evaluation.texi, + scheme-data.texi: Removed a lot of ARGFIXME's after tweaking + docstrings and C source. + + * new-docstrings.texi, scheme-io.texi, scheme-data.texi, + posix.texi, scheme-control.texi, scheme-evaluation.texi, + scheme-memory.texi, scheme-procedures.texi, scheme-modules.texi, + scheme-scheduling.texi: Automated docstring merging. + +2001-04-02 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi (Immediates vs. Non-immediates): Update + out-of-date documentation. (Thanks to Dirk Herrmann for the + report!) + (Immediates vs Non-immediates): Renamed without the dot, since the + dot causes `info' not to be able to display this node! + + * Makefile.am (guile_TEXINFOS): Add in a few more source files + that had got left out. + +2001-03-30 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-reading.texi (Further Reading): Add bullets to further + reading list. + + * gh.texi: Insert page break before chapter. Remove page breaks + within the chapter. + + * Makefile.am: Add script-getopt.texi. + + * guile.texi (Top): Include and link to new script-getopt.texi + chapter. + + * script-getopt.texi: New chapter on command line handling. + (Written and contributed by Martin Grabmueller, revised by me.) + + * intro.texi (Modules and Extensions): Fix typo. + +2001-03-27 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Strings): Reorganized the whole `Strings' + section and wrote introductory material for each new subsection. + +2001-03-25 Marius Vollmer <mvo@zagadka.ping.de> + + * intro.texi (Modules and Extensions): Some short text about + dynamic libraries and modules. + +2001-03-23 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi (Writing Extensions for Guile), scheme-data.texi + (Lists): Fix typos. + + * guile-tut.texi, ChangeLog-guile-doc-tutorial: Added to CVS. It + seems that I somehow missed these out when I moved everything from + guile-doc to guile-core. + + * posix.texi, scheme-data.texi, scheme-evaluation.texi, + scheme-io.texi, scheme-memory.texi: Automatic docstring updates. + + * new-docstrings.texi: New file. Holds snarfed docstrings that + have not yet been incorporated into the reference manual. + +2001-03-20 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-options.texi (Evaluator options): Added evaluator + options, corrected docs for evaluator trap options. + + * scheme-evaluation.texi (Scheme Read): New docs for read-options, + read-enable, read-disable and read-set! and cross references to + option nodes. + (Evaluator Options): New docs for eval-options, eval-enable, + eval-disable and eval-set!, traps, trap-enable, trap-disable and + trap-set! and cross references to option nodes. + (Evaluator Behaviour): Renamed node from `Evaluator options' to + avoid name clash. + + * scheme-io.texi (String Ports): Added docs for SRFI-6 procedures. + (Void Ports): Corrected introductory comment. + +2001-03-16 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * scheme-data.texi (Arithmetic): Documented the arithmetic + procedures. + (Integer Operations): Added documentation. + (Comparison): Added documentation. + (Complex): Added documentation. + (Symbols and Variables): Comment out `builtin-bindings', which is + removed according to NEWS. + (Pairs): Added documentation. + + * scheme-io.texi: Added R5RS index entries for all R5RS + procedures. + (File Ports): New docs for `call-with-input-file', + `call-with-output-file', `with-input-from-file', + `with-output-to-file', `with-error-to-file'. + + * scheme-control.texi, scheme-utility.texi, + * scheme-procedures.texi: Added R5RS index entries for all R5RS + procedures. + + * scheme-evaluation.texi (Fly Evaluation): Added documentation for + `apply'. Added R5RS index entries for all R5RS procedures. + + * scheme-data.texi: Added R5RS index entries for all R5RS + procedures. Removed R5RS index entries for `ass{q,v,occ}-set!'. + Removed explicit entries into the function entries. They are + automagic. + (Vectors): Added documentation for `make-vector', `vector-ref' and + `vector-set!'. + +2001-03-12 Marius Vollmer <mvo@zagadka.ping.de> + + * intro.texi: Changed to reflect current practice better. Added + stuff about writing Guile Extensions (aka dynamically loaded + shared libraries). + +2001-03-09 Mikael Djurfeldt <mdj@linnaeus.mit.edu> + + * goops.texi (VERSION): Bumped to version 0.3. + + * goops-tutorial.texi, goops.texi: Updated to reflect new + define-method syntax. + +2001-03-09 Neil Jerram <neil@ossau.uklinux.net> + + * Makefile.am: Change HTML to HTMLDOC, now that we're part of a + wider distribution. + + Moving documentation files from guile-doc and guile-doc into + guile-core/doc: + + * env.texi, indices.texi, mbapi.texi, mltext.texi, scripts.texi, + scsh.texi, tcltk.texi, hierarchy.txt, scheme-indices.texi, + slib.texi, deprecated.texi, scheme-binding.texi, appendices.texi, + scheme-intro.texi, goops.texi, extend.texi, gh.texi, intro.texi, + preface.texi, scm.texi, goops-tutorial.texi, hierarchy.eps, + r4rs.texi, r5rs.texi, texinfo.tex, scheme-reading.texi, + data-rep.texi, scheme-utility.texi, posix.texi, + scheme-control.texi, scheme-debug.texi, scheme-evaluation.texi, + scheme-io.texi, scheme-memory.texi, scheme-modules.texi, + scheme-options.texi, scheme-procedures.texi, + scheme-scheduling.texi, scheme-translation.texi, guile.texi, + scheme-data.texi, scheme-ideas.texi, expect.texi, + ChangeLog-guile-doc-ref, guile-tut.texi, + ChangeLog-guile-doc-tutorial, AUTHORS, BUGS, NEWS, THANKS: New + files. + + * .cvsignore, Makefile.am, README: Merged. + + * sources: New subdirectory. + + Both the following files are about to be replaced by files from + guile-doc/ref. + + * texinfo.tex: Removed. + + * data-rep.texi: Removed. + +2001-02-15 Neil Jerram <neil@ossau.uklinux.net> + + * README: Explain retirement of `data-rep.texi'. + + * Makefile.am (info_TEXINFOS, data_rep_TEXINFOS): Removed. + + * data-rep.texi: Replace this copy of data-rep.texi with a notice + indicating that it has been retired. The master copy of + data-rep.texi is at guile-doc/ref/data-rep.texi. + +2001-02-04 Marius Vollmer <mvo@zagadka.ping.de> + + * data-rep.texi: Use SCM_SMOB_DATA instead of SCM_CDR. Also + things like SCM_SMOB_PREDICATE and SCM_NEWSMOB. Thanks to Dale + P. Smith! + +2000-10-25 Mikael Djurfeldt <mdj@linnaeus.mit.edu> + + * mop.text: Preliminary documentation of the GOOPS meta object + protocol. + +2000-07-28 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi (Garbage Collection): Fix "accomodate" spelling + mistake. + +2000-06-30 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * data-rep.tex: Removed documentation for SCM_OUTOFRANGE. + +2000-06-20 Mikael Djurfeldt <mdj@thalamus.nada.kth.se> + + * data-rep.texi: Center discussion around the standard interface + for smob type creation (scm_make_smob_type) and warn about the + ongoing discussion which may result in deprecating + scm_make_smob_type_mfpe in next release of Guile. + +2000-05-15 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * data-rep.texi: Updated the macro names for operating on + characters. + +2000-03-22 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * api.txt: Added a first attempt for a description of the newly + designed low level API. + +2000-01-31 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (version.texi): Override automake's rule for + version.texi so that it gets created even in non-maintainer-mode. + +Thu Jan 20 13:00:18 2000 Greg J. Badros <gjb@cs.washington.edu> + + * version.texi, stamp-vti: Removed -- these are auto-generated. + +2000-01-12 Mikael Djurfeldt <mdj@mdj.nada.kth.se> + + * Makefile.am (dist-hook): Updated to include oldfmt.c in + distribution archive. + + * README: Updated with note about oldfmt.c. + + * oldfmt.c: New file: Used by application writers to adapt to + new-style error format strings. + +1999-12-06 Gary Houston <ghouston@freewire.co.uk> + + * data-rep.texi: change dircategory to match change in guile-doc + and scm. + +1999-10-05 Jim Blandy <jimb@savonarola.red-bean.com> + + * Makefile.in: Deleted from CVS repository. Run the autogen.sh + script to create generated files like this one. + +1999-09-11 Jim Blandy <jimb@savonarola.red-bean.com> + + * Makefile.in: Regenerated. + +Fri Jun 25 22:21:43 1999 Greg Badros <gjb@cs.washington.edu> + + * data-rep.texi: Updated SMOB docs to talk about + scm_make_smob_type_mfpe, SCM_RETURN_NEWSMOB, SCM_NEWSMOB function + and macros. + +1999-04-17 Jim Blandy <jimb@savonarola.red-bean.com> + + * Makefile.in: Regenerated. + +1998-10-19 Jim Blandy <jimb@zwingli.cygnus.com> + + * COPYING: New file. + * Makefile.in: Regenerated. + + * Makefile.am (EXAMPLE_SMOB_FILES): List example-smob/COPYING. + * Makefile.in: Regenerated. + +1998-10-16 Jim Blandy <jimb@zwingli.cygnus.com> + + * Makefile.in: Regenerated, after change to qthreads.m4. + +1998-10-15 Jim Blandy <jimb@zwingli.cygnus.com> + + * stamp-vti: Regenerated. + + * hacks.el: Some handy helper functions for working on the manual. + + * data-rep.texi: Extended to accomodate a full running example, + provided with the manual. + * example-smob: A new subdirectory, containing example files for + the manual chapter on smobs. + * Makefile.am (EXAMPLE_SMOB_FILES, dist-hook): New variable and + target, to get the example-smob directory into the distribution. + * Makefile.in: Regenerated. + +1998-10-08 Jim Blandy <jimb@zwingli.cygnus.com> + + * .cvsignore: New file, containing data-rep.info. I'm not sure + whether we want to check this file into CVS, because it's + generated; if you find compelling reasons it should be, let me + know. + +1998-10-07 Jim Blandy <jimb@zwingli.cygnus.com> + + * New directory for documentation. + * README: New file. + * data-rep.texi: It's not a real manual, but it's better than + nothing. + * Makefile.am, Makefile.in, data-rep.info, data-rep.texi, + mdate-sh, stamp-vti, texinfo.tex, version.texi: The usual support + files. diff --git a/doc/ChangeLog-guile-doc b/doc/ChangeLog-guile-doc new file mode 100644 index 000000000..74ce49b55 --- /dev/null +++ b/doc/ChangeLog-guile-doc @@ -0,0 +1,48 @@ +2001-02-15 Neil Jerram <neil@ossau.uklinux.net> + + * sources/data-rep.texi: Removed. (ref/data-rep.texi is now the + current version of this essay.) + +2001-01-26 Neil Jerram <neil@ossau.uklinux.net> + + * configure.in: Only check for `texi2html' program if HTML is + enabled, and explain where to get `texi2html' from if the check + fails. + + * configure.in, Makefile.am, ref/Makefile.am, + tutorial/Makefile.am: Clean up Makefile.am's and support + (configurable) building of HTML documentation in addition to + Info. Thanks to Steve Tell for the patch on which these changes + were based. + +2000-10-14 Neil Jerram <neil@ossau.uklinux.net> + + * sources/data-rep.texi: Merged a lot of changes from + guile-core/doc/data-rep.texi. + +2000-08-07 Neil Jerram <neil@ossau.uklinux.net> + + * configure.in, configure: Advance version number to 1.4. + +2000-07-28 Neil Jerram <neil@ossau.uklinux.net> + + * sources/data-rep.texi (Garbage Collection): Fix "accomodate" + spelling mistake. + +1998-07-27 Mark Galassi <rosalia@cygnus.com> + + * simple test + +1998-04-13 Marius Vollmer <mvo@zagadka.ping.de> + + Have "make dist" include the sources directory: + * Makefile.am: Added "sources" directory to SUBDIRS. + * sources/Makefile.am: New file. + * configure.in: Added "sources/Makefile" to AC_OUTPUT. + +Sun Jun 22 18:38:28 1997 Tim Pierce <twp@twp.tezcat.com> + + New documentation module. + + + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 000000000..f1c694551 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,33 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 1998, 2002, 2006, 2008, 2009, 2010, 2014 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE is free software; you can redistribute it and/or modify it +## under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 3, or +## (at your option) any later version. +## +## GUILE is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with GUILE; see the file COPYING.LESSER. If not, +## write to the Free Software Foundation, Inc., 51 Franklin Street, +## Fifth Floor, Boston, MA 02110-1301 USA + +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = ref r5rs + +dist_man1_MANS = guile.1 + +EXTRA_DIST = groupings.alist ChangeLog-2008 # guile-api.alist + +include $(top_srcdir)/am/maintainer-dirs +guile-api.alist: guile-api.alist-FORCE + ( cd $(top_builddir) ; $(mscripts)/update-guile-api.alist ) +guile-api.alist-FORCE: diff --git a/doc/NEWS b/doc/NEWS new file mode 100644 index 000000000..67c558e7c --- /dev/null +++ b/doc/NEWS @@ -0,0 +1,44 @@ +Guile-doc NEWS --- history of user-visible changes. -*- text -*- +Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. +See the end for copying conditions. + + +Changes since Guile 1.3.4: + +* It's now possible to build HTML documentation as well as Info + +The guile-doc distribution now supports building HTML versions of the +Guile tutorial and reference manual, in addition to the standard Info +documentation. To enable this, include the `--enable-html' option +when you run `./configure': + + ./configure --enable-html + +HTML documentation is installed in $(prefix)/html/guile-$(VERSION). + + +Changes since Guile 1.0 (Sun 5 Jan 1997): + +* The current documentation approach, recommended by Jim Blandy, is to +have: (*) a tutorial with the pedagogical style of guile-user, and a +non-dry reference manual in the style of the most excellent GNU libc +reference manual: the reference manual should be complete, but at the +same time it should have an introductory screen for each major topic, +which can be referenced if the user goes "up" a level in the info +documentation. + + +Copyright information: + +Copyright (C) 1996,1997, 2006 Free Software Foundation, Inc. + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + diff --git a/doc/README b/doc/README new file mode 100644 index 000000000..75c1f7fd6 --- /dev/null +++ b/doc/README @@ -0,0 +1,25 @@ +This directory contains documentation on the Guile core. -*-text-*- + +The documentation consists of the following manuals. + +- The Guile Tutorial (guile-tut.texi) contains a tutorial introduction + to using Guile. + +- The Guile Reference Manual (guile.texi) contains (or is intended to + contain) reference documentation on all aspects of Guile. + +- The Revised^5 Report on the Algorithmic Language Scheme (r5rs.texi). + +Please be aware that this is all very much work in progress (apart +from the Revised^5 Report). Bug reports and contributions are +welcome! + +The `sources' directory includes some stuff relevant to the Guile +reference manual, and which may eventually be folded in to it. It's +not immediately relevant, however, which is why it's not in this +directory. + +The Revised^4 Report (r4rs.texi) is no longer in this distribution, as +it is completely superseded by the Revised^5 Report. If you need to +consult R4RS, it is still widely available, for example at +http://www-swiss.ai.mit.edu/projects/info/SchemeDocs/r4rs/. diff --git a/doc/THANKS b/doc/THANKS new file mode 100644 index 000000000..53cff29f4 --- /dev/null +++ b/doc/THANKS @@ -0,0 +1,19 @@ +Many thanks to the following people for contributing to the Guile +manuals! + +Proofreading, bug reports and patches from: + Chris Bitmead +Christopher Cramer + Marcus Daniels + Dirk Herrmann + Dale P. Smith + Steve Tell + Lee Thomas + Masao Uebayashi + Joel Weber + Keith Wright + +New entries from: + Per Bothner + Martin Grabmueller + Thien Thi Nguyen diff --git a/doc/gendocs_template b/doc/gendocs_template new file mode 100644 index 000000000..178f6cb4c --- /dev/null +++ b/doc/gendocs_template @@ -0,0 +1,91 @@ +<!--#include virtual="/server/header.html" --> +<!-- Parent-Version: 1.77 --> +<title>%%TITLE%% - GNU Project - Free Software Foundation</title> +<!--#include virtual="/server/banner.html" --> +<h2>%%TITLE%%</h2> + +<address>Free Software Foundation</address> +<address>last updated %%DATE%%</address> + +<p>This manual (%%PACKAGE%%) is available in the following formats:</p> + +<ul> +<li><a href="%%PACKAGE%%.html">HTML + (%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li> +<li><a href="html_node/index.html">HTML</a> - with one web page per + node.</li> +%%IF HTML_SECTION%% +<li><a href="html_section/index.html">HTML</a> - with one web page per + section.</li> +%%ENDIF HTML_SECTION%% +%%IF HTML_CHAPTER%% +<li><a href="html_chapter/index.html">HTML</a> - with one web page per + chapter.</li> +%%ENDIF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.html.gz">HTML compressed + (%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on + one web page.</li> +<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed + (%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per node.</li> +%%IF HTML_SECTION%% +<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed + (%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per section.</li> +%%ENDIF HTML_SECTION%% +%%IF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed + (%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per chapter.</li> +%%ENDIF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.info.tar.gz">Info document + (%%INFO_TGZ_SIZE%%K bytes gzipped tar file)</a>.</li> +<li><a href="%%PACKAGE%%.txt">ASCII text + (%%ASCII_SIZE%%K bytes)</a>.</li> +<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed + (%%ASCII_GZ_SIZE%%K bytes gzipped)</a>.</li> +<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file + (%%DVI_GZ_SIZE%%K bytes gzipped)</a>.</li> +<li><a href="%%PACKAGE%%.pdf">PDF file + (%%PDF_SIZE%%K bytes)</a>.</li> +<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source + (%%TEXI_TGZ_SIZE%%K bytes gzipped tar file).</a></li> +</ul> + +<p>You can <a href="http://shop.fsf.org/">buy printed copies of +some manuals</a> (among other items) from the Free Software Foundation; +this helps support FSF activities.</p> + +<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%% +script</a>.)</p> + +<!-- If needed, change the copyright block at the bottom. In general, + all pages on the GNU web server should have the section about + verbatim copying. Please do NOT remove this without talking + with the webmasters first. + Please make sure the copyright date is consistent with the document + and that it is like this: "2001, 2002", not this: "2001-2002". --> +</div><!-- for id="content", starts in the include above --> +<!--#include virtual="/server/footer.html" --> +<div id="footer"> +<div class="unprintable"> + +<p>Please send general FSF & GNU inquiries to +<a href="mailto:gnu@gnu.org"><gnu@gnu.org></a>. +There are also <a href="/contact/">other ways to contact</a> +the FSF. Broken links and other corrections or suggestions can be sent +to <a href="mailto:%%EMAIL%%"><%%EMAIL%%></a>.</p> +</div> + +<p>Copyright © 2017 Free Software Foundation, Inc.</p> + +<p>This page is licensed under a <a rel="license" +href="http://creativecommons.org/licenses/by-nd/3.0/us/">Creative +Commons Attribution-NoDerivs 3.0 United States License</a>.</p> + +<!--#include virtual="/server/bottom-notes.html" --> + +</div> +</div> +</body> +</html> diff --git a/doc/gendocs_template_min b/doc/gendocs_template_min new file mode 100644 index 000000000..112fa3bfb --- /dev/null +++ b/doc/gendocs_template_min @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + +<head> +<title>%%TITLE%% - GNU Project - Free Software Foundation</title> +<meta http-equiv="content-type" content='text/html; charset=utf-8' /> +<link rel="stylesheet" type="text/css" href="/gnu.css" /> +</head> + +<body> + +<h3>%%TITLE%%</h3> + +<address>Free Software Foundation</address> +<address>last updated %%DATE%%</address> +<p> +<a href="/graphics/gnu-head.jpg"> + <img src="/graphics/gnu-head-sm.jpg" + alt=" [image of the head of a GNU] " width="129" height="122"/> +</a> +</p> +<hr /> + +<p>This manual (%%PACKAGE%%) is available in the following formats:</p> + +<ul> +<li><a href="%%PACKAGE%%.html">HTML + (%%HTML_MONO_SIZE%%K bytes)</a> - entirely on one web page.</li> +<li><a href="html_node/index.html">HTML</a> - with one web page per + node.</li> +%%IF HTML_SECTION%% +<li><a href="html_section/index.html">HTML</a> - with one web page per + section.</li> +%%ENDIF HTML_SECTION%% +%%IF HTML_CHAPTER%% +<li><a href="html_chapter/index.html">HTML</a> - with one web page per + chapter.</li> +%%ENDIF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.html.gz">HTML compressed + (%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on + one web page.</li> +<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed + (%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per node.</li> +%%IF HTML_SECTION%% +<li><a href="%%PACKAGE%%.html_section.tar.gz">HTML compressed + (%%HTML_SECTION_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per section.</li> +%%ENDIF HTML_SECTION%% +%%IF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.html_chapter.tar.gz">HTML compressed + (%%HTML_CHAPTER_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per chapter.</li> +%%ENDIF HTML_CHAPTER%% +<li><a href="%%PACKAGE%%.info.tar.gz">Info document + (%%INFO_TGZ_SIZE%%K bytes gzipped tar file)</a>.</li> +<li><a href="%%PACKAGE%%.txt">ASCII text + (%%ASCII_SIZE%%K bytes)</a>.</li> +<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed + (%%ASCII_GZ_SIZE%%K bytes gzipped)</a>.</li> +<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file + (%%DVI_GZ_SIZE%%K bytes gzipped)</a>.</li> +<li><a href="%%PACKAGE%%.pdf">PDF file + (%%PDF_SIZE%%K bytes)</a>.</li> +<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source + (%%TEXI_TGZ_SIZE%%K bytes gzipped tar file).</a></li> +</ul> + +<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%% +script</a>.)</p> + +<div id="footer" class="copyright"> + +<p>Please send general FSF & GNU inquiries to +<a href="mailto:gnu@gnu.org"><gnu@gnu.org></a>. +There are also <a href="/contact/">other ways to contact</a> +the FSF. Broken links and other corrections or suggestions can be sent +to <a href="mailto:%%EMAIL%%"><%%EMAIL%%></a>.</p> +</div> + +<p>Copyright © 2017 Free Software Foundation, Inc.</p> + +<p>This page is licensed under a <a rel="license" +href="http://creativecommons.org/licenses/by-nd/3.0/us/">Creative +Commons Attribution-NoDerivs 3.0 United States License</a>.</p> + +<!--#include virtual="/server/bottom-notes.html" --> + +</div> +</body> +</html> diff --git a/doc/goops.mail b/doc/goops.mail new file mode 100644 index 000000000..305e80403 --- /dev/null +++ b/doc/goops.mail @@ -0,0 +1,78 @@ +From: Mikael Djurfeldt <mdj@mdj.nada.kth.se> +Subject: Re: After GOOPS integration: Computation with native types! +To: Keisuke Nishida <kxn30@po.cwru.edu> +Cc: djurfeldt@nada.kth.se, guile@sourceware.cygnus.com +Cc: djurfeldt@nada.kth.se +Date: 17 Aug 2000 03:01:13 +0200 + +Keisuke Nishida <kxn30@po.cwru.edu> writes: + +> Do I need to include some special feature in my VM? Hmm, but maybe +> I shouldn't do that now... + +Probably not, so I probably shouldn't answer, but... :) + +You'll need to include some extremely efficient mechanism to do +multi-method dispatch. The SCM_IM_DISPATCH form, with its +implementation at line 2250 in eval.c, is the current basis for +efficient dispatch in GOOPS. + +I think we should develop a new instruction for the VM which +corresponds to the SCM_IM_DISPATCH form. + +This form serves both the purpose to map argument types to the correct +code, and as a cache of compiled methods. + +Notice that I talk about cmethods below, not methods. In GOOPS, the +GF has a set of methods, but each method has a "code-table" mapping +argument types to code compiled for those particular concrete types. +(So, in essence, GOOPS methods abstractly do a deeper level of type +dispatch.) + +The SCM_IM_DISPATCH form has two shapes, depending on whether we use +sequential search (few cmethods) or hashed lookup (many cmethods). + +Shape 1: + + (#@dispatch args N-SPECIALIZED #((TYPE1 ... ENV FORMALS FORM1 ...) ...) GF) + +Shape 2: + + (#@dispatch args N-SPECIALIZED HASHSET MASK + #((TYPE1 ... ENV FORMALS FORM1 ...) ...) + GF) + +`args' is (I hope!) a now historic obscure optimization. + +N-SPECIALIZED is the maximum number of arguments t do type checking +on. This is used early termination of argument checking where the +already checked arguments are enough to pick out the cmethod. + +The vector is the cache proper. + +During sequential search the argument types are simply checked against +each entry. + +The method for hashed dispatch is described in: + +http://www.parc.xerox.com/csl/groups/sda/publications/papers/Kiczales-Andreas-PCL + +In this method, each class has a hash code. Dispatch means summing +the hash codes for all arguments (up til N-SPECIALIZED) and using the +sum to pick a location in the cache. The cache is sequentially +searched for an argument type match from that point. + +Kiczales introduced a clever method to maximize the probability of a +direct cache hit. We actually have 8 separate sets of hash codes for +all types. The hash set to use is selected specifically per GF and is +optimized to give fastest average hit. + + +What we could try to do as soon as the VM is complete enough is to +represent the cmethods as chunks of byte code. In the current GOOPS +code, the compilation step (which is currently empty) is situated in +`compile-cmethod' in guile-oops/compile.scm. [Apologies for the +terrible code. That particular part was written at Arlanda airport +after a sleepless night (packing luggage, not coding), on my way to +visit Marius (who, BTW, didn't take GOOPS seriously. ;-)] + diff --git a/doc/groupings.alist b/doc/groupings.alist new file mode 100644 index 000000000..a1748196f --- /dev/null +++ b/doc/groupings.alist @@ -0,0 +1,176 @@ +;;; groupings.alist -*-scheme-*- + +;; Copyright (C) 2002, 2006 Free Software Foundation, Inc. +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU Lesser General Public License +;; as published by the Free Software Foundation; either version 3, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this software; see the file COPYING.LESSER. If +;; not, write to the Free Software Foundation, Inc., 51 Franklin +;; Street, Fifth Floor, Boston, MA 02110-1301 USA + +;;; Commentary: + +;; This file describes interface element groupings. +;; See (scripts scan-api) commentary for more info. +;; NOTE: Order matters; put simple ones first, composites after. +;; +;; TODO: Add goops, add math, etc etc. +;; Group `guile-C-API' needs much more serious thought. + +;;; Code: + +( + + ;; Integrity checks + + (C+scheme + (description "in both groups `scheme' and `C' -- should be empty!") + (grok () (lambda (x) + (and (in-group? x 'Scheme) + (in-group? x 'C))))) + + ;; Embedded foreign libraries + + (embedded-libltdl + (description "begins with lt_ -- should become empty over time") + (grok () (lambda (x) + (name-prefix? x "lt_")))) + + ;; By name + + (libguile-internal + (description "begins with scm_i_") + (grok () (lambda (x) + (name-prefix? x "scm_i_")))) + + (gdb + (description "begins with gdb_") + (grok () (lambda (x) + (name-prefix? x "gdb_")))) + + (coop + (description "begins with coop_") + (grok () (lambda (x) + (name-prefix? x "coop_")))) + + (gh + (description "begins with gh_") + (grok () (lambda (x) + (name-prefix? x "gh_")))) + + (g-fdes + (description "begins with g and ends with fds") + (grok () (lambda (x) + (name-prefix? x "g.+fds$")))) + + (r-fdes + (description "begins with r and ends with fds") + (grok () (lambda (x) + (name-prefix? x "r.+fds$")))) + + (scm + (description "begins with scm_") + (grok () (lambda (x) + (name-prefix? x "scm_")))) + + (k + (description "constants") + (grok () (lambda (x) + (name-prefix? x "[_A-Z0-9]+$")))) + + (POSIX + (description "POSIX support") + (members ; from docs + + ;; ports and file descriptors + port-revealed set-port-revealed! fileno port->fdes fdopen fdes->ports + fdes->inport fdes->outport primitive-move->fdes move->fdes + release-port-handle fsync open open-fdes close close-fdes unread-char + unread-string pipe dup->fdes dup->inport dup->outport dup dup->port + duplicate-port redirect-port dup2 port-mode close-all-ports-except + port-for-each setvbuf fcntl flock select + O_RDONLY O_WRONLY O_RDWR O_APPEND O_CREAT _IONBF _IOLBF _IOFBF + F_DUPFD F_GETFD F_SETFD F_GETFL F_SETFL F_GETOWN F_SETOWN FD_CLOEXEC + LOCK_SH LOCK_EX LOCK_UN LOCK_NB + + ;; file system + access? stat lstat readlink chown chmod utime delete-file copy-file + rename-file link symlink mkdir rmdir opendir directory-stream? readdir + rewinddir closedir sync mknod tmpnam mkstemp! dirname basename + R_OK W_OK X_OK F_OK + stat:perms stat:type stat:blocks stat:blksize stat:ctime stat:mtime + stat:atime stat:size stat:rdev stat:gid stat:uid stat:nlink stat:mode + stat:ino stat:dev + + ;; user information + passwd:name passwd:passwd passwd:uid passwd:gid passwd:gecos passwd:dir + passwd:shell group:name group:passwd group:gid group:mem + getpwuid getpwnam name setpwent getpwent endpwent setpw getpw getgrgid + getgrnam setgrent getgrent endgrent setgr getgr cuserid getlogin + + ;; time + tm:sec set-tm:sec tm:min set-tm:min tm:hour set-tm:hour tm:mday set-tm:mday + tm:mon set-tm:mon tm:year set-tm:year tm:wday set-tm:wday tm:yday + set-tm:yday tm:isdst set-tm:isdst tm:gmtoff set-tm:gmtoff tm:zone + set-tm:zone tms:clock tms:utime tms:stime tms:cutime tms:cstime + current-time gettimeofday localtime gmtime mktime tzset strftime strptime + times get-internal-real-time get-internal-run-time + + ;; runtime environment + program-arguments command-line getenv setenv environ putenv + + ;; proceses + chdir getcwd umask chroot getpid getgroups getppid getuid getgid geteuid + getegid setuid setgid seteuid setegid getpgrp setpgid setsid waitpid + status:exit-val status:term-sig status:stop-sig system primitive-exit execl + execlp execle primitive-fork nice setpriority getpriority + WNOHANG WUNTRACED + + ;; signals + kill raise sigaction restore-signals alarm pause sleep usleep setitimer + getitimer SIGHUP SIGINT + + ;; terminals and ptys + isatty? ttyname ctermid tcgetpgrp tcsetpgrp + + ;; pipes -- not included because they are in (ice-9 popen) + + ;; system identification + utsname:sysname utsname:nodename utsname:release utsname:version + utsname:machine uname gethostname sethostname software-type + + ;; locales + setlocale + LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME + + ;; encryption + crypt getpass)) + + (math + (description "math functions") + (members $abs $acos $acosh $asin $asinh $atan $atan2 $atanh $cos $cosh + $exp $expt $log $sin $sinh $sqrt $tan $tanh)) + + ;; By composition (these must be AFTER their constituent groupings) + + (guile-C-API + (description "the official guile API available to C programs") + (grok () (lambda (x) + (and (in-group? x 'C) + (or (in-group? x 'gh) + (in-group? x 'coop) + (in-group? x 'gdb)))))) + + ;; Add new grouping descriptions here. + ) + +;;; groupings.alist ends here diff --git a/doc/guile-api.alist b/doc/guile-api.alist new file mode 100644 index 000000000..78d3a5cd0 --- /dev/null +++ b/doc/guile-api.alist @@ -0,0 +1,3217 @@ +;;; generated 2002-05-12 05:25:39 UTC by scan-api -- do not edit! + +( +(meta + (GUILE_LOAD_PATH . "") + (LTDL_LIBRARY_PATH . "") + (guile . "pre-inst-guile") + (libguileinterface . "15:0:0") + (sofile . "libguile/.libs/libguile.so.15.0.0") + (groups C+scheme embedded-libltdl libguile-internal gdb coop gh g-fdes r-fdes scm k POSIX math guile-C-API Scheme C) +) ;; end of meta +(interface +($abs (groups math Scheme) (scan-data "#<primitive-procedure $abs>")) +($acos (groups math Scheme) (scan-data "#<primitive-procedure $acos>")) +($acosh (groups math Scheme) (scan-data "#<primitive-procedure $acosh>")) +($asin (groups math Scheme) (scan-data "#<primitive-procedure $asin>")) +($asinh (groups math Scheme) (scan-data "#<primitive-procedure $asinh>")) +($atan (groups math Scheme) (scan-data "#<primitive-procedure $atan>")) +($atan2 (groups math Scheme) (scan-data "#<primitive-procedure $atan2>")) +($atanh (groups math Scheme) (scan-data "#<primitive-procedure $atanh>")) +($cos (groups math Scheme) (scan-data "#<primitive-procedure $cos>")) +($cosh (groups math Scheme) (scan-data "#<primitive-procedure $cosh>")) +($exp (groups math Scheme) (scan-data "#<primitive-procedure $exp>")) +($expt (groups math Scheme) (scan-data "#<primitive-procedure $expt>")) +($log (groups math Scheme) (scan-data "#<primitive-procedure $log>")) +($sin (groups math Scheme) (scan-data "#<primitive-procedure $sin>")) +($sinh (groups math Scheme) (scan-data "#<primitive-procedure $sinh>")) +($sqrt (groups math Scheme) (scan-data "#<primitive-procedure $sqrt>")) +($tan (groups math Scheme) (scan-data "#<primitive-procedure $tan>")) +($tanh (groups math Scheme) (scan-data "#<primitive-procedure $tanh>")) +(%cond-expand-features (groups Scheme) (scan-data "")) +(%cond-expand-table (groups Scheme) (scan-data "")) +(%deliver-signals (groups Scheme) (scan-data "#<primitive-procedure %deliver-signals>")) +(%get-pre-modules-obarray (groups Scheme) (scan-data "#<primitive-procedure %get-pre-modules-obarray>")) +(%guile-build-info (groups Scheme) (scan-data "")) +(%init-goops-builtins (groups Scheme) (scan-data "#<primitive-procedure %init-goops-builtins>")) +(%init-rdelim-builtins (groups Scheme) (scan-data "#<primitive-procedure %init-rdelim-builtins>")) +(%init-rw-builtins (groups Scheme) (scan-data "#<primitive-procedure %init-rw-builtins>")) +(%library-dir (groups Scheme) (scan-data "#<primitive-procedure %library-dir>")) +(%load-announce (groups Scheme) (scan-data "#<procedure %load-announce (file)>")) +(%load-extensions (groups Scheme) (scan-data "")) +(%load-hook (groups Scheme) (scan-data "#<procedure %load-announce (file)>")) +(%load-path (groups Scheme) (scan-data "")) +(%load-verbosely (groups Scheme) (scan-data "")) +(%make-void-port (groups Scheme) (scan-data "#<primitive-procedure %make-void-port>")) +(%module-public-interface (groups Scheme) (scan-data "")) +(%nil (groups Scheme) (scan-data "")) +(%package-data-dir (groups Scheme) (scan-data "#<primitive-procedure %package-data-dir>")) +(%print-module (groups Scheme) (scan-data "#<procedure %print-module (mod port)>")) +(%print-values (groups Scheme) (scan-data "#<primitive-procedure %print-values>")) +(%search-load-path (groups Scheme) (scan-data "#<primitive-procedure %search-load-path>")) +(%site-dir (groups Scheme) (scan-data "#<primitive-procedure %site-dir>")) +(* (groups Scheme) (scan-data "#<primitive-procedure *>")) +(*features* (groups Scheme) (scan-data "")) +(*null-device* (groups Scheme) (scan-data "")) +(*random-state* (groups Scheme) (scan-data "")) +(*unspecified* (groups Scheme) (scan-data "")) +(+ (groups Scheme) (scan-data "#<primitive-procedure +>")) +(- (groups Scheme) (scan-data "#<primitive-procedure ->")) +(->bool (groups Scheme) (scan-data "#<procedure ->bool (x)>")) +(/ (groups Scheme) (scan-data "#<primitive-procedure />")) +(1+ (groups Scheme) (scan-data "#<procedure 1+ (n)>")) +(1- (groups Scheme) (scan-data "#<procedure 1- (n)>")) +(< (groups Scheme) (scan-data "#<primitive-procedure <>")) +(<= (groups Scheme) (scan-data "#<primitive-procedure <=>")) +(<class> (groups Scheme) (scan-data "")) +(<entity> (groups Scheme) (scan-data "")) +(<operator-class> (groups Scheme) (scan-data "")) +(= (groups Scheme) (scan-data "#<primitive-procedure =>")) +(> (groups Scheme) (scan-data "#<primitive-procedure >>")) +(>= (groups Scheme) (scan-data "#<primitive-procedure >=>")) +(@apply (groups Scheme) (scan-data "")) +(@bind (groups Scheme) (scan-data "")) +(@call-with-current-continuation (groups Scheme) (scan-data "")) +(@call-with-values (groups Scheme) (scan-data "")) +(@fop (groups Scheme) (scan-data "")) +(AF_INET (groups k Scheme) (scan-data "")) +(AF_INET6 (groups k Scheme) (scan-data "")) +(AF_UNIX (groups k Scheme) (scan-data "")) +(AF_UNSPEC (groups k Scheme) (scan-data "")) +(E2BIG (groups k Scheme) (scan-data "")) +(EACCES (groups k Scheme) (scan-data "")) +(EADDRINUSE (groups k Scheme) (scan-data "")) +(EADDRNOTAVAIL (groups k Scheme) (scan-data "")) +(EADV (groups k Scheme) (scan-data "")) +(EAFNOSUPPORT (groups k Scheme) (scan-data "")) +(EAGAIN (groups k Scheme) (scan-data "")) +(EALREADY (groups k Scheme) (scan-data "")) +(EBADE (groups k Scheme) (scan-data "")) +(EBADF (groups k Scheme) (scan-data "")) +(EBADFD (groups k Scheme) (scan-data "")) +(EBADMSG (groups k Scheme) (scan-data "")) +(EBADR (groups k Scheme) (scan-data "")) +(EBADRQC (groups k Scheme) (scan-data "")) +(EBADSLT (groups k Scheme) (scan-data "")) +(EBFONT (groups k Scheme) (scan-data "")) +(EBUSY (groups k Scheme) (scan-data "")) +(ECHILD (groups k Scheme) (scan-data "")) +(ECHRNG (groups k Scheme) (scan-data "")) +(ECOMM (groups k Scheme) (scan-data "")) +(ECONNABORTED (groups k Scheme) (scan-data "")) +(ECONNREFUSED (groups k Scheme) (scan-data "")) +(ECONNRESET (groups k Scheme) (scan-data "")) +(EDEADLK (groups k Scheme) (scan-data "")) +(EDEADLOCK (groups k Scheme) (scan-data "")) +(EDESTADDRREQ (groups k Scheme) (scan-data "")) +(EDOM (groups k Scheme) (scan-data "")) +(EDOTDOT (groups k Scheme) (scan-data "")) +(EDQUOT (groups k Scheme) (scan-data "")) +(EEXIST (groups k Scheme) (scan-data "")) +(EFAULT (groups k Scheme) (scan-data "")) +(EFBIG (groups k Scheme) (scan-data "")) +(EHOSTDOWN (groups k Scheme) (scan-data "")) +(EHOSTUNREACH (groups k Scheme) (scan-data "")) +(EIDRM (groups k Scheme) (scan-data "")) +(EILSEQ (groups k Scheme) (scan-data "")) +(EINPROGRESS (groups k Scheme) (scan-data "")) +(EINTR (groups k Scheme) (scan-data "")) +(EINVAL (groups k Scheme) (scan-data "")) +(EIO (groups k Scheme) (scan-data "")) +(EISCONN (groups k Scheme) (scan-data "")) +(EISDIR (groups k Scheme) (scan-data "")) +(EISNAM (groups k Scheme) (scan-data "")) +(EL2HLT (groups k Scheme) (scan-data "")) +(EL2NSYNC (groups k Scheme) (scan-data "")) +(EL3HLT (groups k Scheme) (scan-data "")) +(EL3RST (groups k Scheme) (scan-data "")) +(ELIBACC (groups k Scheme) (scan-data "")) +(ELIBBAD (groups k Scheme) (scan-data "")) +(ELIBEXEC (groups k Scheme) (scan-data "")) +(ELIBMAX (groups k Scheme) (scan-data "")) +(ELIBSCN (groups k Scheme) (scan-data "")) +(ELNRNG (groups k Scheme) (scan-data "")) +(ELOOP (groups k Scheme) (scan-data "")) +(EMFILE (groups k Scheme) (scan-data "")) +(EMLINK (groups k Scheme) (scan-data "")) +(EMSGSIZE (groups k Scheme) (scan-data "")) +(EMULTIHOP (groups k Scheme) (scan-data "")) +(ENAMETOOLONG (groups k Scheme) (scan-data "")) +(ENAVAIL (groups k Scheme) (scan-data "")) +(ENETDOWN (groups k Scheme) (scan-data "")) +(ENETRESET (groups k Scheme) (scan-data "")) +(ENETUNREACH (groups k Scheme) (scan-data "")) +(ENFILE (groups k Scheme) (scan-data "")) +(ENOANO (groups k Scheme) (scan-data "")) +(ENOBUFS (groups k Scheme) (scan-data "")) +(ENOCSI (groups k Scheme) (scan-data "")) +(ENODATA (groups k Scheme) (scan-data "")) +(ENODEV (groups k Scheme) (scan-data "")) +(ENOENT (groups k Scheme) (scan-data "")) +(ENOEXEC (groups k Scheme) (scan-data "")) +(ENOLCK (groups k Scheme) (scan-data "")) +(ENOLINK (groups k Scheme) (scan-data "")) +(ENOMEM (groups k Scheme) (scan-data "")) +(ENOMSG (groups k Scheme) (scan-data "")) +(ENONET (groups k Scheme) (scan-data "")) +(ENOPKG (groups k Scheme) (scan-data "")) +(ENOPROTOOPT (groups k Scheme) (scan-data "")) +(ENOSPC (groups k Scheme) (scan-data "")) +(ENOSR (groups k Scheme) (scan-data "")) +(ENOSTR (groups k Scheme) (scan-data "")) +(ENOSYS (groups k Scheme) (scan-data "")) +(ENOTBLK (groups k Scheme) (scan-data "")) +(ENOTCONN (groups k Scheme) (scan-data "")) +(ENOTDIR (groups k Scheme) (scan-data "")) +(ENOTEMPTY (groups k Scheme) (scan-data "")) +(ENOTNAM (groups k Scheme) (scan-data "")) +(ENOTSOCK (groups k Scheme) (scan-data "")) +(ENOTTY (groups k Scheme) (scan-data "")) +(ENOTUNIQ (groups k Scheme) (scan-data "")) +(ENXIO (groups k Scheme) (scan-data "")) +(EOPNOTSUPP (groups k Scheme) (scan-data "")) +(EOVERFLOW (groups k Scheme) (scan-data "")) +(EPERM (groups k Scheme) (scan-data "")) +(EPFNOSUPPORT (groups k Scheme) (scan-data "")) +(EPIPE (groups k Scheme) (scan-data "")) +(EPROTO (groups k Scheme) (scan-data "")) +(EPROTONOSUPPORT (groups k Scheme) (scan-data "")) +(EPROTOTYPE (groups k Scheme) (scan-data "")) +(ERANGE (groups k Scheme) (scan-data "")) +(EREMCHG (groups k Scheme) (scan-data "")) +(EREMOTE (groups k Scheme) (scan-data "")) +(EREMOTEIO (groups k Scheme) (scan-data "")) +(ERESTART (groups k Scheme) (scan-data "")) +(EROFS (groups k Scheme) (scan-data "")) +(ESHUTDOWN (groups k Scheme) (scan-data "")) +(ESOCKTNOSUPPORT (groups k Scheme) (scan-data "")) +(ESPIPE (groups k Scheme) (scan-data "")) +(ESRCH (groups k Scheme) (scan-data "")) +(ESRMNT (groups k Scheme) (scan-data "")) +(ESTALE (groups k Scheme) (scan-data "")) +(ESTRPIPE (groups k Scheme) (scan-data "")) +(ETIME (groups k Scheme) (scan-data "")) +(ETIMEDOUT (groups k Scheme) (scan-data "")) +(ETOOMANYREFS (groups k Scheme) (scan-data "")) +(ETXTBSY (groups k Scheme) (scan-data "")) +(EUCLEAN (groups k Scheme) (scan-data "")) +(EUNATCH (groups k Scheme) (scan-data "")) +(EUSERS (groups k Scheme) (scan-data "")) +(EWOULDBLOCK (groups k Scheme) (scan-data "")) +(EXDEV (groups k Scheme) (scan-data "")) +(EXFULL (groups k Scheme) (scan-data "")) +(FD_CLOEXEC (groups POSIX k Scheme) (scan-data "")) +(F_DUPFD (groups POSIX k Scheme) (scan-data "")) +(F_GETFD (groups POSIX k Scheme) (scan-data "")) +(F_GETFL (groups POSIX k Scheme) (scan-data "")) +(F_GETOWN (groups POSIX k Scheme) (scan-data "")) +(F_OK (groups POSIX k Scheme) (scan-data "")) +(F_SETFD (groups POSIX k Scheme) (scan-data "")) +(F_SETFL (groups POSIX k Scheme) (scan-data "")) +(F_SETOWN (groups POSIX k Scheme) (scan-data "")) +(INADDR_ANY (groups k Scheme) (scan-data "")) +(INADDR_BROADCAST (groups k Scheme) (scan-data "")) +(INADDR_LOOPBACK (groups k Scheme) (scan-data "")) +(INADDR_NONE (groups k Scheme) (scan-data "")) +(ITIMER_PROF (groups k Scheme) (scan-data "")) +(ITIMER_REAL (groups k Scheme) (scan-data "")) +(ITIMER_VIRTUAL (groups k Scheme) (scan-data "")) +(LC_ALL (groups POSIX k Scheme) (scan-data "")) +(LC_COLLATE (groups POSIX k Scheme) (scan-data "")) +(LC_CTYPE (groups POSIX k Scheme) (scan-data "")) +(LC_MESSAGES (groups POSIX k Scheme) (scan-data "")) +(LC_MONETARY (groups POSIX k Scheme) (scan-data "")) +(LC_NUMERIC (groups POSIX k Scheme) (scan-data "")) +(LC_TIME (groups POSIX k Scheme) (scan-data "")) +(LOCK_EX (groups POSIX k Scheme) (scan-data "")) +(LOCK_NB (groups POSIX k Scheme) (scan-data "")) +(LOCK_SH (groups POSIX k Scheme) (scan-data "")) +(LOCK_UN (groups POSIX k Scheme) (scan-data "")) +(MSG_DONTROUTE (groups k Scheme) (scan-data "")) +(MSG_OOB (groups k Scheme) (scan-data "")) +(MSG_PEEK (groups k Scheme) (scan-data "")) +(NSIG (groups k Scheme) (scan-data "")) +(OPEN_BOTH (groups k Scheme) (scan-data "")) +(OPEN_READ (groups k Scheme) (scan-data "")) +(OPEN_WRITE (groups k Scheme) (scan-data "")) +(O_APPEND (groups POSIX k Scheme) (scan-data "")) +(O_CREAT (groups POSIX k Scheme) (scan-data "")) +(O_EXCL (groups k Scheme) (scan-data "")) +(O_NDELAY (groups k Scheme) (scan-data "")) +(O_NOCTTY (groups k Scheme) (scan-data "")) +(O_NONBLOCK (groups k Scheme) (scan-data "")) +(O_RDONLY (groups POSIX k Scheme) (scan-data "")) +(O_RDWR (groups POSIX k Scheme) (scan-data "")) +(O_SYNC (groups k Scheme) (scan-data "")) +(O_TRUNC (groups k Scheme) (scan-data "")) +(O_WRONLY (groups POSIX k Scheme) (scan-data "")) +(PF_INET (groups k Scheme) (scan-data "")) +(PF_INET6 (groups k Scheme) (scan-data "")) +(PF_UNIX (groups k Scheme) (scan-data "")) +(PF_UNSPEC (groups k Scheme) (scan-data "")) +(PIPE_BUF (groups k Scheme) (scan-data "")) +(PRIO_PGRP (groups k Scheme) (scan-data "")) +(PRIO_PROCESS (groups k Scheme) (scan-data "")) +(PRIO_USER (groups k Scheme) (scan-data "")) +(R_OK (groups POSIX k Scheme) (scan-data "")) +(SA_NOCLDSTOP (groups k Scheme) (scan-data "")) +(SA_RESTART (groups k Scheme) (scan-data "")) +(SEEK_CUR (groups k Scheme) (scan-data "")) +(SEEK_END (groups k Scheme) (scan-data "")) +(SEEK_SET (groups k Scheme) (scan-data "")) +(SIGABRT (groups k Scheme) (scan-data "")) +(SIGALRM (groups k Scheme) (scan-data "")) +(SIGBUS (groups k Scheme) (scan-data "")) +(SIGCHLD (groups k Scheme) (scan-data "")) +(SIGCLD (groups k Scheme) (scan-data "")) +(SIGCONT (groups k Scheme) (scan-data "")) +(SIGFPE (groups k Scheme) (scan-data "")) +(SIGHUP (groups POSIX k Scheme) (scan-data "")) +(SIGILL (groups k Scheme) (scan-data "")) +(SIGINT (groups POSIX k Scheme) (scan-data "")) +(SIGIO (groups k Scheme) (scan-data "")) +(SIGIOT (groups k Scheme) (scan-data "")) +(SIGKILL (groups k Scheme) (scan-data "")) +(SIGPIPE (groups k Scheme) (scan-data "")) +(SIGPOLL (groups k Scheme) (scan-data "")) +(SIGPROF (groups k Scheme) (scan-data "")) +(SIGPWR (groups k Scheme) (scan-data "")) +(SIGQUIT (groups k Scheme) (scan-data "")) +(SIGSEGV (groups k Scheme) (scan-data "")) +(SIGSTKFLT (groups k Scheme) (scan-data "")) +(SIGSTOP (groups k Scheme) (scan-data "")) +(SIGTERM (groups k Scheme) (scan-data "")) +(SIGTRAP (groups k Scheme) (scan-data "")) +(SIGTSTP (groups k Scheme) (scan-data "")) +(SIGTTIN (groups k Scheme) (scan-data "")) +(SIGTTOU (groups k Scheme) (scan-data "")) +(SIGUNUSED (groups k Scheme) (scan-data "")) +(SIGURG (groups k Scheme) (scan-data "")) +(SIGUSR1 (groups k Scheme) (scan-data "")) +(SIGUSR2 (groups k Scheme) (scan-data "")) +(SIGVTALRM (groups k Scheme) (scan-data "")) +(SIGWINCH (groups k Scheme) (scan-data "")) +(SIGXCPU (groups k Scheme) (scan-data "")) +(SIGXFSZ (groups k Scheme) (scan-data "")) +(SIG_DFL (groups k Scheme) (scan-data "")) +(SIG_IGN (groups k Scheme) (scan-data "")) +(SOCK_DGRAM (groups k Scheme) (scan-data "")) +(SOCK_RAW (groups k Scheme) (scan-data "")) +(SOCK_STREAM (groups k Scheme) (scan-data "")) +(SOL_IP (groups k Scheme) (scan-data "")) +(SOL_SOCKET (groups k Scheme) (scan-data "")) +(SO_BROADCAST (groups k Scheme) (scan-data "")) +(SO_DEBUG (groups k Scheme) (scan-data "")) +(SO_DONTROUTE (groups k Scheme) (scan-data "")) +(SO_ERROR (groups k Scheme) (scan-data "")) +(SO_KEEPALIVE (groups k Scheme) (scan-data "")) +(SO_LINGER (groups k Scheme) (scan-data "")) +(SO_NO_CHECK (groups k Scheme) (scan-data "")) +(SO_OOBINLINE (groups k Scheme) (scan-data "")) +(SO_PRIORITY (groups k Scheme) (scan-data "")) +(SO_RCVBUF (groups k Scheme) (scan-data "")) +(SO_REUSEADDR (groups k Scheme) (scan-data "")) +(SO_SNDBUF (groups k Scheme) (scan-data "")) +(SO_TYPE (groups k Scheme) (scan-data "")) +(WAIT_ANY (groups k Scheme) (scan-data "")) +(WAIT_MYPGRP (groups k Scheme) (scan-data "")) +(WNOHANG (groups POSIX k Scheme) (scan-data "")) +(WUNTRACED (groups POSIX k Scheme) (scan-data "")) +(W_OK (groups POSIX k Scheme) (scan-data "")) +(X_OK (groups POSIX k Scheme) (scan-data "")) +(_IOFBF (groups POSIX k Scheme) (scan-data "")) +(_IOLBF (groups POSIX k Scheme) (scan-data "")) +(_IONBF (groups POSIX k Scheme) (scan-data "")) +(_fini (groups C) (scan-data T)) +(_init (groups C) (scan-data T)) +(abort-hook (groups Scheme) (scan-data "")) +(abs (groups Scheme) (scan-data "#<primitive-procedure abs>")) +(accept (groups Scheme) (scan-data "#<primitive-procedure accept>")) +(access? (groups POSIX Scheme) (scan-data "#<primitive-procedure access?>")) +(acons (groups Scheme) (scan-data "#<primitive-procedure acons>")) +(acos (groups Scheme) (scan-data "#<procedure acos (z)>")) +(acosh (groups Scheme) (scan-data "#<procedure acosh (z)>")) +(add-hook! (groups Scheme) (scan-data "#<primitive-procedure add-hook!>")) +(after-backtrace-hook (groups Scheme) (scan-data "")) +(after-error-hook (groups Scheme) (scan-data "")) +(after-eval-hook (groups Scheme) (scan-data "")) +(after-gc-hook (groups Scheme) (scan-data "")) +(after-print-hook (groups Scheme) (scan-data "")) +(after-read-hook (groups Scheme) (scan-data "")) +(alarm (groups POSIX Scheme) (scan-data "#<primitive-procedure alarm>")) +(and (groups Scheme) (scan-data "")) +(and-map (groups Scheme) (scan-data "#<procedure and-map (f lst)>")) +(and=> (groups Scheme) (scan-data "#<procedure and=> (value procedure)>")) +(angle (groups Scheme) (scan-data "#<primitive-procedure angle>")) +(app (groups Scheme) (scan-data "")) +(append (groups Scheme) (scan-data "#<primitive-procedure append>")) +(append! (groups Scheme) (scan-data "#<primitive-procedure append!>")) +(apply (groups Scheme) (scan-data "#<procedure apply (fun . args)>")) +(apply-to-args (groups Scheme) (scan-data "#<procedure apply-to-args (args fn)>")) +(apply:nconc2last (groups Scheme) (scan-data "#<primitive-procedure apply:nconc2last>")) +(array->list (groups Scheme) (scan-data "#<primitive-procedure array->list>")) +(array-contents (groups Scheme) (scan-data "#<primitive-procedure array-contents>")) +(array-copy! (groups Scheme) (scan-data "#<primitive-procedure array-copy!>")) +(array-copy-in-order! (groups Scheme) (scan-data "#<primitive-procedure array-copy-in-order!>")) +(array-dimensions (groups Scheme) (scan-data "#<primitive-procedure array-dimensions>")) +(array-equal? (groups Scheme) (scan-data "#<primitive-procedure array-equal?>")) +(array-fill! (groups Scheme) (scan-data "#<primitive-procedure array-fill!>")) +(array-for-each (groups Scheme) (scan-data "#<primitive-procedure array-for-each>")) +(array-in-bounds? (groups Scheme) (scan-data "#<primitive-procedure array-in-bounds?>")) +(array-index-map! (groups Scheme) (scan-data "#<primitive-procedure array-index-map!>")) +(array-map! (groups Scheme) (scan-data "#<primitive-procedure array-map!>")) +(array-map-in-order! (groups Scheme) (scan-data "#<primitive-procedure array-map-in-order!>")) +(array-prototype (groups Scheme) (scan-data "#<primitive-procedure array-prototype>")) +(array-rank (groups Scheme) (scan-data "#<primitive-procedure array-rank>")) +(array-ref (groups Scheme) (scan-data "#<primitive-procedure array-ref>")) +(array-set! (groups Scheme) (scan-data "#<primitive-procedure array-set!>")) +(array-shape (groups Scheme) (scan-data "#<procedure array-shape (a)>")) +(array? (groups Scheme) (scan-data "#<primitive-procedure array?>")) +(ash (groups Scheme) (scan-data "#<primitive-procedure ash>")) +(asin (groups Scheme) (scan-data "#<procedure asin (z)>")) +(asinh (groups Scheme) (scan-data "#<procedure asinh (z)>")) +(assert-defmacro?! (groups Scheme) (scan-data "#<procedure assert-defmacro?! (m)>")) +(assert-load-verbosity (groups Scheme) (scan-data "#<procedure assert-load-verbosity (v)>")) +(assert-repl-print-unspecified (groups Scheme) (scan-data "#<procedure assert-repl-print-unspecified (v)>")) +(assert-repl-silence (groups Scheme) (scan-data "#<procedure assert-repl-silence (v)>")) +(assert-repl-verbosity (groups Scheme) (scan-data "#<procedure assert-repl-verbosity (v)>")) +(assoc (groups Scheme) (scan-data "#<primitive-procedure assoc>")) +(assoc-ref (groups Scheme) (scan-data "#<primitive-procedure assoc-ref>")) +(assoc-remove! (groups Scheme) (scan-data "#<primitive-procedure assoc-remove!>")) +(assoc-set! (groups Scheme) (scan-data "#<primitive-procedure assoc-set!>")) +(assq (groups Scheme) (scan-data "#<primitive-procedure assq>")) +(assq-ref (groups Scheme) (scan-data "#<primitive-procedure assq-ref>")) +(assq-remove! (groups Scheme) (scan-data "#<primitive-procedure assq-remove!>")) +(assq-set! (groups Scheme) (scan-data "#<primitive-procedure assq-set!>")) +(assv (groups Scheme) (scan-data "#<primitive-procedure assv>")) +(assv-ref (groups Scheme) (scan-data "#<primitive-procedure assv-ref>")) +(assv-remove! (groups Scheme) (scan-data "#<primitive-procedure assv-remove!>")) +(assv-set! (groups Scheme) (scan-data "#<primitive-procedure assv-set!>")) +(async (groups Scheme) (scan-data "#<primitive-procedure async>")) +(async-mark (groups Scheme) (scan-data "#<primitive-procedure async-mark>")) +(atan (groups Scheme) (scan-data "#<procedure atan (z . y)>")) +(atanh (groups Scheme) (scan-data "#<procedure atanh (z)>")) +(autoload-done! (groups Scheme) (scan-data "#<procedure autoload-done! (p m)>")) +(autoload-done-or-in-progress? (groups Scheme) (scan-data "#<procedure autoload-done-or-in-progress? (p m)>")) +(autoload-in-progress! (groups Scheme) (scan-data "#<procedure autoload-in-progress! (p m)>")) +(autoloads-done (groups Scheme) (scan-data "")) +(autoloads-in-progress (groups Scheme) (scan-data "")) +(backtrace (groups Scheme) (scan-data "#<primitive-procedure backtrace>")) +(bad-throw (groups Scheme) (scan-data "#<procedure bad-throw (key . args)>")) +(basename (groups POSIX Scheme) (scan-data "#<primitive-procedure basename>")) +(basic-load (groups Scheme) (scan-data "#<procedure load (name)>")) +(batch-mode? (groups Scheme) (scan-data "#<procedure batch-mode? ()>")) +(beautify-user-module! (groups Scheme) (scan-data "#<procedure beautify-user-module! (module)>")) +(before-backtrace-hook (groups Scheme) (scan-data "")) +(before-error-hook (groups Scheme) (scan-data "")) +(before-eval-hook (groups Scheme) (scan-data "")) +(before-print-hook (groups Scheme) (scan-data "")) +(before-read-hook (groups Scheme) (scan-data "")) +(before-signal-stack (groups Scheme) (scan-data "")) +(begin (groups Scheme) (scan-data "")) +(begin-deprecated (groups Scheme) (scan-data "")) +(bind (groups Scheme) (scan-data "#<primitive-procedure bind>")) +(bit-count (groups Scheme) (scan-data "#<primitive-procedure bit-count>")) +(bit-count* (groups Scheme) (scan-data "#<primitive-procedure bit-count*>")) +(bit-extract (groups Scheme) (scan-data "#<primitive-procedure bit-extract>")) +(bit-invert! (groups Scheme) (scan-data "#<primitive-procedure bit-invert!>")) +(bit-position (groups Scheme) (scan-data "#<primitive-procedure bit-position>")) +(bit-set*! (groups Scheme) (scan-data "#<primitive-procedure bit-set*!>")) +(boolean? (groups Scheme) (scan-data "#<primitive-procedure boolean?>")) +(caaaar (groups Scheme) (scan-data "#<primitive-procedure caaaar>")) +(caaadr (groups Scheme) (scan-data "#<primitive-procedure caaadr>")) +(caaar (groups Scheme) (scan-data "#<primitive-procedure caaar>")) +(caadar (groups Scheme) (scan-data "#<primitive-procedure caadar>")) +(caaddr (groups Scheme) (scan-data "#<primitive-procedure caaddr>")) +(caadr (groups Scheme) (scan-data "#<primitive-procedure caadr>")) +(caar (groups Scheme) (scan-data "#<primitive-procedure caar>")) +(cadaar (groups Scheme) (scan-data "#<primitive-procedure cadaar>")) +(cadadr (groups Scheme) (scan-data "#<primitive-procedure cadadr>")) +(cadar (groups Scheme) (scan-data "#<primitive-procedure cadar>")) +(caddar (groups Scheme) (scan-data "#<primitive-procedure caddar>")) +(cadddr (groups Scheme) (scan-data "#<primitive-procedure cadddr>")) +(caddr (groups Scheme) (scan-data "#<primitive-procedure caddr>")) +(cadr (groups Scheme) (scan-data "#<primitive-procedure cadr>")) +(call-with-current-continuation (groups Scheme) (scan-data "#<procedure call-with-current-continuation (proc)>")) +(call-with-dynamic-root (groups Scheme) (scan-data "#<primitive-procedure call-with-dynamic-root>")) +(call-with-input-file (groups Scheme) (scan-data "#<procedure call-with-input-file (str proc)>")) +(call-with-input-string (groups Scheme) (scan-data "#<primitive-procedure call-with-input-string>")) +(call-with-new-thread (groups Scheme) (scan-data "#<primitive-procedure call-with-new-thread>")) +(call-with-output-file (groups Scheme) (scan-data "#<procedure call-with-output-file (str proc)>")) +(call-with-output-string (groups Scheme) (scan-data "#<primitive-procedure call-with-output-string>")) +(call-with-values (groups Scheme) (scan-data "#<procedure call-with-values (producer consumer)>")) +(car (groups Scheme) (scan-data "#<primitive-procedure car>")) +(case (groups Scheme) (scan-data "")) +(catch (groups Scheme) (scan-data "#<primitive-procedure catch>")) +(cdaaar (groups Scheme) (scan-data "#<primitive-procedure cdaaar>")) +(cdaadr (groups Scheme) (scan-data "#<primitive-procedure cdaadr>")) +(cdaar (groups Scheme) (scan-data "#<primitive-procedure cdaar>")) +(cdadar (groups Scheme) (scan-data "#<primitive-procedure cdadar>")) +(cdaddr (groups Scheme) (scan-data "#<primitive-procedure cdaddr>")) +(cdadr (groups Scheme) (scan-data "#<primitive-procedure cdadr>")) +(cdar (groups Scheme) (scan-data "#<primitive-procedure cdar>")) +(cddaar (groups Scheme) (scan-data "#<primitive-procedure cddaar>")) +(cddadr (groups Scheme) (scan-data "#<primitive-procedure cddadr>")) +(cddar (groups Scheme) (scan-data "#<primitive-procedure cddar>")) +(cdddar (groups Scheme) (scan-data "#<primitive-procedure cdddar>")) +(cddddr (groups Scheme) (scan-data "#<primitive-procedure cddddr>")) +(cdddr (groups Scheme) (scan-data "#<primitive-procedure cdddr>")) +(cddr (groups Scheme) (scan-data "#<primitive-procedure cddr>")) +(cdr (groups Scheme) (scan-data "#<primitive-procedure cdr>")) +(ceiling (groups Scheme) (scan-data "#<primitive-procedure ceiling>")) +(char->integer (groups Scheme) (scan-data "#<primitive-procedure char->integer>")) +(char-alphabetic? (groups Scheme) (scan-data "#<primitive-procedure char-alphabetic?>")) +(char-ci<=? (groups Scheme) (scan-data "#<primitive-procedure char-ci<=?>")) +(char-ci<? (groups Scheme) (scan-data "#<primitive-procedure char-ci<?>")) +(char-ci=? (groups Scheme) (scan-data "#<primitive-procedure char-ci=?>")) +(char-ci>=? (groups Scheme) (scan-data "#<primitive-procedure char-ci>=?>")) +(char-ci>? (groups Scheme) (scan-data "#<primitive-procedure char-ci>?>")) +(char-downcase (groups Scheme) (scan-data "#<primitive-procedure char-downcase>")) +(char-is-both? (groups Scheme) (scan-data "#<primitive-procedure char-is-both?>")) +(char-lower-case? (groups Scheme) (scan-data "#<primitive-procedure char-lower-case?>")) +(char-numeric? (groups Scheme) (scan-data "#<primitive-procedure char-numeric?>")) +(char-ready? (groups Scheme) (scan-data "#<primitive-procedure char-ready?>")) +(char-upcase (groups Scheme) (scan-data "#<primitive-procedure char-upcase>")) +(char-upper-case? (groups Scheme) (scan-data "#<primitive-procedure char-upper-case?>")) +(char-whitespace? (groups Scheme) (scan-data "#<primitive-procedure char-whitespace?>")) +(char<=? (groups Scheme) (scan-data "#<primitive-procedure char<=?>")) +(char<? (groups Scheme) (scan-data "#<primitive-procedure char<?>")) +(char=? (groups Scheme) (scan-data "#<primitive-procedure char=?>")) +(char>=? (groups Scheme) (scan-data "#<primitive-procedure char>=?>")) +(char>? (groups Scheme) (scan-data "#<primitive-procedure char>?>")) +(char? (groups Scheme) (scan-data "#<primitive-procedure char?>")) +(chdir (groups POSIX Scheme) (scan-data "#<primitive-procedure chdir>")) +(chmod (groups POSIX Scheme) (scan-data "#<primitive-procedure chmod>")) +(chown (groups POSIX Scheme) (scan-data "#<primitive-procedure chown>")) +(chroot (groups POSIX Scheme) (scan-data "#<primitive-procedure chroot>")) +(class-of (groups Scheme) (scan-data "#<primitive-procedure class-of>")) +(close (groups POSIX Scheme) (scan-data "#<primitive-procedure close>")) +(close-fdes (groups POSIX Scheme) (scan-data "#<primitive-procedure close-fdes>")) +(close-input-port (groups Scheme) (scan-data "#<primitive-procedure close-input-port>")) +(close-io-port (groups Scheme) (scan-data "#<primitive-procedure close-port>")) +(close-output-port (groups Scheme) (scan-data "#<primitive-procedure close-output-port>")) +(close-port (groups Scheme) (scan-data "#<primitive-procedure close-port>")) +(closedir (groups POSIX Scheme) (scan-data "#<primitive-procedure closedir>")) +(closure? (groups Scheme) (scan-data "#<primitive-procedure closure?>")) +(collect (groups Scheme) (scan-data "")) +(command-line (groups POSIX Scheme) (scan-data "#<procedure command-line ()>")) +(compile-define-module-args (groups Scheme) (scan-data "#<procedure compile-define-module-args (args)>")) +(compile-interface-spec (groups Scheme) (scan-data "#<procedure compile-interface-spec (spec)>")) +(complex? (groups Scheme) (scan-data "#<primitive-procedure complex?>")) +(cond (groups Scheme) (scan-data "")) +(cond-expand (groups Scheme) (scan-data "")) +(cond-expand-provide (groups Scheme) (scan-data "#<procedure cond-expand-provide (module features)>")) +(connect (groups Scheme) (scan-data "#<primitive-procedure connect>")) +(cons (groups Scheme) (scan-data "#<primitive-procedure cons>")) +(cons* (groups Scheme) (scan-data "#<primitive-procedure cons*>")) +(cons-source (groups Scheme) (scan-data "#<primitive-procedure cons-source>")) +(coop_abort (groups guile-C-API coop C) (scan-data T)) +(coop_condition_variable_destroy (groups guile-C-API coop C) (scan-data T)) +(coop_condition_variable_init (groups guile-C-API coop C) (scan-data T)) +(coop_condition_variable_signal (groups guile-C-API coop C) (scan-data T)) +(coop_condition_variable_timed_wait_mutex (groups guile-C-API coop C) (scan-data T)) +(coop_condition_variable_wait_mutex (groups guile-C-API coop C) (scan-data T)) +(coop_create (groups guile-C-API coop C) (scan-data T)) +(coop_getspecific (groups guile-C-API coop C) (scan-data T)) +(coop_global_allq (groups guile-C-API coop C) (scan-data B)) +(coop_global_curr (groups guile-C-API coop C) (scan-data B)) +(coop_global_runq (groups guile-C-API coop C) (scan-data B)) +(coop_global_sleepq (groups guile-C-API coop C) (scan-data B)) +(coop_init (groups guile-C-API coop C) (scan-data T)) +(coop_join (groups guile-C-API coop C) (scan-data T)) +(coop_key_create (groups guile-C-API coop C) (scan-data T)) +(coop_key_delete (groups guile-C-API coop C) (scan-data T)) +(coop_mutex_destroy (groups guile-C-API coop C) (scan-data T)) +(coop_mutex_init (groups guile-C-API coop C) (scan-data T)) +(coop_mutex_lock (groups guile-C-API coop C) (scan-data T)) +(coop_mutex_trylock (groups guile-C-API coop C) (scan-data T)) +(coop_mutex_unlock (groups guile-C-API coop C) (scan-data T)) +(coop_new_condition_variable_init (groups guile-C-API coop C) (scan-data T)) +(coop_new_mutex_init (groups guile-C-API coop C) (scan-data T)) +(coop_next_runnable_thread (groups guile-C-API coop C) (scan-data T)) +(coop_qget (groups guile-C-API coop C) (scan-data T)) +(coop_qput (groups guile-C-API coop C) (scan-data T)) +(coop_setspecific (groups guile-C-API coop C) (scan-data T)) +(coop_sleephelp (groups guile-C-API coop C) (scan-data T)) +(coop_start (groups guile-C-API coop C) (scan-data T)) +(coop_timeout_qinsert (groups guile-C-API coop C) (scan-data T)) +(coop_tmp_queue (groups guile-C-API coop C) (scan-data B)) +(coop_wait_for_runnable_thread (groups guile-C-API coop C) (scan-data T)) +(coop_wait_for_runnable_thread_now (groups guile-C-API coop C) (scan-data T)) +(coop_yield (groups guile-C-API coop C) (scan-data T)) +(copy-file (groups POSIX Scheme) (scan-data "#<primitive-procedure copy-file>")) +(copy-random-state (groups Scheme) (scan-data "#<primitive-procedure copy-random-state>")) +(copy-tree (groups Scheme) (scan-data "#<primitive-procedure copy-tree>")) +(cos (groups Scheme) (scan-data "#<procedure cos (z)>")) +(cosh (groups Scheme) (scan-data "#<procedure cosh (z)>")) +(crypt (groups POSIX Scheme) (scan-data "#<primitive-procedure crypt>")) +(ctermid (groups POSIX Scheme) (scan-data "#<primitive-procedure ctermid>")) +(current-error-port (groups Scheme) (scan-data "#<primitive-procedure current-error-port>")) +(current-input-port (groups Scheme) (scan-data "#<primitive-procedure current-input-port>")) +(current-load-port (groups Scheme) (scan-data "#<primitive-procedure current-load-port>")) +(current-module (groups Scheme) (scan-data "#<primitive-procedure current-module>")) +(current-output-port (groups Scheme) (scan-data "#<primitive-procedure current-output-port>")) +(current-time (groups POSIX Scheme) (scan-data "#<primitive-procedure current-time>")) +(cuserid (groups POSIX Scheme) (scan-data "#<primitive-procedure cuserid>")) +(debug-disable (groups Scheme) (scan-data "#<procedure debug-disable flags>")) +(debug-enable (groups Scheme) (scan-data "#<procedure debug-enable flags>")) +(debug-object? (groups Scheme) (scan-data "#<primitive-procedure debug-object?>")) +(debug-options (groups Scheme) (scan-data "#<procedure debug-options args>")) +(debug-options-interface (groups Scheme) (scan-data "#<primitive-procedure debug-options-interface>")) +(debug-set! (groups Scheme) (scan-data "")) +(default-lazy-handler (groups Scheme) (scan-data "#<procedure default-lazy-handler (key . args)>")) +(define (groups Scheme) (scan-data "")) +(define-macro (groups Scheme) (scan-data "")) +(define-module (groups Scheme) (scan-data "")) +(define-option-interface (groups Scheme) (scan-data "")) +(define-private (groups Scheme) (scan-data "")) +(define-public (groups Scheme) (scan-data "")) +(define-syntax-macro (groups Scheme) (scan-data "")) +(defined? (groups Scheme) (scan-data "#<primitive-procedure defined?>")) +(defmacro (groups Scheme) (scan-data "")) +(defmacro-public (groups Scheme) (scan-data "")) +(defmacro-transformer (groups Scheme) (scan-data "#<procedure defmacro-transformer (m)>")) +(defmacro:syntax-transformer (groups Scheme) (scan-data "#<procedure defmacro:syntax-transformer (f)>")) +(defmacro:transformer (groups Scheme) (scan-data "#<procedure defmacro:transformer (f)>")) +(defmacro? (groups Scheme) (scan-data "#<procedure defmacro? (m)>")) +(delay (groups Scheme) (scan-data "")) +(delete (groups Scheme) (scan-data "#<primitive-procedure delete>")) +(delete! (groups Scheme) (scan-data "#<primitive-procedure delete!>")) +(delete-file (groups POSIX Scheme) (scan-data "#<primitive-procedure delete-file>")) +(delete1! (groups Scheme) (scan-data "#<primitive-procedure delete1!>")) +(delq (groups Scheme) (scan-data "#<primitive-procedure delq>")) +(delq! (groups Scheme) (scan-data "#<primitive-procedure delq!>")) +(delq1! (groups Scheme) (scan-data "#<primitive-procedure delq1!>")) +(delv (groups Scheme) (scan-data "#<primitive-procedure delv>")) +(delv! (groups Scheme) (scan-data "#<primitive-procedure delv!>")) +(delv1! (groups Scheme) (scan-data "#<primitive-procedure delv1!>")) +(destroy-guardian! (groups Scheme) (scan-data "#<primitive-procedure destroy-guardian!>")) +(dimensions->uniform-array (groups Scheme) (scan-data "#<primitive-procedure dimensions->uniform-array>")) +(directory-stream? (groups POSIX Scheme) (scan-data "#<primitive-procedure directory-stream?>")) +(dirname (groups POSIX Scheme) (scan-data "#<primitive-procedure dirname>")) +(display (groups Scheme) (scan-data "#<primitive-procedure display>")) +(display-application (groups Scheme) (scan-data "#<primitive-procedure display-application>")) +(display-backtrace (groups Scheme) (scan-data "#<primitive-procedure display-backtrace>")) +(display-error (groups Scheme) (scan-data "#<primitive-procedure display-error>")) +(display-usage-report (groups Scheme) (scan-data "#<procedure display-usage-report (kw-desc)>")) +(do (groups Scheme) (scan-data "")) +(doubly-weak-hash-table? (groups Scheme) (scan-data "#<primitive-procedure doubly-weak-hash-table?>")) +(drain-input (groups Scheme) (scan-data "#<primitive-procedure drain-input>")) +(dup (groups POSIX Scheme) (scan-data "#<procedure dup (port/fd . maybe-fd)>")) +(dup->fdes (groups POSIX Scheme) (scan-data "#<primitive-procedure dup->fdes>")) +(dup->inport (groups POSIX Scheme) (scan-data "#<procedure dup->inport (port/fd . maybe-fd)>")) +(dup->outport (groups POSIX Scheme) (scan-data "#<procedure dup->outport (port/fd . maybe-fd)>")) +(dup->port (groups POSIX Scheme) (scan-data "#<procedure dup->port (port/fd mode . maybe-fd)>")) +(dup2 (groups POSIX Scheme) (scan-data "#<primitive-procedure dup2>")) +(duplicate-port (groups POSIX Scheme) (scan-data "#<procedure duplicate-port (port modes)>")) +(dynamic-args-call (groups Scheme) (scan-data "#<primitive-procedure dynamic-args-call>")) +(dynamic-call (groups Scheme) (scan-data "#<primitive-procedure dynamic-call>")) +(dynamic-func (groups Scheme) (scan-data "#<primitive-procedure dynamic-func>")) +(dynamic-link (groups Scheme) (scan-data "#<primitive-procedure dynamic-link>")) +(dynamic-object? (groups Scheme) (scan-data "#<primitive-procedure dynamic-object?>")) +(dynamic-root (groups Scheme) (scan-data "#<primitive-procedure dynamic-root>")) +(dynamic-unlink (groups Scheme) (scan-data "#<primitive-procedure dynamic-unlink>")) +(dynamic-wind (groups Scheme) (scan-data "#<primitive-procedure dynamic-wind>")) +(enclose-array (groups Scheme) (scan-data "#<primitive-procedure enclose-array>")) +(endgrent (groups POSIX Scheme) (scan-data "#<procedure endgrent ()>")) +(endhostent (groups Scheme) (scan-data "#<procedure endhostent ()>")) +(endnetent (groups Scheme) (scan-data "#<procedure endnetent ()>")) +(endprotoent (groups Scheme) (scan-data "#<procedure endprotoent ()>")) +(endpwent (groups POSIX Scheme) (scan-data "#<procedure endpwent ()>")) +(endservent (groups Scheme) (scan-data "#<procedure endservent ()>")) +(entity? (groups Scheme) (scan-data "#<primitive-procedure entity?>")) +(env-module (groups Scheme) (scan-data "#<primitive-procedure env-module>")) +(environ (groups POSIX Scheme) (scan-data "#<primitive-procedure environ>")) +(environment-bound? (groups Scheme) (scan-data "#<primitive-procedure environment-bound?>")) +(environment-cell (groups Scheme) (scan-data "#<primitive-procedure environment-cell>")) +(environment-define (groups Scheme) (scan-data "#<primitive-procedure environment-define>")) +(environment-fold (groups Scheme) (scan-data "#<primitive-procedure environment-fold>")) +(environment-module (groups Scheme) (scan-data "#<procedure environment-module (env)>")) +(environment-observe (groups Scheme) (scan-data "#<primitive-procedure environment-observe>")) +(environment-observe-weak (groups Scheme) (scan-data "#<primitive-procedure environment-observe-weak>")) +(environment-ref (groups Scheme) (scan-data "#<primitive-procedure environment-ref>")) +(environment-set! (groups Scheme) (scan-data "#<primitive-procedure environment-set!>")) +(environment-undefine (groups Scheme) (scan-data "#<primitive-procedure environment-undefine>")) +(environment-unobserve (groups Scheme) (scan-data "#<primitive-procedure environment-unobserve>")) +(environment? (groups Scheme) (scan-data "#<primitive-procedure environment?>")) +(eof-object? (groups Scheme) (scan-data "#<primitive-procedure eof-object?>")) +(eq? (groups Scheme) (scan-data "#<primitive-procedure eq?>")) +(equal? (groups Scheme) (scan-data "#<primitive-procedure equal?>")) +(eqv? (groups Scheme) (scan-data "#<primitive-procedure eqv?>")) +(error (groups Scheme) (scan-data "#<procedure error args>")) +(error-catching-loop (groups Scheme) (scan-data "#<procedure error-catching-loop (thunk)>")) +(error-catching-repl (groups Scheme) (scan-data "#<procedure error-catching-repl (r e p)>")) +(eval (groups Scheme) (scan-data "#<primitive-procedure eval>")) +(eval-case (groups Scheme) (scan-data "")) +(eval-disable (groups Scheme) (scan-data "#<procedure eval-disable flags>")) +(eval-enable (groups Scheme) (scan-data "#<procedure eval-enable flags>")) +(eval-environment-imported (groups Scheme) (scan-data "#<primitive-procedure eval-environment-imported>")) +(eval-environment-local (groups Scheme) (scan-data "#<primitive-procedure eval-environment-local>")) +(eval-environment-set-imported! (groups Scheme) (scan-data "#<primitive-procedure eval-environment-set-imported!>")) +(eval-environment-set-local! (groups Scheme) (scan-data "#<primitive-procedure eval-environment-set-local!>")) +(eval-environment? (groups Scheme) (scan-data "#<primitive-procedure eval-environment?>")) +(eval-options (groups Scheme) (scan-data "#<procedure eval-options args>")) +(eval-options-interface (groups Scheme) (scan-data "#<primitive-procedure eval-options-interface>")) +(eval-set! (groups Scheme) (scan-data "")) +(eval-string (groups Scheme) (scan-data "#<primitive-procedure eval-string>")) +(evaluator-traps-interface (groups Scheme) (scan-data "#<primitive-procedure evaluator-traps-interface>")) +(even? (groups Scheme) (scan-data "#<primitive-procedure even?>")) +(exact->inexact (groups Scheme) (scan-data "#<primitive-procedure exact->inexact>")) +(exact? (groups Scheme) (scan-data "#<primitive-procedure exact?>")) +(execl (groups POSIX Scheme) (scan-data "#<primitive-procedure execl>")) +(execle (groups POSIX Scheme) (scan-data "#<primitive-procedure execle>")) +(execlp (groups POSIX Scheme) (scan-data "#<primitive-procedure execlp>")) +(exit (groups Scheme) (scan-data "#<procedure quit args>")) +(exit-hook (groups Scheme) (scan-data "")) +(exp (groups Scheme) (scan-data "#<procedure exp (z)>")) +(export (groups Scheme) (scan-data "")) +(export-environment-private (groups Scheme) (scan-data "#<primitive-procedure export-environment-private>")) +(export-environment-set-private! (groups Scheme) (scan-data "#<primitive-procedure export-environment-set-private!>")) +(export-environment-set-signature! (groups Scheme) (scan-data "#<primitive-procedure export-environment-set-signature!>")) +(export-environment-signature (groups Scheme) (scan-data "#<primitive-procedure export-environment-signature>")) +(export-environment? (groups Scheme) (scan-data "#<primitive-procedure export-environment?>")) +(export-syntax (groups Scheme) (scan-data "")) +(expt (groups Scheme) (scan-data "#<procedure expt (z1 z2)>")) +(false-if-exception (groups Scheme) (scan-data "")) +(fcntl (groups POSIX Scheme) (scan-data "#<primitive-procedure fcntl>")) +(fdes->inport (groups POSIX Scheme) (scan-data "#<procedure fdes->inport (fdes)>")) +(fdes->outport (groups POSIX Scheme) (scan-data "#<procedure fdes->outport (fdes)>")) +(fdes->ports (groups POSIX Scheme) (scan-data "#<primitive-procedure fdes->ports>")) +(fdopen (groups POSIX Scheme) (scan-data "#<primitive-procedure fdopen>")) +(feature? (groups Scheme) (scan-data "#<procedure provided? (feature)>")) +(file-exists? (groups Scheme) (scan-data "#<procedure file-exists? (str)>")) +(file-is-directory? (groups Scheme) (scan-data "#<procedure file-is-directory? (str)>")) +(file-port? (groups Scheme) (scan-data "#<primitive-procedure file-port?>")) +(file-position (groups Scheme) (scan-data "#<procedure file-position args>")) +(file-set-position (groups Scheme) (scan-data "#<procedure file-set-position args>")) +(fileno (groups POSIX Scheme) (scan-data "#<primitive-procedure fileno>")) +(flock (groups POSIX Scheme) (scan-data "#<primitive-procedure flock>")) +(floor (groups Scheme) (scan-data "#<primitive-procedure floor>")) +(fluid-ref (groups Scheme) (scan-data "#<primitive-procedure fluid-ref>")) +(fluid-set! (groups Scheme) (scan-data "#<primitive-procedure fluid-set!>")) +(fluid? (groups Scheme) (scan-data "#<primitive-procedure fluid?>")) +(flush-all-ports (groups Scheme) (scan-data "#<primitive-procedure flush-all-ports>")) +(for-each (groups Scheme) (scan-data "#<primitive-procedure for-each>")) +(for-next-option (groups Scheme) (scan-data "#<procedure for-next-option (proc argv kw-opts kw-args)>")) +(force (groups Scheme) (scan-data "#<primitive-procedure force>")) +(force-output (groups Scheme) (scan-data "#<primitive-procedure force-output>")) +(format (groups Scheme) (scan-data "#<primitive-procedure simple-format>")) +(frame-arguments (groups Scheme) (scan-data "#<primitive-procedure frame-arguments>")) +(frame-evaluating-args? (groups Scheme) (scan-data "#<primitive-procedure frame-evaluating-args?>")) +(frame-next (groups Scheme) (scan-data "#<primitive-procedure frame-next>")) +(frame-number (groups Scheme) (scan-data "#<primitive-procedure frame-number>")) +(frame-overflow? (groups Scheme) (scan-data "#<primitive-procedure frame-overflow?>")) +(frame-previous (groups Scheme) (scan-data "#<primitive-procedure frame-previous>")) +(frame-procedure (groups Scheme) (scan-data "#<primitive-procedure frame-procedure>")) +(frame-procedure? (groups Scheme) (scan-data "#<primitive-procedure frame-procedure?>")) +(frame-real? (groups Scheme) (scan-data "#<primitive-procedure frame-real?>")) +(frame-source (groups Scheme) (scan-data "#<primitive-procedure frame-source>")) +(frame? (groups Scheme) (scan-data "#<primitive-procedure frame?>")) +(fsync (groups POSIX Scheme) (scan-data "#<primitive-procedure fsync>")) +(ftell (groups Scheme) (scan-data "#<primitive-procedure ftell>")) +(gc (groups Scheme) (scan-data "#<primitive-procedure gc>")) +(gc-run-time (groups Scheme) (scan-data "#<procedure gc-run-time ()>")) +(gc-stats (groups Scheme) (scan-data "#<primitive-procedure gc-stats>")) +(gcd (groups Scheme) (scan-data "#<primitive-procedure gcd>")) +(gdb_binding (groups guile-C-API gdb C) (scan-data T)) +(gdb_eval (groups guile-C-API gdb C) (scan-data T)) +(gdb_language (groups guile-C-API gdb C) (scan-data D)) +(gdb_maybe_valid_type_p (groups guile-C-API gdb C) (scan-data T)) +(gdb_options (groups guile-C-API gdb C) (scan-data D)) +(gdb_output (groups guile-C-API gdb C) (scan-data B)) +(gdb_output_length (groups guile-C-API gdb C) (scan-data B)) +(gdb_print (groups guile-C-API gdb C) (scan-data T)) +(gdb_read (groups guile-C-API gdb C) (scan-data T)) +(gdb_result (groups guile-C-API gdb C) (scan-data B)) +(gensym (groups Scheme) (scan-data "#<primitive-procedure gensym>")) +(get-internal-real-time (groups POSIX Scheme) (scan-data "#<primitive-procedure get-internal-real-time>")) +(get-internal-run-time (groups POSIX Scheme) (scan-data "#<primitive-procedure get-internal-run-time>")) +(get-option (groups Scheme) (scan-data "#<procedure get-option (argv kw-opts kw-args return)>")) +(get-output-string (groups Scheme) (scan-data "#<primitive-procedure get-output-string>")) +(get-print-state (groups Scheme) (scan-data "#<primitive-procedure get-print-state>")) +(getcwd (groups POSIX Scheme) (scan-data "#<primitive-procedure getcwd>")) +(getegid (groups POSIX Scheme) (scan-data "#<primitive-procedure getegid>")) +(getenv (groups POSIX Scheme) (scan-data "#<primitive-procedure getenv>")) +(geteuid (groups POSIX Scheme) (scan-data "#<primitive-procedure geteuid>")) +(getgid (groups POSIX Scheme) (scan-data "#<primitive-procedure getgid>")) +(getgr (groups POSIX Scheme) (scan-data "#<primitive-procedure getgr>")) +(getgrent (groups POSIX Scheme) (scan-data "#<procedure getgrent ()>")) +(getgrgid (groups POSIX Scheme) (scan-data "#<procedure getgrgid (id)>")) +(getgrnam (groups POSIX Scheme) (scan-data "#<procedure getgrnam (name)>")) +(getgroups (groups POSIX Scheme) (scan-data "#<primitive-procedure getgroups>")) +(gethost (groups Scheme) (scan-data "#<primitive-procedure gethost>")) +(gethostbyaddr (groups Scheme) (scan-data "#<procedure gethostbyaddr (addr)>")) +(gethostbyname (groups Scheme) (scan-data "#<procedure gethostbyname (name)>")) +(gethostent (groups Scheme) (scan-data "#<procedure gethostent ()>")) +(gethostname (groups POSIX Scheme) (scan-data "#<primitive-procedure gethostname>")) +(getitimer (groups POSIX Scheme) (scan-data "#<primitive-procedure getitimer>")) +(getlogin (groups POSIX Scheme) (scan-data "#<primitive-procedure getlogin>")) +(getnet (groups Scheme) (scan-data "#<primitive-procedure getnet>")) +(getnetbyaddr (groups Scheme) (scan-data "#<procedure getnetbyaddr (addr)>")) +(getnetbyname (groups Scheme) (scan-data "#<procedure getnetbyname (name)>")) +(getnetent (groups Scheme) (scan-data "#<procedure getnetent ()>")) +(getpass (groups POSIX Scheme) (scan-data "#<primitive-procedure getpass>")) +(getpeername (groups Scheme) (scan-data "#<primitive-procedure getpeername>")) +(getpgrp (groups POSIX Scheme) (scan-data "#<primitive-procedure getpgrp>")) +(getpid (groups POSIX Scheme) (scan-data "#<primitive-procedure getpid>")) +(getppid (groups POSIX Scheme) (scan-data "#<primitive-procedure getppid>")) +(getpriority (groups POSIX Scheme) (scan-data "#<primitive-procedure getpriority>")) +(getproto (groups Scheme) (scan-data "#<primitive-procedure getproto>")) +(getprotobyname (groups Scheme) (scan-data "#<procedure getprotobyname (name)>")) +(getprotobynumber (groups Scheme) (scan-data "#<procedure getprotobynumber (addr)>")) +(getprotoent (groups Scheme) (scan-data "#<procedure getprotoent ()>")) +(getpw (groups POSIX Scheme) (scan-data "#<primitive-procedure getpw>")) +(getpwent (groups POSIX Scheme) (scan-data "#<procedure getpwent ()>")) +(getpwnam (groups POSIX Scheme) (scan-data "#<procedure getpwnam (name)>")) +(getpwuid (groups POSIX Scheme) (scan-data "#<procedure getpwuid (uid)>")) +(getserv (groups Scheme) (scan-data "#<primitive-procedure getserv>")) +(getservbyname (groups Scheme) (scan-data "#<procedure getservbyname (name proto)>")) +(getservbyport (groups Scheme) (scan-data "#<procedure getservbyport (port proto)>")) +(getservent (groups Scheme) (scan-data "#<procedure getservent ()>")) +(getsockname (groups Scheme) (scan-data "#<primitive-procedure getsockname>")) +(getsockopt (groups Scheme) (scan-data "#<primitive-procedure getsockopt>")) +(gettimeofday (groups POSIX Scheme) (scan-data "#<primitive-procedure gettimeofday>")) +(getuid (groups POSIX Scheme) (scan-data "#<primitive-procedure getuid>")) +(gh_append (groups guile-C-API gh C) (scan-data T)) +(gh_append2 (groups guile-C-API gh C) (scan-data T)) +(gh_append3 (groups guile-C-API gh C) (scan-data T)) +(gh_append4 (groups guile-C-API gh C) (scan-data T)) +(gh_apply (groups guile-C-API gh C) (scan-data T)) +(gh_bool2scm (groups guile-C-API gh C) (scan-data T)) +(gh_boolean_p (groups guile-C-API gh C) (scan-data T)) +(gh_caaar (groups guile-C-API gh C) (scan-data T)) +(gh_caadr (groups guile-C-API gh C) (scan-data T)) +(gh_caar (groups guile-C-API gh C) (scan-data T)) +(gh_cadar (groups guile-C-API gh C) (scan-data T)) +(gh_caddr (groups guile-C-API gh C) (scan-data T)) +(gh_cadr (groups guile-C-API gh C) (scan-data T)) +(gh_call0 (groups guile-C-API gh C) (scan-data T)) +(gh_call1 (groups guile-C-API gh C) (scan-data T)) +(gh_call2 (groups guile-C-API gh C) (scan-data T)) +(gh_call3 (groups guile-C-API gh C) (scan-data T)) +(gh_car (groups guile-C-API gh C) (scan-data T)) +(gh_catch (groups guile-C-API gh C) (scan-data T)) +(gh_cdaar (groups guile-C-API gh C) (scan-data T)) +(gh_cdadr (groups guile-C-API gh C) (scan-data T)) +(gh_cdar (groups guile-C-API gh C) (scan-data T)) +(gh_cddar (groups guile-C-API gh C) (scan-data T)) +(gh_cdddr (groups guile-C-API gh C) (scan-data T)) +(gh_cddr (groups guile-C-API gh C) (scan-data T)) +(gh_cdr (groups guile-C-API gh C) (scan-data T)) +(gh_char2scm (groups guile-C-API gh C) (scan-data T)) +(gh_char_p (groups guile-C-API gh C) (scan-data T)) +(gh_chars2byvect (groups guile-C-API gh C) (scan-data T)) +(gh_cons (groups guile-C-API gh C) (scan-data T)) +(gh_define (groups guile-C-API gh C) (scan-data T)) +(gh_display (groups guile-C-API gh C) (scan-data T)) +(gh_double2scm (groups guile-C-API gh C) (scan-data T)) +(gh_doubles2dvect (groups guile-C-API gh C) (scan-data T)) +(gh_doubles2scm (groups guile-C-API gh C) (scan-data T)) +(gh_enter (groups guile-C-API gh C) (scan-data T)) +(gh_eq_p (groups guile-C-API gh C) (scan-data T)) +(gh_equal_p (groups guile-C-API gh C) (scan-data T)) +(gh_eqv_p (groups guile-C-API gh C) (scan-data T)) +(gh_eval_file (groups guile-C-API gh C) (scan-data T)) +(gh_eval_file_with_catch (groups guile-C-API gh C) (scan-data T)) +(gh_eval_file_with_standard_handler (groups guile-C-API gh C) (scan-data T)) +(gh_eval_str (groups guile-C-API gh C) (scan-data T)) +(gh_eval_str_with_catch (groups guile-C-API gh C) (scan-data T)) +(gh_eval_str_with_stack_saving_handler (groups guile-C-API gh C) (scan-data T)) +(gh_eval_str_with_standard_handler (groups guile-C-API gh C) (scan-data T)) +(gh_exact_p (groups guile-C-API gh C) (scan-data T)) +(gh_floats2fvect (groups guile-C-API gh C) (scan-data T)) +(gh_get_substr (groups guile-C-API gh C) (scan-data T)) +(gh_inexact_p (groups guile-C-API gh C) (scan-data T)) +(gh_int2scm (groups guile-C-API gh C) (scan-data T)) +(gh_ints2scm (groups guile-C-API gh C) (scan-data T)) +(gh_length (groups guile-C-API gh C) (scan-data T)) +(gh_list_p (groups guile-C-API gh C) (scan-data T)) +(gh_long2scm (groups guile-C-API gh C) (scan-data T)) +(gh_longs2ivect (groups guile-C-API gh C) (scan-data T)) +(gh_lookup (groups guile-C-API gh C) (scan-data T)) +(gh_make_vector (groups guile-C-API gh C) (scan-data T)) +(gh_module_lookup (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure0_0 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure0_1 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure0_2 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure1_0 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure1_1 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure1_2 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure2_0 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure2_1 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure2_2 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure3_0 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure4_0 (groups guile-C-API gh C) (scan-data T)) +(gh_new_procedure5_0 (groups guile-C-API gh C) (scan-data T)) +(gh_newline (groups guile-C-API gh C) (scan-data T)) +(gh_null_p (groups guile-C-API gh C) (scan-data T)) +(gh_number_p (groups guile-C-API gh C) (scan-data T)) +(gh_pair_p (groups guile-C-API gh C) (scan-data T)) +(gh_procedure_p (groups guile-C-API gh C) (scan-data T)) +(gh_repl (groups guile-C-API gh C) (scan-data T)) +(gh_scm2bool (groups guile-C-API gh C) (scan-data T)) +(gh_scm2char (groups guile-C-API gh C) (scan-data T)) +(gh_scm2chars (groups guile-C-API gh C) (scan-data T)) +(gh_scm2double (groups guile-C-API gh C) (scan-data T)) +(gh_scm2doubles (groups guile-C-API gh C) (scan-data T)) +(gh_scm2floats (groups guile-C-API gh C) (scan-data T)) +(gh_scm2int (groups guile-C-API gh C) (scan-data T)) +(gh_scm2long (groups guile-C-API gh C) (scan-data T)) +(gh_scm2longs (groups guile-C-API gh C) (scan-data T)) +(gh_scm2newstr (groups guile-C-API gh C) (scan-data T)) +(gh_scm2shorts (groups guile-C-API gh C) (scan-data T)) +(gh_scm2ulong (groups guile-C-API gh C) (scan-data T)) +(gh_set_car_x (groups guile-C-API gh C) (scan-data T)) +(gh_set_cdr_x (groups guile-C-API gh C) (scan-data T)) +(gh_set_substr (groups guile-C-API gh C) (scan-data T)) +(gh_shorts2svect (groups guile-C-API gh C) (scan-data T)) +(gh_standard_handler (groups guile-C-API gh C) (scan-data T)) +(gh_str02scm (groups guile-C-API gh C) (scan-data T)) +(gh_str2scm (groups guile-C-API gh C) (scan-data T)) +(gh_string_equal_p (groups guile-C-API gh C) (scan-data T)) +(gh_string_p (groups guile-C-API gh C) (scan-data T)) +(gh_symbol2newstr (groups guile-C-API gh C) (scan-data T)) +(gh_symbol2scm (groups guile-C-API gh C) (scan-data T)) +(gh_symbol_p (groups guile-C-API gh C) (scan-data T)) +(gh_ulong2scm (groups guile-C-API gh C) (scan-data T)) +(gh_ulongs2uvect (groups guile-C-API gh C) (scan-data T)) +(gh_uniform_vector_length (groups guile-C-API gh C) (scan-data T)) +(gh_uniform_vector_ref (groups guile-C-API gh C) (scan-data T)) +(gh_vector_length (groups guile-C-API gh C) (scan-data T)) +(gh_vector_p (groups guile-C-API gh C) (scan-data T)) +(gh_vector_ref (groups guile-C-API gh C) (scan-data T)) +(gh_vector_set_x (groups guile-C-API gh C) (scan-data T)) +(gh_write (groups guile-C-API gh C) (scan-data T)) +(gmtime (groups POSIX Scheme) (scan-data "#<primitive-procedure gmtime>")) +(group:gid (groups POSIX Scheme) (scan-data "#<procedure group:gid (obj)>")) +(group:mem (groups POSIX Scheme) (scan-data "#<procedure group:mem (obj)>")) +(group:name (groups POSIX Scheme) (scan-data "#<procedure group:name (obj)>")) +(group:passwd (groups POSIX Scheme) (scan-data "#<procedure group:passwd (obj)>")) +(guardian-destroyed? (groups Scheme) (scan-data "#<primitive-procedure guardian-destroyed?>")) +(guardian-greedy? (groups Scheme) (scan-data "#<primitive-procedure guardian-greedy?>")) +(handle-system-error (groups Scheme) (scan-data "#<procedure handle-system-error (key . args)>")) +(has-shown-backtrace-hint? (groups Scheme) (scan-data "")) +(has-shown-debugger-hint? (groups Scheme) (scan-data "")) +(has-suffix? (groups Scheme) (scan-data "#<procedure has-suffix? (str suffix)>")) +(hash (groups Scheme) (scan-data "#<primitive-procedure hash>")) +(hash-create-handle! (groups Scheme) (scan-data "#<primitive-procedure hash-create-handle!>")) +(hash-fold (groups Scheme) (scan-data "#<primitive-procedure hash-fold>")) +(hash-get-handle (groups Scheme) (scan-data "#<primitive-procedure hash-get-handle>")) +(hash-ref (groups Scheme) (scan-data "#<primitive-procedure hash-ref>")) +(hash-remove! (groups Scheme) (scan-data "#<primitive-procedure hash-remove!>")) +(hash-set! (groups Scheme) (scan-data "#<primitive-procedure hash-set!>")) +(hashq (groups Scheme) (scan-data "#<primitive-procedure hashq>")) +(hashq-create-handle! (groups Scheme) (scan-data "#<primitive-procedure hashq-create-handle!>")) +(hashq-get-handle (groups Scheme) (scan-data "#<primitive-procedure hashq-get-handle>")) +(hashq-ref (groups Scheme) (scan-data "#<primitive-procedure hashq-ref>")) +(hashq-remove! (groups Scheme) (scan-data "#<primitive-procedure hashq-remove!>")) +(hashq-set! (groups Scheme) (scan-data "#<primitive-procedure hashq-set!>")) +(hashv (groups Scheme) (scan-data "#<primitive-procedure hashv>")) +(hashv-create-handle! (groups Scheme) (scan-data "#<primitive-procedure hashv-create-handle!>")) +(hashv-get-handle (groups Scheme) (scan-data "#<primitive-procedure hashv-get-handle>")) +(hashv-ref (groups Scheme) (scan-data "#<primitive-procedure hashv-ref>")) +(hashv-remove! (groups Scheme) (scan-data "#<primitive-procedure hashv-remove!>")) +(hashv-set! (groups Scheme) (scan-data "#<primitive-procedure hashv-set!>")) +(hashx-create-handle! (groups Scheme) (scan-data "#<primitive-procedure hashx-create-handle!>")) +(hashx-get-handle (groups Scheme) (scan-data "#<primitive-procedure hashx-get-handle>")) +(hashx-ref (groups Scheme) (scan-data "#<primitive-procedure hashx-ref>")) +(hashx-set! (groups Scheme) (scan-data "#<primitive-procedure hashx-set!>")) +(hook->list (groups Scheme) (scan-data "#<primitive-procedure hook->list>")) +(hook-empty? (groups Scheme) (scan-data "#<primitive-procedure hook-empty?>")) +(hook? (groups Scheme) (scan-data "#<primitive-procedure hook?>")) +(hostent:addr-list (groups Scheme) (scan-data "#<procedure hostent:addr-list (obj)>")) +(hostent:addrtype (groups Scheme) (scan-data "#<procedure hostent:addrtype (obj)>")) +(hostent:aliases (groups Scheme) (scan-data "#<procedure hostent:aliases (obj)>")) +(hostent:length (groups Scheme) (scan-data "#<procedure hostent:length (obj)>")) +(hostent:name (groups Scheme) (scan-data "#<procedure hostent:name (obj)>")) +(htonl (groups Scheme) (scan-data "#<primitive-procedure htonl>")) +(htons (groups Scheme) (scan-data "#<primitive-procedure htons>")) +(identity (groups Scheme) (scan-data "#<procedure identity (x)>")) +(if (groups Scheme) (scan-data "")) +(imag-part (groups Scheme) (scan-data "#<primitive-procedure imag-part>")) +(import-environment-imports (groups Scheme) (scan-data "#<primitive-procedure import-environment-imports>")) +(import-environment-set-imports! (groups Scheme) (scan-data "#<primitive-procedure import-environment-set-imports!>")) +(import-environment? (groups Scheme) (scan-data "#<primitive-procedure import-environment?>")) +(in-vicinity (groups Scheme) (scan-data "#<procedure in-vicinity (vicinity file)>")) +(include-deprecated-features (groups Scheme) (scan-data "#<primitive-procedure include-deprecated-features>")) +(inet-aton (groups Scheme) (scan-data "#<primitive-procedure inet-aton>")) +(inet-lnaof (groups Scheme) (scan-data "#<primitive-procedure inet-lnaof>")) +(inet-makeaddr (groups Scheme) (scan-data "#<primitive-procedure inet-makeaddr>")) +(inet-netof (groups Scheme) (scan-data "#<primitive-procedure inet-netof>")) +(inet-ntoa (groups Scheme) (scan-data "#<primitive-procedure inet-ntoa>")) +(inet-ntop (groups Scheme) (scan-data "#<primitive-procedure inet-ntop>")) +(inet-pton (groups Scheme) (scan-data "#<primitive-procedure inet-pton>")) +(inexact->exact (groups Scheme) (scan-data "#<primitive-procedure inexact->exact>")) +(inexact? (groups Scheme) (scan-data "#<primitive-procedure inexact?>")) +(inf (groups Scheme) (scan-data "#<primitive-procedure inf>")) +(inf? (groups Scheme) (scan-data "#<primitive-procedure inf?>")) +(inherit-print-state (groups Scheme) (scan-data "#<procedure inherit-print-state (old-port new-port)>")) +(input-port? (groups Scheme) (scan-data "#<primitive-procedure input-port?>")) +(integer->char (groups Scheme) (scan-data "#<primitive-procedure integer->char>")) +(integer-expt (groups Scheme) (scan-data "#<primitive-procedure integer-expt>")) +(integer-length (groups Scheme) (scan-data "#<primitive-procedure integer-length>")) +(integer? (groups Scheme) (scan-data "#<primitive-procedure integer?>")) +(interaction-environment (groups Scheme) (scan-data "#<primitive-procedure interaction-environment>")) +(internal-time-units-per-second (groups Scheme) (scan-data "")) +(iota (groups Scheme) (scan-data "#<procedure iota (n)>")) +(ipow-by-squaring (groups Scheme) (scan-data "#<procedure ipow-by-squaring (x k acc proc)>")) +(isatty? (groups POSIX Scheme) (scan-data "#<primitive-procedure isatty?>")) +(issue-deprecation-warning (groups Scheme) (scan-data "#<primitive-procedure issue-deprecation-warning>")) +(join-thread (groups Scheme) (scan-data "#<primitive-procedure join-thread>")) +(keyword->symbol (groups Scheme) (scan-data "#<procedure keyword->symbol (kw)>")) +(keyword-dash-symbol (groups Scheme) (scan-data "#<primitive-procedure keyword-dash-symbol>")) +(keyword-like-symbol->keyword (groups Scheme) (scan-data "#<procedure keyword-like-symbol->keyword (sym)>")) +(keyword? (groups Scheme) (scan-data "#<primitive-procedure keyword?>")) +(kill (groups POSIX Scheme) (scan-data "#<primitive-procedure kill>")) +(kw-arg-ref (groups Scheme) (scan-data "#<procedure kw-arg-ref (args kw)>")) +(lambda (groups Scheme) (scan-data "")) +(last-pair (groups Scheme) (scan-data "#<primitive-procedure last-pair>")) +(last-stack-frame (groups Scheme) (scan-data "#<primitive-procedure last-stack-frame>")) +(lazy-catch (groups Scheme) (scan-data "#<primitive-procedure lazy-catch>")) +(lazy-handler-dispatch (groups Scheme) (scan-data "#<procedure lazy-handler-dispatch (key . args)>")) +(lcm (groups Scheme) (scan-data "#<primitive-procedure lcm>")) +(leaf-environment? (groups Scheme) (scan-data "#<primitive-procedure leaf-environment?>")) +(length (groups Scheme) (scan-data "#<primitive-procedure length>")) +(let (groups Scheme) (scan-data "")) +(let* (groups Scheme) (scan-data "")) +(letrec (groups Scheme) (scan-data "")) +(link (groups POSIX Scheme) (scan-data "#<primitive-procedure link>")) +(list (groups Scheme) (scan-data "#<primitive-procedure list>")) +(list->array (groups Scheme) (scan-data "#<procedure list->array (ndim lst)>")) +(list->string (groups Scheme) (scan-data "#<primitive-procedure list->string>")) +(list->symbol (groups Scheme) (scan-data "#<procedure list->symbol args>")) +(list->uniform-array (groups Scheme) (scan-data "#<primitive-procedure list->uniform-array>")) +(list->uniform-vector (groups Scheme) (scan-data "#<procedure list->uniform-vector (prot lst)>")) +(list->vector (groups Scheme) (scan-data "#<primitive-procedure list->vector>")) +(list->weak-vector (groups Scheme) (scan-data "#<primitive-procedure list->weak-vector>")) +(list-cdr-ref (groups Scheme) (scan-data "#<primitive-procedure list-cdr-ref>")) +(list-cdr-set! (groups Scheme) (scan-data "#<primitive-procedure list-cdr-set!>")) +(list-copy (groups Scheme) (scan-data "#<primitive-procedure list-copy>")) +(list-head (groups Scheme) (scan-data "#<primitive-procedure list-head>")) +(list-index (groups Scheme) (scan-data "#<procedure list-index (l k)>")) +(list-ref (groups Scheme) (scan-data "#<primitive-procedure list-ref>")) +(list-set! (groups Scheme) (scan-data "#<primitive-procedure list-set!>")) +(list-tail (groups Scheme) (scan-data "#<primitive-procedure list-tail>")) +(list? (groups Scheme) (scan-data "#<primitive-procedure list?>")) +(listen (groups Scheme) (scan-data "#<primitive-procedure listen>")) +(load (groups Scheme) (scan-data "#<procedure load-module (filename)>")) +(load-compiled (groups Scheme) (scan-data "")) +(load-emacs-interface (groups Scheme) (scan-data "#<procedure load-emacs-interface ()>")) +(load-extension (groups Scheme) (scan-data "#<primitive-procedure load-extension>")) +(load-from-path (groups Scheme) (scan-data "#<procedure load-from-path (name)>")) +(load-module (groups Scheme) (scan-data "#<procedure load-module (filename)>")) +(load-user-init (groups Scheme) (scan-data "#<procedure load-user-init ()>")) +(local-define (groups Scheme) (scan-data "#<procedure local-define (names val)>")) +(local-eval (groups Scheme) (scan-data "#<primitive-procedure local-eval>")) +(local-ref (groups Scheme) (scan-data "#<procedure local-ref (names)>")) +(local-remove (groups Scheme) (scan-data "#<procedure local-remove (names)>")) +(local-set! (groups Scheme) (scan-data "#<procedure local-set! (names val)>")) +(localtime (groups POSIX Scheme) (scan-data "#<primitive-procedure localtime>")) +(lock-mutex (groups Scheme) (scan-data "#<primitive-procedure lock-mutex>")) +(log (groups Scheme) (scan-data "#<procedure log (z)>")) +(log10 (groups Scheme) (scan-data "#<procedure log10 (arg)>")) +(logand (groups Scheme) (scan-data "#<primitive-procedure logand>")) +(logbit? (groups Scheme) (scan-data "#<primitive-procedure logbit?>")) +(logcount (groups Scheme) (scan-data "#<primitive-procedure logcount>")) +(logior (groups Scheme) (scan-data "#<primitive-procedure logior>")) +(lognot (groups Scheme) (scan-data "#<primitive-procedure lognot>")) +(logtest (groups Scheme) (scan-data "#<primitive-procedure logtest>")) +(logxor (groups Scheme) (scan-data "#<primitive-procedure logxor>")) +(lstat (groups POSIX Scheme) (scan-data "#<primitive-procedure lstat>")) +(macro-name (groups Scheme) (scan-data "#<primitive-procedure macro-name>")) +(macro-table (groups Scheme) (scan-data "")) +(macro-transformer (groups Scheme) (scan-data "#<primitive-procedure macro-transformer>")) +(macro-type (groups Scheme) (scan-data "#<primitive-procedure macro-type>")) +(macro? (groups Scheme) (scan-data "#<primitive-procedure macro?>")) +(macroexpand (groups Scheme) (scan-data "#<procedure macroexpand (e)>")) +(macroexpand-1 (groups Scheme) (scan-data "#<procedure macroexpand-1 (e)>")) +(magnitude (groups Scheme) (scan-data "#<primitive-procedure magnitude>")) +(major-version (groups Scheme) (scan-data "#<primitive-procedure major-version>")) +(make-arbiter (groups Scheme) (scan-data "#<primitive-procedure make-arbiter>")) +(make-array (groups Scheme) (scan-data "#<procedure make-array (fill . args)>")) +(make-autoload-interface (groups Scheme) (scan-data "#<procedure make-autoload-interface (module name bindings)>")) +(make-class-object (groups Scheme) (scan-data "#<primitive-procedure make-class-object>")) +(make-condition-variable (groups Scheme) (scan-data "#<primitive-procedure make-condition-variable>")) +(make-doubly-weak-hash-table (groups Scheme) (scan-data "#<primitive-procedure make-doubly-weak-hash-table>")) +(make-eval-environment (groups Scheme) (scan-data "#<primitive-procedure make-eval-environment>")) +(make-export-environment (groups Scheme) (scan-data "#<primitive-procedure make-export-environment>")) +(make-fluid (groups Scheme) (scan-data "#<primitive-procedure make-fluid>")) +(make-guardian (groups Scheme) (scan-data "#<primitive-procedure make-guardian>")) +(make-hash-table (groups Scheme) (scan-data "#<procedure make-hash-table (k)>")) +(make-hook (groups Scheme) (scan-data "#<primitive-procedure make-hook>")) +(make-import-environment (groups Scheme) (scan-data "#<primitive-procedure make-import-environment>")) +(make-keyword-from-dash-symbol (groups Scheme) (scan-data "#<primitive-procedure make-keyword-from-dash-symbol>")) +(make-leaf-environment (groups Scheme) (scan-data "#<primitive-procedure make-leaf-environment>")) +(make-list (groups Scheme) (scan-data "#<procedure make-list (n . init)>")) +(make-module (groups Scheme) (scan-data "#<procedure make-module args>")) +(make-modules-in (groups Scheme) (scan-data "#<procedure make-modules-in (module name)>")) +(make-mutex (groups Scheme) (scan-data "#<primitive-procedure make-mutex>")) +(make-object-property (groups Scheme) (scan-data "#<procedure make-object-property ()>")) +(make-polar (groups Scheme) (scan-data "#<primitive-procedure make-polar>")) +(make-procedure-with-setter (groups Scheme) (scan-data "#<primitive-procedure make-procedure-with-setter>")) +(make-record-type (groups Scheme) (scan-data "#<procedure make-record-type (type-name fields . opt)>")) +(make-rectangular (groups Scheme) (scan-data "#<primitive-procedure make-rectangular>")) +(make-regexp (groups Scheme) (scan-data "#<primitive-procedure make-regexp>")) +(make-root-module (groups Scheme) (scan-data "#<procedure make-root-module ()>")) +(make-scm-module (groups Scheme) (scan-data "#<procedure make-scm-module ()>")) +(make-shared-array (groups Scheme) (scan-data "#<primitive-procedure make-shared-array>")) +(make-soft-port (groups Scheme) (scan-data "#<primitive-procedure make-soft-port>")) +(make-stack (groups Scheme) (scan-data "#<primitive-procedure make-stack>")) +(make-string (groups Scheme) (scan-data "#<primitive-procedure make-string>")) +(make-struct (groups Scheme) (scan-data "#<primitive-procedure make-struct>")) +(make-struct-layout (groups Scheme) (scan-data "#<primitive-procedure make-struct-layout>")) +(make-subclass-object (groups Scheme) (scan-data "#<primitive-procedure make-subclass-object>")) +(make-symbol (groups Scheme) (scan-data "#<primitive-procedure make-symbol>")) +(make-undefined-variable (groups Scheme) (scan-data "#<primitive-procedure make-undefined-variable>")) +(make-uniform-array (groups Scheme) (scan-data "#<procedure make-uniform-array (prot . args)>")) +(make-uniform-vector (groups Scheme) (scan-data "#<primitive-procedure dimensions->uniform-array>")) +(make-variable (groups Scheme) (scan-data "#<primitive-procedure make-variable>")) +(make-vector (groups Scheme) (scan-data "#<primitive-procedure make-vector>")) +(make-vtable-vtable (groups Scheme) (scan-data "#<primitive-procedure make-vtable-vtable>")) +(make-weak-key-hash-table (groups Scheme) (scan-data "#<primitive-procedure make-weak-key-hash-table>")) +(make-weak-value-hash-table (groups Scheme) (scan-data "#<primitive-procedure make-weak-value-hash-table>")) +(make-weak-vector (groups Scheme) (scan-data "#<primitive-procedure make-weak-vector>")) +(map (groups Scheme) (scan-data "#<primitive-procedure map>")) +(map-in-order (groups Scheme) (scan-data "#<primitive-procedure map-in-order>")) +(mask-signals (groups Scheme) (scan-data "#<primitive-procedure mask-signals>")) +(max (groups Scheme) (scan-data "#<primitive-procedure max>")) +(member (groups Scheme) (scan-data "#<primitive-procedure member>")) +(memoized-environment (groups Scheme) (scan-data "#<primitive-procedure memoized-environment>")) +(memoized? (groups Scheme) (scan-data "#<primitive-procedure memoized?>")) +(memq (groups Scheme) (scan-data "#<primitive-procedure memq>")) +(memv (groups Scheme) (scan-data "#<primitive-procedure memv>")) +(merge (groups Scheme) (scan-data "#<primitive-procedure merge>")) +(merge! (groups Scheme) (scan-data "#<primitive-procedure merge!>")) +(micro-version (groups Scheme) (scan-data "#<primitive-procedure micro-version>")) +(min (groups Scheme) (scan-data "#<primitive-procedure min>")) +(minor-version (groups Scheme) (scan-data "#<primitive-procedure minor-version>")) +(mkdir (groups POSIX Scheme) (scan-data "#<primitive-procedure mkdir>")) +(mknod (groups POSIX Scheme) (scan-data "#<primitive-procedure mknod>")) +(mkstemp! (groups POSIX Scheme) (scan-data "#<primitive-procedure mkstemp!>")) +(mktime (groups POSIX Scheme) (scan-data "#<primitive-procedure mktime>")) +(module-add! (groups Scheme) (scan-data "#<procedure module-add! (m v var)>")) +(module-binder (groups Scheme) (scan-data "#<procedure module-binder (obj)>")) +(module-bound? (groups Scheme) (scan-data "#<procedure module-bound? (m v)>")) +(module-clear! (groups Scheme) (scan-data "#<procedure module-clear! (m)>")) +(module-constructor (groups Scheme) (scan-data "#<procedure module-constructor (obarray uses binder eval-closure transformer name kind observers weak-observers observer-id)>")) +(module-define! (groups Scheme) (scan-data "#<procedure module-define! (module name value)>")) +(module-defined? (groups Scheme) (scan-data "#<procedure module-defined? (module name)>")) +(module-ensure-local-variable! (groups Scheme) (scan-data "#<procedure module-ensure-local-variable! (module symbol)>")) +(module-eval-closure (groups Scheme) (scan-data "#<procedure module-eval-closure (obj)>")) +(module-export! (groups Scheme) (scan-data "#<procedure module-export! (m names)>")) +(module-for-each (groups Scheme) (scan-data "#<procedure module-for-each (proc module)>")) +(module-kind (groups Scheme) (scan-data "#<procedure module-kind (obj)>")) +(module-local-variable (groups Scheme) (scan-data "#<procedure module-local-variable (m v)>")) +(module-locally-bound? (groups Scheme) (scan-data "#<procedure module-locally-bound? (m v)>")) +(module-make-local-var! (groups Scheme) (scan-data "#<procedure module-make-local-var! (m v)>")) +(module-map (groups Scheme) (scan-data "#<procedure module-map (proc module)>")) +(module-modified (groups Scheme) (scan-data "#<procedure module-modified (m)>")) +(module-name (groups Scheme) (scan-data "#<procedure module-name (obj)>")) +(module-obarray (groups Scheme) (scan-data "#<procedure module-obarray (obj)>")) +(module-obarray-get-handle (groups Scheme) (scan-data "#<procedure module-obarray-get-handle (ob key)>")) +(module-obarray-ref (groups Scheme) (scan-data "#<procedure module-obarray-ref (ob key)>")) +(module-obarray-remove! (groups Scheme) (scan-data "#<procedure module-obarray-remove! (ob key)>")) +(module-obarray-set! (groups Scheme) (scan-data "#<procedure module-obarray-set! (ob key val)>")) +(module-observe (groups Scheme) (scan-data "#<procedure module-observe (module proc)>")) +(module-observe-weak (groups Scheme) (scan-data "#<procedure module-observe-weak (module proc)>")) +(module-observer-id (groups Scheme) (scan-data "#<procedure module-observer-id (obj)>")) +(module-observers (groups Scheme) (scan-data "#<procedure module-observers (obj)>")) +(module-public-interface (groups Scheme) (scan-data "#<procedure module-public-interface (m)>")) +(module-re-export! (groups Scheme) (scan-data "#<procedure module-re-export! (m names)>")) +(module-ref (groups Scheme) (scan-data "#<procedure module-ref (module name . rest)>")) +(module-remove! (groups Scheme) (scan-data "#<procedure module-remove! (m v)>")) +(module-search (groups Scheme) (scan-data "#<procedure module-search (fn m v)>")) +(module-set! (groups Scheme) (scan-data "#<procedure module-set! (module name value)>")) +(module-symbol-binding (groups Scheme) (scan-data "#<procedure module-symbol-binding (m v . opt-val)>")) +(module-symbol-interned? (groups Scheme) (scan-data "#<procedure module-symbol-interned? (m v)>")) +(module-symbol-local-binding (groups Scheme) (scan-data "#<procedure module-symbol-local-binding (m v . opt-val)>")) +(module-symbol-locally-interned? (groups Scheme) (scan-data "#<procedure module-symbol-locally-interned? (m v)>")) +(module-transformer (groups Scheme) (scan-data "#<procedure module-transformer (obj)>")) +(module-type (groups Scheme) (scan-data "")) +(module-unobserve (groups Scheme) (scan-data "#<procedure module-unobserve (token)>")) +(module-use! (groups Scheme) (scan-data "#<procedure module-use! (module interface)>")) +(module-uses (groups Scheme) (scan-data "#<procedure module-uses (obj)>")) +(module-variable (groups Scheme) (scan-data "#<procedure module-variable (m v)>")) +(module-weak-observers (groups Scheme) (scan-data "#<procedure module-weak-observers (obj)>")) +(module? (groups Scheme) (scan-data "#<procedure module? (obj)>")) +(modulo (groups Scheme) (scan-data "#<primitive-procedure modulo>")) +(most-negative-fixnum (groups Scheme) (scan-data "")) +(most-positive-fixnum (groups Scheme) (scan-data "")) +(move->fdes (groups POSIX Scheme) (scan-data "#<procedure move->fdes (fd/port fd)>")) +(named-module-use! (groups Scheme) (scan-data "#<procedure named-module-use! (user usee)>")) +(nan (groups Scheme) (scan-data "#<primitive-procedure nan>")) +(nan? (groups Scheme) (scan-data "#<primitive-procedure nan?>")) +(negative? (groups Scheme) (scan-data "#<primitive-procedure negative?>")) +(nested-define! (groups Scheme) (scan-data "#<procedure nested-define! (root names val)>")) +(nested-ref (groups Scheme) (scan-data "#<procedure nested-ref (root names)>")) +(nested-remove! (groups Scheme) (scan-data "#<procedure nested-remove! (root names)>")) +(nested-set! (groups Scheme) (scan-data "#<procedure nested-set! (root names val)>")) +(netent:addrtype (groups Scheme) (scan-data "#<procedure netent:addrtype (obj)>")) +(netent:aliases (groups Scheme) (scan-data "#<procedure netent:aliases (obj)>")) +(netent:name (groups Scheme) (scan-data "#<procedure netent:name (obj)>")) +(netent:net (groups Scheme) (scan-data "#<procedure netent:net (obj)>")) +(newline (groups Scheme) (scan-data "#<primitive-procedure newline>")) +(nice (groups POSIX Scheme) (scan-data "#<primitive-procedure nice>")) +(nil-cond (groups Scheme) (scan-data "")) +(noop (groups Scheme) (scan-data "#<primitive-procedure noop>")) +(not (groups Scheme) (scan-data "#<primitive-procedure not>")) +(ntohl (groups Scheme) (scan-data "#<primitive-procedure ntohl>")) +(ntohs (groups Scheme) (scan-data "#<primitive-procedure ntohs>")) +(null? (groups Scheme) (scan-data "#<primitive-procedure null?>")) +(number->string (groups Scheme) (scan-data "#<primitive-procedure number->string>")) +(number? (groups Scheme) (scan-data "#<primitive-procedure number?>")) +(object->string (groups Scheme) (scan-data "#<primitive-procedure object->string>")) +(object-address (groups Scheme) (scan-data "#<primitive-procedure object-address>")) +(object-properties (groups Scheme) (scan-data "#<primitive-procedure object-properties>")) +(object-property (groups Scheme) (scan-data "#<primitive-procedure object-property>")) +(odd? (groups Scheme) (scan-data "#<primitive-procedure odd?>")) +(open (groups POSIX Scheme) (scan-data "#<primitive-procedure open>")) +(open-fdes (groups POSIX Scheme) (scan-data "#<primitive-procedure open-fdes>")) +(open-file (groups Scheme) (scan-data "#<primitive-procedure open-file>")) +(open-input-file (groups Scheme) (scan-data "#<procedure open-input-file (str)>")) +(open-input-string (groups Scheme) (scan-data "#<primitive-procedure open-input-string>")) +(open-io-file (groups Scheme) (scan-data "#<procedure open-io-file (str)>")) +(open-output-file (groups Scheme) (scan-data "#<procedure open-output-file (str)>")) +(open-output-string (groups Scheme) (scan-data "#<primitive-procedure open-output-string>")) +(opendir (groups POSIX Scheme) (scan-data "#<primitive-procedure opendir>")) +(operator? (groups Scheme) (scan-data "#<primitive-procedure operator?>")) +(or (groups Scheme) (scan-data "")) +(or-map (groups Scheme) (scan-data "#<procedure or-map (f lst)>")) +(output-port? (groups Scheme) (scan-data "#<primitive-procedure output-port?>")) +(pair? (groups Scheme) (scan-data "#<primitive-procedure pair?>")) +(parse-path (groups Scheme) (scan-data "#<primitive-procedure parse-path>")) +(passwd:dir (groups POSIX Scheme) (scan-data "#<procedure passwd:dir (obj)>")) +(passwd:gecos (groups POSIX Scheme) (scan-data "#<procedure passwd:gecos (obj)>")) +(passwd:gid (groups POSIX Scheme) (scan-data "#<procedure passwd:gid (obj)>")) +(passwd:name (groups POSIX Scheme) (scan-data "#<procedure passwd:name (obj)>")) +(passwd:passwd (groups POSIX Scheme) (scan-data "#<procedure passwd:passwd (obj)>")) +(passwd:shell (groups POSIX Scheme) (scan-data "#<procedure passwd:shell (obj)>")) +(passwd:uid (groups POSIX Scheme) (scan-data "#<procedure passwd:uid (obj)>")) +(pause (groups POSIX Scheme) (scan-data "#<primitive-procedure pause>")) +(peek (groups Scheme) (scan-data "#<procedure peek stuff>")) +(peek-char (groups Scheme) (scan-data "#<primitive-procedure peek-char>")) +(pipe (groups POSIX Scheme) (scan-data "#<primitive-procedure pipe>")) +(pk (groups Scheme) (scan-data "#<procedure peek stuff>")) +(port->fdes (groups POSIX Scheme) (scan-data "#<procedure port->fdes (port)>")) +(port-closed? (groups Scheme) (scan-data "#<primitive-procedure port-closed?>")) +(port-column (groups Scheme) (scan-data "#<primitive-procedure port-column>")) +(port-filename (groups Scheme) (scan-data "#<primitive-procedure port-filename>")) +(port-for-each (groups POSIX Scheme) (scan-data "#<primitive-procedure port-for-each>")) +(port-line (groups Scheme) (scan-data "#<primitive-procedure port-line>")) +(port-mode (groups POSIX Scheme) (scan-data "#<primitive-procedure port-mode>")) +(port-revealed (groups POSIX Scheme) (scan-data "#<primitive-procedure port-revealed>")) +(port-with-print-state (groups Scheme) (scan-data "#<primitive-procedure port-with-print-state>")) +(port? (groups Scheme) (scan-data "#<primitive-procedure port?>")) +(positive? (groups Scheme) (scan-data "#<primitive-procedure positive?>")) +(primitive-eval (groups Scheme) (scan-data "#<primitive-procedure primitive-eval>")) +(primitive-exit (groups POSIX Scheme) (scan-data "#<primitive-procedure primitive-exit>")) +(primitive-fork (groups POSIX Scheme) (scan-data "#<primitive-procedure primitive-fork>")) +(primitive-load (groups Scheme) (scan-data "#<primitive-procedure primitive-load>")) +(primitive-load-path (groups Scheme) (scan-data "#<primitive-procedure primitive-load-path>")) +(primitive-macro? (groups Scheme) (scan-data "#<procedure primitive-macro? (m)>")) +(primitive-make-property (groups Scheme) (scan-data "#<primitive-procedure primitive-make-property>")) +(primitive-move->fdes (groups POSIX Scheme) (scan-data "#<primitive-procedure primitive-move->fdes>")) +(primitive-property-del! (groups Scheme) (scan-data "#<primitive-procedure primitive-property-del!>")) +(primitive-property-ref (groups Scheme) (scan-data "#<primitive-procedure primitive-property-ref>")) +(primitive-property-set! (groups Scheme) (scan-data "#<primitive-procedure primitive-property-set!>")) +(print-disable (groups Scheme) (scan-data "#<procedure print-disable flags>")) +(print-enable (groups Scheme) (scan-data "#<procedure print-enable flags>")) +(print-options (groups Scheme) (scan-data "#<procedure print-options args>")) +(print-options-interface (groups Scheme) (scan-data "#<primitive-procedure print-options-interface>")) +(print-set! (groups Scheme) (scan-data "")) +(procedure (groups Scheme) (scan-data "#<primitive-procedure procedure>")) +(procedure->macro (groups Scheme) (scan-data "#<primitive-procedure procedure->macro>")) +(procedure->memoizing-macro (groups Scheme) (scan-data "#<primitive-procedure procedure->memoizing-macro>")) +(procedure->syntax (groups Scheme) (scan-data "#<primitive-procedure procedure->syntax>")) +(procedure-documentation (groups Scheme) (scan-data "#<primitive-procedure procedure-documentation>")) +(procedure-environment (groups Scheme) (scan-data "#<primitive-procedure procedure-environment>")) +(procedure-name (groups Scheme) (scan-data "#<primitive-procedure procedure-name>")) +(procedure-properties (groups Scheme) (scan-data "#<primitive-procedure procedure-properties>")) +(procedure-property (groups Scheme) (scan-data "#<primitive-procedure procedure-property>")) +(procedure-source (groups Scheme) (scan-data "#<primitive-procedure procedure-source>")) +(procedure-with-setter? (groups Scheme) (scan-data "#<primitive-procedure procedure-with-setter?>")) +(procedure? (groups Scheme) (scan-data "#<primitive-procedure procedure?>")) +(process-define-module (groups Scheme) (scan-data "#<procedure process-define-module (args)>")) +(process-use-modules (groups Scheme) (scan-data "#<procedure process-use-modules (module-interface-args)>")) +(program-arguments (groups POSIX Scheme) (scan-data "#<primitive-procedure program-arguments>")) +(promise? (groups Scheme) (scan-data "#<primitive-procedure promise?>")) +(protoent:aliases (groups Scheme) (scan-data "#<procedure protoent:aliases (obj)>")) +(protoent:name (groups Scheme) (scan-data "#<procedure protoent:name (obj)>")) +(protoent:proto (groups Scheme) (scan-data "#<procedure protoent:proto (obj)>")) +(provide (groups Scheme) (scan-data "#<procedure provide (sym)>")) +(provided? (groups Scheme) (scan-data "#<procedure provided? (feature)>")) +(purify-module! (groups Scheme) (scan-data "#<procedure purify-module! (module)>")) +(putenv (groups POSIX Scheme) (scan-data "#<primitive-procedure putenv>")) +(quasiquote (groups Scheme) (scan-data "")) +(quit (groups Scheme) (scan-data "#<procedure quit args>")) +(quote (groups Scheme) (scan-data "")) +(quotient (groups Scheme) (scan-data "#<primitive-procedure quotient>")) +(raise (groups POSIX Scheme) (scan-data "#<primitive-procedure raise>")) +(random (groups Scheme) (scan-data "#<primitive-procedure random>")) +(random:exp (groups Scheme) (scan-data "#<primitive-procedure random:exp>")) +(random:hollow-sphere! (groups Scheme) (scan-data "#<primitive-procedure random:hollow-sphere!>")) +(random:normal (groups Scheme) (scan-data "#<primitive-procedure random:normal>")) +(random:normal-vector! (groups Scheme) (scan-data "#<primitive-procedure random:normal-vector!>")) +(random:solid-sphere! (groups Scheme) (scan-data "#<primitive-procedure random:solid-sphere!>")) +(random:uniform (groups Scheme) (scan-data "#<primitive-procedure random:uniform>")) +(rational? (groups Scheme) (scan-data "#<primitive-procedure rational?>")) +(re-export (groups Scheme) (scan-data "")) +(re-export-syntax (groups Scheme) (scan-data "")) +(read (groups Scheme) (scan-data "#<primitive-procedure read>")) +(read-char (groups Scheme) (scan-data "#<primitive-procedure read-char>")) +(read-disable (groups Scheme) (scan-data "#<procedure read-disable flags>")) +(read-enable (groups Scheme) (scan-data "#<procedure read-enable flags>")) +(read-eval? (groups Scheme) (scan-data "")) +(read-hash-extend (groups Scheme) (scan-data "#<primitive-procedure read-hash-extend>")) +(read-hash-procedures (groups Scheme) (scan-data "")) +(read-options (groups Scheme) (scan-data "#<procedure read-options args>")) +(read-options-interface (groups Scheme) (scan-data "#<primitive-procedure read-options-interface>")) +(read-set! (groups Scheme) (scan-data "")) +(read:array (groups Scheme) (scan-data "#<procedure read:array (digit port)>")) +(read:uniform-vector (groups Scheme) (scan-data "#<procedure read:uniform-vector (proto port)>")) +(readdir (groups POSIX Scheme) (scan-data "#<primitive-procedure readdir>")) +(readlink (groups POSIX Scheme) (scan-data "#<primitive-procedure readlink>")) +(real-part (groups Scheme) (scan-data "#<primitive-procedure real-part>")) +(real? (groups Scheme) (scan-data "#<primitive-procedure real?>")) +(record-accessor (groups Scheme) (scan-data "#<procedure record-accessor (rtd field-name)>")) +(record-constructor (groups Scheme) (scan-data "#<procedure record-constructor (rtd . opt)>")) +(record-modifier (groups Scheme) (scan-data "#<procedure record-modifier (rtd field-name)>")) +(record-predicate (groups Scheme) (scan-data "#<procedure record-predicate (rtd)>")) +(record-type-descriptor (groups Scheme) (scan-data "#<procedure record-type-descriptor (obj)>")) +(record-type-fields (groups Scheme) (scan-data "#<procedure record-type-fields (obj)>")) +(record-type-name (groups Scheme) (scan-data "#<procedure record-type-name (obj)>")) +(record-type-vtable (groups Scheme) (scan-data "")) +(record-type? (groups Scheme) (scan-data "#<procedure record-type? (obj)>")) +(record? (groups Scheme) (scan-data "#<procedure record? (obj)>")) +(recv! (groups Scheme) (scan-data "#<primitive-procedure recv!>")) +(recvfrom! (groups Scheme) (scan-data "#<primitive-procedure recvfrom!>")) +(redirect-port (groups POSIX Scheme) (scan-data "#<primitive-procedure redirect-port>")) +(regexp-exec (groups Scheme) (scan-data "#<primitive-procedure regexp-exec>")) +(regexp/basic (groups Scheme) (scan-data "")) +(regexp/extended (groups Scheme) (scan-data "")) +(regexp/icase (groups Scheme) (scan-data "")) +(regexp/newline (groups Scheme) (scan-data "")) +(regexp/notbol (groups Scheme) (scan-data "")) +(regexp/noteol (groups Scheme) (scan-data "")) +(regexp? (groups Scheme) (scan-data "#<primitive-procedure regexp?>")) +(release-arbiter (groups Scheme) (scan-data "#<primitive-procedure release-arbiter>")) +(release-port-handle (groups POSIX Scheme) (scan-data "#<procedure release-port-handle (port)>")) +(remainder (groups Scheme) (scan-data "#<primitive-procedure remainder>")) +(remove-hook! (groups Scheme) (scan-data "#<primitive-procedure remove-hook!>")) +(rename-file (groups POSIX Scheme) (scan-data "#<primitive-procedure rename-file>")) +(repl (groups Scheme) (scan-data "#<procedure repl (read evaler print)>")) +(repl-reader (groups Scheme) (scan-data "#<procedure repl-reader (prompt)>")) +(reset-hook! (groups Scheme) (scan-data "#<primitive-procedure reset-hook!>")) +(resolve-interface (groups Scheme) (scan-data "#<procedure resolve-interface (name . args)>")) +(resolve-module (groups Scheme) (scan-data "#<procedure resolve-module (name . maybe-autoload)>")) +(restore-signals (groups POSIX Scheme) (scan-data "#<primitive-procedure restore-signals>")) +(restricted-vector-sort! (groups Scheme) (scan-data "#<primitive-procedure restricted-vector-sort!>")) +(reverse (groups Scheme) (scan-data "#<primitive-procedure reverse>")) +(reverse! (groups Scheme) (scan-data "#<primitive-procedure reverse!>")) +(rewinddir (groups POSIX Scheme) (scan-data "#<primitive-procedure rewinddir>")) +(rmdir (groups POSIX Scheme) (scan-data "#<primitive-procedure rmdir>")) +(round (groups Scheme) (scan-data "#<primitive-procedure round>")) +(run-asyncs (groups Scheme) (scan-data "#<primitive-procedure run-asyncs>")) +(run-hook (groups Scheme) (scan-data "#<primitive-procedure run-hook>")) +(save-module-excursion (groups Scheme) (scan-data "#<procedure save-module-excursion (thunk)>")) +(save-stack (groups Scheme) (scan-data "#<procedure save-stack narrowing>")) +(scheme-file-suffix (groups Scheme) (scan-data "#<procedure scheme-file-suffix ()>")) +(scm-error (groups Scheme) (scan-data "#<primitive-procedure scm-error>")) +(scm-repl-print-unspecified (groups Scheme) (scan-data "")) +(scm-repl-prompt (groups Scheme) (scan-data "")) +(scm-repl-silent (groups Scheme) (scan-data "")) +(scm-repl-verbose (groups Scheme) (scan-data "")) +(scm-style-repl (groups Scheme) (scan-data "#<procedure scm-style-repl ()>")) +(scm_I_am_dead (groups scm C) (scan-data B)) +(scm_abs (groups scm C) (scan-data T)) +(scm_accept (groups scm C) (scan-data T)) +(scm_access (groups scm C) (scan-data T)) +(scm_accessor_method_slot_definition (groups scm C) (scan-data T)) +(scm_acons (groups scm C) (scan-data T)) +(scm_acosh (groups scm C) (scan-data T)) +(scm_add_feature (groups scm C) (scan-data T)) +(scm_add_hook_x (groups scm C) (scan-data T)) +(scm_add_method (groups scm C) (scan-data T)) +(scm_add_slot (groups scm C) (scan-data T)) +(scm_add_to_port_table (groups scm C) (scan-data T)) +(scm_addbig (groups scm C) (scan-data T)) +(scm_after_gc_c_hook (groups scm C) (scan-data B)) +(scm_after_gc_hook (groups scm C) (scan-data B)) +(scm_after_sweep_c_hook (groups scm C) (scan-data B)) +(scm_aind (groups scm C) (scan-data T)) +(scm_alarm (groups scm C) (scan-data T)) +(scm_alloc_struct (groups scm C) (scan-data T)) +(scm_allocate_string (groups scm C) (scan-data T)) +(scm_angle (groups scm C) (scan-data T)) +(scm_append (groups scm C) (scan-data T)) +(scm_append_x (groups scm C) (scan-data T)) +(scm_apply (groups scm C) (scan-data T)) +(scm_apply_0 (groups scm C) (scan-data T)) +(scm_apply_1 (groups scm C) (scan-data T)) +(scm_apply_2 (groups scm C) (scan-data T)) +(scm_apply_3 (groups scm C) (scan-data T)) +(scm_apply_generic (groups scm C) (scan-data T)) +(scm_apply_with_dynamic_root (groups scm C) (scan-data T)) +(scm_arg_type_key (groups scm C) (scan-data B)) +(scm_args_number_key (groups scm C) (scan-data B)) +(scm_array_contents (groups scm C) (scan-data T)) +(scm_array_copy_x (groups scm C) (scan-data T)) +(scm_array_dimensions (groups scm C) (scan-data T)) +(scm_array_equal_p (groups scm C) (scan-data T)) +(scm_array_fill_x (groups scm C) (scan-data T)) +(scm_array_for_each (groups scm C) (scan-data T)) +(scm_array_identity (groups scm C) (scan-data T)) +(scm_array_in_bounds_p (groups scm C) (scan-data T)) +(scm_array_index_map_x (groups scm C) (scan-data T)) +(scm_array_map_x (groups scm C) (scan-data T)) +(scm_array_p (groups scm C) (scan-data T)) +(scm_array_prototype (groups scm C) (scan-data T)) +(scm_array_rank (groups scm C) (scan-data T)) +(scm_array_set_x (groups scm C) (scan-data T)) +(scm_array_to_list (groups scm C) (scan-data T)) +(scm_ash (groups scm C) (scan-data T)) +(scm_asinh (groups scm C) (scan-data T)) +(scm_assoc (groups scm C) (scan-data T)) +(scm_assoc_ref (groups scm C) (scan-data T)) +(scm_assoc_remove_x (groups scm C) (scan-data T)) +(scm_assoc_set_x (groups scm C) (scan-data T)) +(scm_assq (groups scm C) (scan-data T)) +(scm_assq_ref (groups scm C) (scan-data T)) +(scm_assq_remove_x (groups scm C) (scan-data T)) +(scm_assq_set_x (groups scm C) (scan-data T)) +(scm_assv (groups scm C) (scan-data T)) +(scm_assv_ref (groups scm C) (scan-data T)) +(scm_assv_remove_x (groups scm C) (scan-data T)) +(scm_assv_set_x (groups scm C) (scan-data T)) +(scm_async (groups scm C) (scan-data T)) +(scm_async_click (groups scm C) (scan-data T)) +(scm_async_mark (groups scm C) (scan-data T)) +(scm_asyncs_pending_p (groups scm C) (scan-data D)) +(scm_atanh (groups scm C) (scan-data T)) +(scm_backtrace (groups scm C) (scan-data T)) +(scm_badargsp (groups scm C) (scan-data T)) +(scm_basename (groups scm C) (scan-data T)) +(scm_basic_basic_make_class (groups scm C) (scan-data T)) +(scm_basic_make_class (groups scm C) (scan-data T)) +(scm_before_gc_c_hook (groups scm C) (scan-data B)) +(scm_before_mark_c_hook (groups scm C) (scan-data B)) +(scm_before_sweep_c_hook (groups scm C) (scan-data B)) +(scm_big_and (groups scm C) (scan-data T)) +(scm_big_ior (groups scm C) (scan-data T)) +(scm_big_test (groups scm C) (scan-data T)) +(scm_big_xor (groups scm C) (scan-data T)) +(scm_bigcomp (groups scm C) (scan-data T)) +(scm_bigequal (groups scm C) (scan-data T)) +(scm_bigprint (groups scm C) (scan-data T)) +(scm_bind (groups scm C) (scan-data T)) +(scm_bit_count (groups scm C) (scan-data T)) +(scm_bit_count_star (groups scm C) (scan-data T)) +(scm_bit_extract (groups scm C) (scan-data T)) +(scm_bit_invert_x (groups scm C) (scan-data T)) +(scm_bit_position (groups scm C) (scan-data T)) +(scm_bit_set_star_x (groups scm C) (scan-data T)) +(scm_block_gc (groups scm C) (scan-data D)) +(scm_body_thunk (groups scm C) (scan-data T)) +(scm_boolean_p (groups scm C) (scan-data T)) +(scm_boot_guile (groups scm C) (scan-data T)) +(scm_boot_guile_1_live (groups scm C) (scan-data D)) +(scm_c_call_with_current_module (groups scm C) (scan-data T)) +(scm_c_chars2byvect (groups scm C) (scan-data T)) +(scm_c_chars2scm (groups scm C) (scan-data T)) +(scm_c_default_rstate (groups scm C) (scan-data T)) +(scm_c_define (groups scm C) (scan-data T)) +(scm_c_define_gsubr (groups scm C) (scan-data T)) +(scm_c_define_gsubr_with_generic (groups scm C) (scan-data T)) +(scm_c_define_module (groups scm C) (scan-data T)) +(scm_c_define_subr (groups scm C) (scan-data T)) +(scm_c_define_subr_with_generic (groups scm C) (scan-data T)) +(scm_c_doubles2dvect (groups scm C) (scan-data T)) +(scm_c_doubles2scm (groups scm C) (scan-data T)) +(scm_c_environment_cell (groups scm C) (scan-data T)) +(scm_c_environment_fold (groups scm C) (scan-data T)) +(scm_c_environment_observe (groups scm C) (scan-data T)) +(scm_c_environment_ref (groups scm C) (scan-data T)) +(scm_c_eval_string (groups scm C) (scan-data T)) +(scm_c_exp1 (groups scm C) (scan-data T)) +(scm_c_export (groups scm C) (scan-data T)) +(scm_c_floats2fvect (groups scm C) (scan-data T)) +(scm_c_floats2scm (groups scm C) (scan-data T)) +(scm_c_get_internal_run_time (groups scm C) (scan-data T)) +(scm_c_hook_add (groups scm C) (scan-data T)) +(scm_c_hook_init (groups scm C) (scan-data T)) +(scm_c_hook_remove (groups scm C) (scan-data T)) +(scm_c_hook_run (groups scm C) (scan-data T)) +(scm_c_ints2ivect (groups scm C) (scan-data T)) +(scm_c_ints2scm (groups scm C) (scan-data T)) +(scm_c_issue_deprecation_warning (groups scm C) (scan-data T)) +(scm_c_issue_deprecation_warning_fmt (groups scm C) (scan-data T)) +(scm_c_load_extension (groups scm C) (scan-data T)) +(scm_c_longs2ivect (groups scm C) (scan-data T)) +(scm_c_longs2scm (groups scm C) (scan-data T)) +(scm_c_lookup (groups scm C) (scan-data T)) +(scm_c_make_gsubr (groups scm C) (scan-data T)) +(scm_c_make_gsubr_with_generic (groups scm C) (scan-data T)) +(scm_c_make_hash_table (groups scm C) (scan-data T)) +(scm_c_make_keyword (groups scm C) (scan-data T)) +(scm_c_make_rstate (groups scm C) (scan-data T)) +(scm_c_make_subr (groups scm C) (scan-data T)) +(scm_c_make_subr_with_generic (groups scm C) (scan-data T)) +(scm_c_make_vector (groups scm C) (scan-data T)) +(scm_c_memq (groups scm C) (scan-data T)) +(scm_c_module_define (groups scm C) (scan-data T)) +(scm_c_module_lookup (groups scm C) (scan-data T)) +(scm_c_normal01 (groups scm C) (scan-data T)) +(scm_c_primitive_load (groups scm C) (scan-data T)) +(scm_c_primitive_load_path (groups scm C) (scan-data T)) +(scm_c_random (groups scm C) (scan-data T)) +(scm_c_random_bignum (groups scm C) (scan-data T)) +(scm_c_read (groups scm C) (scan-data T)) +(scm_c_read_string (groups scm C) (scan-data T)) +(scm_c_register_extension (groups scm C) (scan-data T)) +(scm_c_resolve_module (groups scm C) (scan-data T)) +(scm_c_run_hook (groups scm C) (scan-data T)) +(scm_c_scm2chars (groups scm C) (scan-data T)) +(scm_c_scm2doubles (groups scm C) (scan-data T)) +(scm_c_scm2floats (groups scm C) (scan-data T)) +(scm_c_scm2ints (groups scm C) (scan-data T)) +(scm_c_scm2longs (groups scm C) (scan-data T)) +(scm_c_scm2shorts (groups scm C) (scan-data T)) +(scm_c_shorts2scm (groups scm C) (scan-data T)) +(scm_c_shorts2svect (groups scm C) (scan-data T)) +(scm_c_source_property_breakpoint_p (groups scm C) (scan-data T)) +(scm_c_string2str (groups scm C) (scan-data T)) +(scm_c_substring2str (groups scm C) (scan-data T)) +(scm_c_symbol2str (groups scm C) (scan-data T)) +(scm_c_uints2uvect (groups scm C) (scan-data T)) +(scm_c_ulongs2uvect (groups scm C) (scan-data T)) +(scm_c_uniform01 (groups scm C) (scan-data T)) +(scm_c_use_module (groups scm C) (scan-data T)) +(scm_c_with_fluid (groups scm C) (scan-data T)) +(scm_c_with_fluids (groups scm C) (scan-data T)) +(scm_c_write (groups scm C) (scan-data T)) +(scm_call_0 (groups scm C) (scan-data T)) +(scm_call_1 (groups scm C) (scan-data T)) +(scm_call_2 (groups scm C) (scan-data T)) +(scm_call_3 (groups scm C) (scan-data T)) +(scm_call_4 (groups scm C) (scan-data T)) +(scm_call_generic_0 (groups scm C) (scan-data T)) +(scm_call_generic_1 (groups scm C) (scan-data T)) +(scm_call_generic_2 (groups scm C) (scan-data T)) +(scm_call_generic_3 (groups scm C) (scan-data T)) +(scm_call_with_dynamic_root (groups scm C) (scan-data T)) +(scm_call_with_input_string (groups scm C) (scan-data T)) +(scm_call_with_new_thread (groups scm C) (scan-data T)) +(scm_call_with_output_string (groups scm C) (scan-data T)) +(scm_casei_streq (groups scm C) (scan-data T)) +(scm_catch (groups scm C) (scan-data T)) +(scm_cellp (groups scm C) (scan-data T)) +(scm_cells_allocated (groups scm C) (scan-data D)) +(scm_ceval (groups scm C) (scan-data T)) +(scm_ceval_ptr (groups scm C) (scan-data B)) +(scm_change_object_class (groups scm C) (scan-data T)) +(scm_char_alphabetic_p (groups scm C) (scan-data T)) +(scm_char_ci_eq_p (groups scm C) (scan-data T)) +(scm_char_ci_geq_p (groups scm C) (scan-data T)) +(scm_char_ci_gr_p (groups scm C) (scan-data T)) +(scm_char_ci_leq_p (groups scm C) (scan-data T)) +(scm_char_ci_less_p (groups scm C) (scan-data T)) +(scm_char_downcase (groups scm C) (scan-data T)) +(scm_char_eq_p (groups scm C) (scan-data T)) +(scm_char_geq_p (groups scm C) (scan-data T)) +(scm_char_gr_p (groups scm C) (scan-data T)) +(scm_char_is_both_p (groups scm C) (scan-data T)) +(scm_char_leq_p (groups scm C) (scan-data T)) +(scm_char_less_p (groups scm C) (scan-data T)) +(scm_char_lower_case_p (groups scm C) (scan-data T)) +(scm_char_numeric_p (groups scm C) (scan-data T)) +(scm_char_p (groups scm C) (scan-data T)) +(scm_char_ready_p (groups scm C) (scan-data T)) +(scm_char_to_integer (groups scm C) (scan-data T)) +(scm_char_upcase (groups scm C) (scan-data T)) +(scm_char_upper_case_p (groups scm C) (scan-data T)) +(scm_char_whitespace_p (groups scm C) (scan-data T)) +(scm_charnames (groups scm C) (scan-data D)) +(scm_charnums (groups scm C) (scan-data R)) +(scm_chdir (groups scm C) (scan-data T)) +(scm_check_apply_p (groups scm C) (scan-data B)) +(scm_check_entry_p (groups scm C) (scan-data B)) +(scm_check_exit_p (groups scm C) (scan-data B)) +(scm_chmod (groups scm C) (scan-data T)) +(scm_chown (groups scm C) (scan-data T)) +(scm_chroot (groups scm C) (scan-data T)) +(scm_class_accessor (groups scm C) (scan-data B)) +(scm_class_boolean (groups scm C) (scan-data B)) +(scm_class_char (groups scm C) (scan-data B)) +(scm_class_class (groups scm C) (scan-data B)) +(scm_class_complex (groups scm C) (scan-data B)) +(scm_class_direct_methods (groups scm C) (scan-data T)) +(scm_class_direct_slots (groups scm C) (scan-data T)) +(scm_class_direct_subclasses (groups scm C) (scan-data T)) +(scm_class_direct_supers (groups scm C) (scan-data T)) +(scm_class_double (groups scm C) (scan-data B)) +(scm_class_entity (groups scm C) (scan-data B)) +(scm_class_entity_class (groups scm C) (scan-data B)) +(scm_class_entity_with_setter (groups scm C) (scan-data B)) +(scm_class_environment (groups scm C) (scan-data T)) +(scm_class_float (groups scm C) (scan-data B)) +(scm_class_foreign_class (groups scm C) (scan-data B)) +(scm_class_foreign_object (groups scm C) (scan-data B)) +(scm_class_foreign_slot (groups scm C) (scan-data B)) +(scm_class_generic (groups scm C) (scan-data B)) +(scm_class_generic_with_setter (groups scm C) (scan-data B)) +(scm_class_input_output_port (groups scm C) (scan-data B)) +(scm_class_input_port (groups scm C) (scan-data B)) +(scm_class_int (groups scm C) (scan-data B)) +(scm_class_integer (groups scm C) (scan-data B)) +(scm_class_keyword (groups scm C) (scan-data B)) +(scm_class_list (groups scm C) (scan-data B)) +(scm_class_method (groups scm C) (scan-data B)) +(scm_class_name (groups scm C) (scan-data T)) +(scm_class_null (groups scm C) (scan-data B)) +(scm_class_number (groups scm C) (scan-data B)) +(scm_class_object (groups scm C) (scan-data B)) +(scm_class_of (groups scm C) (scan-data T)) +(scm_class_opaque (groups scm C) (scan-data B)) +(scm_class_operator_class (groups scm C) (scan-data B)) +(scm_class_operator_with_setter_class (groups scm C) (scan-data B)) +(scm_class_output_port (groups scm C) (scan-data B)) +(scm_class_pair (groups scm C) (scan-data B)) +(scm_class_port (groups scm C) (scan-data B)) +(scm_class_precedence_list (groups scm C) (scan-data T)) +(scm_class_primitive_generic (groups scm C) (scan-data B)) +(scm_class_procedure (groups scm C) (scan-data B)) +(scm_class_procedure_class (groups scm C) (scan-data B)) +(scm_class_procedure_with_setter (groups scm C) (scan-data B)) +(scm_class_protected (groups scm C) (scan-data B)) +(scm_class_protected_opaque (groups scm C) (scan-data B)) +(scm_class_protected_read_only (groups scm C) (scan-data B)) +(scm_class_read_only (groups scm C) (scan-data B)) +(scm_class_real (groups scm C) (scan-data B)) +(scm_class_scm (groups scm C) (scan-data B)) +(scm_class_self (groups scm C) (scan-data B)) +(scm_class_simple_method (groups scm C) (scan-data B)) +(scm_class_slots (groups scm C) (scan-data T)) +(scm_class_string (groups scm C) (scan-data B)) +(scm_class_symbol (groups scm C) (scan-data B)) +(scm_class_top (groups scm C) (scan-data B)) +(scm_class_unknown (groups scm C) (scan-data B)) +(scm_class_vector (groups scm C) (scan-data B)) +(scm_close (groups scm C) (scan-data T)) +(scm_close_fdes (groups scm C) (scan-data T)) +(scm_close_input_port (groups scm C) (scan-data T)) +(scm_close_output_port (groups scm C) (scan-data T)) +(scm_close_port (groups scm C) (scan-data T)) +(scm_closedir (groups scm C) (scan-data T)) +(scm_closure (groups scm C) (scan-data T)) +(scm_closure_p (groups scm C) (scan-data T)) +(scm_compile_shell_switches (groups scm C) (scan-data T)) +(scm_complex_equalp (groups scm C) (scan-data T)) +(scm_components (groups scm C) (scan-data B)) +(scm_compute_applicable_methods (groups scm C) (scan-data T)) +(scm_connect (groups scm C) (scan-data T)) +(scm_cons (groups scm C) (scan-data T)) +(scm_cons2 (groups scm C) (scan-data T)) +(scm_cons_source (groups scm C) (scan-data T)) +(scm_cons_star (groups scm C) (scan-data T)) +(scm_copy_big_dec (groups scm C) (scan-data T)) +(scm_copy_file (groups scm C) (scan-data T)) +(scm_copy_fluids (groups scm C) (scan-data T)) +(scm_copy_random_state (groups scm C) (scan-data T)) +(scm_copy_smaller (groups scm C) (scan-data T)) +(scm_copy_tree (groups scm C) (scan-data T)) +(scm_count_argv (groups scm C) (scan-data T)) +(scm_critical_section_mutex (groups scm C) (scan-data B)) +(scm_crypt (groups scm C) (scan-data T)) +(scm_ctermid (groups scm C) (scan-data T)) +(scm_current_error_port (groups scm C) (scan-data T)) +(scm_current_input_port (groups scm C) (scan-data T)) +(scm_current_load_port (groups scm C) (scan-data T)) +(scm_current_module (groups scm C) (scan-data T)) +(scm_current_module_lookup_closure (groups scm C) (scan-data T)) +(scm_current_module_transformer (groups scm C) (scan-data T)) +(scm_current_output_port (groups scm C) (scan-data T)) +(scm_current_time (groups scm C) (scan-data T)) +(scm_cuserid (groups scm C) (scan-data T)) +(scm_cvref (groups scm C) (scan-data T)) +(scm_dapply (groups scm C) (scan-data T)) +(scm_dblprec (groups scm C) (scan-data B)) +(scm_debug_eframe_size (groups scm C) (scan-data B)) +(scm_debug_mode (groups scm C) (scan-data B)) +(scm_debug_object_p (groups scm C) (scan-data T)) +(scm_debug_options (groups scm C) (scan-data T)) +(scm_debug_opts (groups scm C) (scan-data D)) +(scm_default_init_heap_size_1 (groups scm C) (scan-data D)) +(scm_default_init_heap_size_2 (groups scm C) (scan-data D)) +(scm_default_max_segment_size (groups scm C) (scan-data D)) +(scm_default_min_yield_1 (groups scm C) (scan-data D)) +(scm_default_min_yield_2 (groups scm C) (scan-data D)) +(scm_define (groups scm C) (scan-data T)) +(scm_definedp (groups scm C) (scan-data T)) +(scm_delete (groups scm C) (scan-data T)) +(scm_delete1_x (groups scm C) (scan-data T)) +(scm_delete_file (groups scm C) (scan-data T)) +(scm_delete_x (groups scm C) (scan-data T)) +(scm_delq (groups scm C) (scan-data T)) +(scm_delq1_x (groups scm C) (scan-data T)) +(scm_delq_x (groups scm C) (scan-data T)) +(scm_delv (groups scm C) (scan-data T)) +(scm_delv1_x (groups scm C) (scan-data T)) +(scm_delv_x (groups scm C) (scan-data T)) +(scm_deprecated_newcell (groups scm C) (scan-data T)) +(scm_deprecated_newcell2 (groups scm C) (scan-data T)) +(scm_destroy_guardian_x (groups scm C) (scan-data T)) +(scm_deval (groups scm C) (scan-data T)) +(scm_difference (groups scm C) (scan-data T)) +(scm_dimensions_to_uniform_array (groups scm C) (scan-data T)) +(scm_directory_stream_p (groups scm C) (scan-data T)) +(scm_dirname (groups scm C) (scan-data T)) +(scm_display (groups scm C) (scan-data T)) +(scm_display_application (groups scm C) (scan-data T)) +(scm_display_backtrace (groups scm C) (scan-data T)) +(scm_display_error (groups scm C) (scan-data T)) +(scm_display_error_message (groups scm C) (scan-data T)) +(scm_divbigdig (groups scm C) (scan-data T)) +(scm_divide (groups scm C) (scan-data T)) +(scm_done_free (groups scm C) (scan-data T)) +(scm_done_malloc (groups scm C) (scan-data T)) +(scm_dot_string (groups scm C) (scan-data B)) +(scm_double2num (groups scm C) (scan-data T)) +(scm_doubly_weak_hash_table_p (groups scm C) (scan-data T)) +(scm_dowinds (groups scm C) (scan-data T)) +(scm_downcase (groups scm C) (scan-data T)) +(scm_drain_input (groups scm C) (scan-data T)) +(scm_dup2 (groups scm C) (scan-data T)) +(scm_dup_to_fdes (groups scm C) (scan-data T)) +(scm_dynamic_args_call (groups scm C) (scan-data T)) +(scm_dynamic_call (groups scm C) (scan-data T)) +(scm_dynamic_func (groups scm C) (scan-data T)) +(scm_dynamic_link (groups scm C) (scan-data T)) +(scm_dynamic_object_p (groups scm C) (scan-data T)) +(scm_dynamic_root (groups scm C) (scan-data T)) +(scm_dynamic_unlink (groups scm C) (scan-data T)) +(scm_dynamic_wind (groups scm C) (scan-data T)) +(scm_enable_primitive_generic_x (groups scm C) (scan-data T)) +(scm_enclose_array (groups scm C) (scan-data T)) +(scm_end_input (groups scm C) (scan-data T)) +(scm_ensure_accessor (groups scm C) (scan-data T)) +(scm_entity_p (groups scm C) (scan-data T)) +(scm_env_module (groups scm C) (scan-data T)) +(scm_env_top_level (groups scm C) (scan-data T)) +(scm_environ (groups scm C) (scan-data T)) +(scm_environment_bound_p (groups scm C) (scan-data T)) +(scm_environment_cell (groups scm C) (scan-data T)) +(scm_environment_define (groups scm C) (scan-data T)) +(scm_environment_fold (groups scm C) (scan-data T)) +(scm_environment_observe (groups scm C) (scan-data T)) +(scm_environment_observe_weak (groups scm C) (scan-data T)) +(scm_environment_p (groups scm C) (scan-data T)) +(scm_environment_ref (groups scm C) (scan-data T)) +(scm_environment_set_x (groups scm C) (scan-data T)) +(scm_environment_undefine (groups scm C) (scan-data T)) +(scm_environment_unobserve (groups scm C) (scan-data T)) +(scm_environments_prehistory (groups scm C) (scan-data T)) +(scm_eof_object_p (groups scm C) (scan-data T)) +(scm_eq_p (groups scm C) (scan-data T)) +(scm_equal_p (groups scm C) (scan-data T)) +(scm_eqv_p (groups scm C) (scan-data T)) +(scm_error (groups scm C) (scan-data T)) +(scm_error_environment_immutable_binding (groups scm C) (scan-data T)) +(scm_error_environment_immutable_location (groups scm C) (scan-data T)) +(scm_error_environment_unbound (groups scm C) (scan-data T)) +(scm_error_num_args_subr (groups scm C) (scan-data T)) +(scm_error_revive_threads (groups scm C) (scan-data T)) +(scm_error_scm (groups scm C) (scan-data T)) +(scm_eval (groups scm C) (scan-data T)) +(scm_eval_args (groups scm C) (scan-data T)) +(scm_eval_body (groups scm C) (scan-data T)) +(scm_eval_car (groups scm C) (scan-data T)) +(scm_eval_closure_lookup (groups scm C) (scan-data T)) +(scm_eval_environment_imported (groups scm C) (scan-data T)) +(scm_eval_environment_local (groups scm C) (scan-data T)) +(scm_eval_environment_p (groups scm C) (scan-data T)) +(scm_eval_environment_set_imported_x (groups scm C) (scan-data T)) +(scm_eval_environment_set_local_x (groups scm C) (scan-data T)) +(scm_eval_options_interface (groups scm C) (scan-data T)) +(scm_eval_opts (groups scm C) (scan-data D)) +(scm_eval_stack (groups scm C) (scan-data B)) +(scm_eval_string (groups scm C) (scan-data T)) +(scm_eval_x (groups scm C) (scan-data T)) +(scm_evaluator_trap_table (groups scm C) (scan-data D)) +(scm_evaluator_traps (groups scm C) (scan-data T)) +(scm_even_p (groups scm C) (scan-data T)) +(scm_evict_ports (groups scm C) (scan-data T)) +(scm_exact_p (groups scm C) (scan-data T)) +(scm_exact_to_inexact (groups scm C) (scan-data T)) +(scm_execl (groups scm C) (scan-data T)) +(scm_execle (groups scm C) (scan-data T)) +(scm_execlp (groups scm C) (scan-data T)) +(scm_exit_status (groups scm C) (scan-data T)) +(scm_expmem (groups scm C) (scan-data D)) +(scm_export_environment_p (groups scm C) (scan-data T)) +(scm_export_environment_private (groups scm C) (scan-data T)) +(scm_export_environment_set_private_x (groups scm C) (scan-data T)) +(scm_export_environment_set_signature_x (groups scm C) (scan-data T)) +(scm_export_environment_signature (groups scm C) (scan-data T)) +(scm_f_apply (groups scm C) (scan-data B)) +(scm_f_gsubr_apply (groups scm C) (scan-data B)) +(scm_fcntl (groups scm C) (scan-data T)) +(scm_fdes_to_port (groups scm C) (scan-data T)) +(scm_fdes_to_ports (groups scm C) (scan-data T)) +(scm_fdopen (groups scm C) (scan-data T)) +(scm_file_port_p (groups scm C) (scan-data T)) +(scm_fileno (groups scm C) (scan-data T)) +(scm_fill_input (groups scm C) (scan-data T)) +(scm_find_executable (groups scm C) (scan-data T)) +(scm_find_method (groups scm C) (scan-data T)) +(scm_finish_srcprop (groups scm C) (scan-data T)) +(scm_float2num (groups scm C) (scan-data T)) +(scm_flock (groups scm C) (scan-data T)) +(scm_fluid_p (groups scm C) (scan-data T)) +(scm_fluid_ref (groups scm C) (scan-data T)) +(scm_fluid_set_x (groups scm C) (scan-data T)) +(scm_flush (groups scm C) (scan-data T)) +(scm_flush_all_ports (groups scm C) (scan-data T)) +(scm_flush_ws (groups scm C) (scan-data T)) +(scm_for_each (groups scm C) (scan-data T)) +(scm_force (groups scm C) (scan-data T)) +(scm_force_output (groups scm C) (scan-data T)) +(scm_fork (groups scm C) (scan-data T)) +(scm_frame_arguments (groups scm C) (scan-data T)) +(scm_frame_evaluating_args_p (groups scm C) (scan-data T)) +(scm_frame_next (groups scm C) (scan-data T)) +(scm_frame_number (groups scm C) (scan-data T)) +(scm_frame_overflow_p (groups scm C) (scan-data T)) +(scm_frame_p (groups scm C) (scan-data T)) +(scm_frame_previous (groups scm C) (scan-data T)) +(scm_frame_procedure (groups scm C) (scan-data T)) +(scm_frame_procedure_p (groups scm C) (scan-data T)) +(scm_frame_real_p (groups scm C) (scan-data T)) +(scm_frame_source (groups scm C) (scan-data T)) +(scm_free0 (groups scm C) (scan-data T)) +(scm_free_print_state (groups scm C) (scan-data T)) +(scm_free_subr_entry (groups scm C) (scan-data T)) +(scm_freelist (groups scm C) (scan-data D)) +(scm_freelist2 (groups scm C) (scan-data D)) +(scm_fsync (groups scm C) (scan-data T)) +(scm_ftell (groups scm C) (scan-data T)) +(scm_gc (groups scm C) (scan-data T)) +(scm_gc_cells_collected (groups scm C) (scan-data B)) +(scm_gc_cells_marked_acc (groups scm C) (scan-data D)) +(scm_gc_cells_swept (groups scm C) (scan-data D)) +(scm_gc_cells_swept_acc (groups scm C) (scan-data D)) +(scm_gc_for_newcell (groups scm C) (scan-data T)) +(scm_gc_free (groups scm C) (scan-data T)) +(scm_gc_heap_lock (groups scm C) (scan-data D)) +(scm_gc_malloc (groups scm C) (scan-data T)) +(scm_gc_malloc_collected (groups scm C) (scan-data B)) +(scm_gc_mark (groups scm C) (scan-data T)) +(scm_gc_mark_dependencies (groups scm C) (scan-data T)) +(scm_gc_mark_time_taken (groups scm C) (scan-data D)) +(scm_gc_ports_collected (groups scm C) (scan-data B)) +(scm_gc_protect_object (groups scm C) (scan-data T)) +(scm_gc_realloc (groups scm C) (scan-data T)) +(scm_gc_register_collectable_memory (groups scm C) (scan-data T)) +(scm_gc_register_root (groups scm C) (scan-data T)) +(scm_gc_register_roots (groups scm C) (scan-data T)) +(scm_gc_running_p (groups scm C) (scan-data D)) +(scm_gc_stats (groups scm C) (scan-data T)) +(scm_gc_strdup (groups scm C) (scan-data T)) +(scm_gc_strndup (groups scm C) (scan-data T)) +(scm_gc_sweep (groups scm C) (scan-data T)) +(scm_gc_sweep_time_taken (groups scm C) (scan-data D)) +(scm_gc_time_taken (groups scm C) (scan-data D)) +(scm_gc_times (groups scm C) (scan-data D)) +(scm_gc_unprotect_object (groups scm C) (scan-data T)) +(scm_gc_unregister_collectable_memory (groups scm C) (scan-data T)) +(scm_gc_unregister_root (groups scm C) (scan-data T)) +(scm_gc_unregister_roots (groups scm C) (scan-data T)) +(scm_gc_yield (groups scm C) (scan-data B)) +(scm_gcd (groups scm C) (scan-data T)) +(scm_generic_capability_p (groups scm C) (scan-data T)) +(scm_generic_function_methods (groups scm C) (scan-data T)) +(scm_generic_function_name (groups scm C) (scan-data T)) +(scm_gensym (groups scm C) (scan-data T)) +(scm_geq_p (groups scm C) (scan-data T)) +(scm_get_internal_real_time (groups scm C) (scan-data T)) +(scm_get_internal_run_time (groups scm C) (scan-data T)) +(scm_get_keyword (groups scm C) (scan-data T)) +(scm_get_meta_args (groups scm C) (scan-data T)) +(scm_get_one_zombie (groups scm C) (scan-data T)) +(scm_get_output_string (groups scm C) (scan-data T)) +(scm_get_pre_modules_obarray (groups scm C) (scan-data T)) +(scm_get_print_state (groups scm C) (scan-data T)) +(scm_get_stack_base (groups scm C) (scan-data T)) +(scm_getc (groups scm C) (scan-data T)) +(scm_getcwd (groups scm C) (scan-data T)) +(scm_getegid (groups scm C) (scan-data T)) +(scm_getenv (groups scm C) (scan-data T)) +(scm_geteuid (groups scm C) (scan-data T)) +(scm_getgid (groups scm C) (scan-data T)) +(scm_getgrgid (groups scm C) (scan-data T)) +(scm_getgroups (groups scm C) (scan-data T)) +(scm_gethost (groups scm C) (scan-data T)) +(scm_gethostname (groups scm C) (scan-data T)) +(scm_getitimer (groups scm C) (scan-data T)) +(scm_getlogin (groups scm C) (scan-data T)) +(scm_getnet (groups scm C) (scan-data T)) +(scm_getpass (groups scm C) (scan-data T)) +(scm_getpeername (groups scm C) (scan-data T)) +(scm_getpgrp (groups scm C) (scan-data T)) +(scm_getpid (groups scm C) (scan-data T)) +(scm_getppid (groups scm C) (scan-data T)) +(scm_getpriority (groups scm C) (scan-data T)) +(scm_getproto (groups scm C) (scan-data T)) +(scm_getpwuid (groups scm C) (scan-data T)) +(scm_getserv (groups scm C) (scan-data T)) +(scm_getsockname (groups scm C) (scan-data T)) +(scm_getsockopt (groups scm C) (scan-data T)) +(scm_gettimeofday (groups scm C) (scan-data T)) +(scm_getuid (groups scm C) (scan-data T)) +(scm_gmtime (groups scm C) (scan-data T)) +(scm_gr_p (groups scm C) (scan-data T)) +(scm_grow_tok_buf (groups scm C) (scan-data T)) +(scm_gsubr_apply (groups scm C) (scan-data T)) +(scm_guard (groups scm C) (scan-data T)) +(scm_guardian_destroyed_p (groups scm C) (scan-data T)) +(scm_guardian_greedy_p (groups scm C) (scan-data T)) +(scm_handle_by_message (groups scm C) (scan-data T)) +(scm_handle_by_message_noexit (groups scm C) (scan-data T)) +(scm_handle_by_proc (groups scm C) (scan-data T)) +(scm_handle_by_proc_catching_all (groups scm C) (scan-data T)) +(scm_handle_by_throw (groups scm C) (scan-data T)) +(scm_hash (groups scm C) (scan-data T)) +(scm_hash_create_handle_x (groups scm C) (scan-data T)) +(scm_hash_fn_create_handle_x (groups scm C) (scan-data T)) +(scm_hash_fn_get_handle (groups scm C) (scan-data T)) +(scm_hash_fn_ref (groups scm C) (scan-data T)) +(scm_hash_fn_remove_x (groups scm C) (scan-data T)) +(scm_hash_fn_set_x (groups scm C) (scan-data T)) +(scm_hash_fold (groups scm C) (scan-data T)) +(scm_hash_get_handle (groups scm C) (scan-data T)) +(scm_hash_ref (groups scm C) (scan-data T)) +(scm_hash_remove_x (groups scm C) (scan-data T)) +(scm_hash_set_x (groups scm C) (scan-data T)) +(scm_hasher (groups scm C) (scan-data T)) +(scm_hashq (groups scm C) (scan-data T)) +(scm_hashq_create_handle_x (groups scm C) (scan-data T)) +(scm_hashq_get_handle (groups scm C) (scan-data T)) +(scm_hashq_ref (groups scm C) (scan-data T)) +(scm_hashq_remove_x (groups scm C) (scan-data T)) +(scm_hashq_set_x (groups scm C) (scan-data T)) +(scm_hashv (groups scm C) (scan-data T)) +(scm_hashv_create_handle_x (groups scm C) (scan-data T)) +(scm_hashv_get_handle (groups scm C) (scan-data T)) +(scm_hashv_ref (groups scm C) (scan-data T)) +(scm_hashv_remove_x (groups scm C) (scan-data T)) +(scm_hashv_set_x (groups scm C) (scan-data T)) +(scm_hashx_create_handle_x (groups scm C) (scan-data T)) +(scm_hashx_get_handle (groups scm C) (scan-data T)) +(scm_hashx_ref (groups scm C) (scan-data T)) +(scm_hashx_remove_x (groups scm C) (scan-data T)) +(scm_hashx_set_x (groups scm C) (scan-data T)) +(scm_heap_org (groups scm C) (scan-data B)) +(scm_heap_table (groups scm C) (scan-data D)) +(scm_hook_empty_p (groups scm C) (scan-data T)) +(scm_hook_p (groups scm C) (scan-data T)) +(scm_hook_to_list (groups scm C) (scan-data T)) +(scm_htonl (groups scm C) (scan-data T)) +(scm_htons (groups scm C) (scan-data T)) +(scm_i_adjbig (groups scm libguile-internal C) (scan-data T)) +(scm_i_big2dbl (groups scm libguile-internal C) (scan-data T)) +(scm_i_big2inum (groups scm libguile-internal C) (scan-data T)) +(scm_i_copy_rstate (groups scm libguile-internal C) (scan-data T)) +(scm_i_copybig (groups scm libguile-internal C) (scan-data T)) +(scm_i_dbl2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_display_error (groups scm libguile-internal C) (scan-data T)) +(scm_i_dummy (groups scm libguile-internal C) (scan-data B)) +(scm_i_eval (groups scm libguile-internal C) (scan-data T)) +(scm_i_eval_x (groups scm libguile-internal C) (scan-data T)) +(scm_i_get_keyword (groups scm libguile-internal C) (scan-data T)) +(scm_i_init_rstate (groups scm libguile-internal C) (scan-data T)) +(scm_i_int2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_long2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_long_long2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_make_class_object (groups scm libguile-internal C) (scan-data T)) +(scm_i_mem2number (groups scm libguile-internal C) (scan-data T)) +(scm_i_mkbig (groups scm libguile-internal C) (scan-data T)) +(scm_i_normbig (groups scm libguile-internal C) (scan-data T)) +(scm_i_procedure_arity (groups scm libguile-internal C) (scan-data T)) +(scm_i_ptrdiff2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_short2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_size2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_terminating (groups scm libguile-internal C) (scan-data B)) +(scm_i_uint2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_ulong2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_ulong_long2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_uniform32 (groups scm libguile-internal C) (scan-data T)) +(scm_i_ushort2big (groups scm libguile-internal C) (scan-data T)) +(scm_i_variable_print (groups scm libguile-internal C) (scan-data T)) +(scm_ice_9_already_loaded (groups scm C) (scan-data D)) +(scm_igc (groups scm C) (scan-data T)) +(scm_ihash (groups scm C) (scan-data T)) +(scm_ihashq (groups scm C) (scan-data T)) +(scm_ihashv (groups scm C) (scan-data T)) +(scm_iint2str (groups scm C) (scan-data T)) +(scm_ilength (groups scm C) (scan-data T)) +(scm_ilookup (groups scm C) (scan-data T)) +(scm_imag_part (groups scm C) (scan-data T)) +(scm_import_environment_imports (groups scm C) (scan-data T)) +(scm_import_environment_p (groups scm C) (scan-data T)) +(scm_import_environment_set_imports_x (groups scm C) (scan-data T)) +(scm_include_deprecated_features (groups scm C) (scan-data T)) +(scm_inet_aton (groups scm C) (scan-data T)) +(scm_inet_makeaddr (groups scm C) (scan-data T)) +(scm_inet_netof (groups scm C) (scan-data T)) +(scm_inet_ntoa (groups scm C) (scan-data T)) +(scm_inet_ntop (groups scm C) (scan-data T)) +(scm_inet_pton (groups scm C) (scan-data T)) +(scm_inexact_p (groups scm C) (scan-data T)) +(scm_inexact_to_exact (groups scm C) (scan-data T)) +(scm_inf (groups scm C) (scan-data T)) +(scm_inf_p (groups scm C) (scan-data T)) +(scm_init_alist (groups scm C) (scan-data T)) +(scm_init_arbiters (groups scm C) (scan-data T)) +(scm_init_async (groups scm C) (scan-data T)) +(scm_init_backtrace (groups scm C) (scan-data T)) +(scm_init_boolean (groups scm C) (scan-data T)) +(scm_init_chars (groups scm C) (scan-data T)) +(scm_init_continuations (groups scm C) (scan-data T)) +(scm_init_debug (groups scm C) (scan-data T)) +(scm_init_deprecation (groups scm C) (scan-data T)) +(scm_init_dynamic_linking (groups scm C) (scan-data T)) +(scm_init_dynwind (groups scm C) (scan-data T)) +(scm_init_environments (groups scm C) (scan-data T)) +(scm_init_eq (groups scm C) (scan-data T)) +(scm_init_error (groups scm C) (scan-data T)) +(scm_init_eval (groups scm C) (scan-data T)) +(scm_init_evalext (groups scm C) (scan-data T)) +(scm_init_extensions (groups scm C) (scan-data T)) +(scm_init_feature (groups scm C) (scan-data T)) +(scm_init_filesys (groups scm C) (scan-data T)) +(scm_init_fluids (groups scm C) (scan-data T)) +(scm_init_fports (groups scm C) (scan-data T)) +(scm_init_gc (groups scm C) (scan-data T)) +(scm_init_gdbint (groups scm C) (scan-data T)) +(scm_init_goops (groups scm C) (scan-data T)) +(scm_init_goops_builtins (groups scm C) (scan-data T)) +(scm_init_gsubr (groups scm C) (scan-data T)) +(scm_init_guardians (groups scm C) (scan-data T)) +(scm_init_guile (groups scm C) (scan-data T)) +(scm_init_hash (groups scm C) (scan-data T)) +(scm_init_hashtab (groups scm C) (scan-data T)) +(scm_init_hooks (groups scm C) (scan-data T)) +(scm_init_ioext (groups scm C) (scan-data T)) +(scm_init_iselect (groups scm C) (scan-data T)) +(scm_init_keywords (groups scm C) (scan-data T)) +(scm_init_lang (groups scm C) (scan-data T)) +(scm_init_list (groups scm C) (scan-data T)) +(scm_init_load (groups scm C) (scan-data T)) +(scm_init_load_path (groups scm C) (scan-data T)) +(scm_init_macros (groups scm C) (scan-data T)) +(scm_init_mallocs (groups scm C) (scan-data T)) +(scm_init_modules (groups scm C) (scan-data T)) +(scm_init_net_db (groups scm C) (scan-data T)) +(scm_init_numbers (groups scm C) (scan-data T)) +(scm_init_objects (groups scm C) (scan-data T)) +(scm_init_objprop (groups scm C) (scan-data T)) +(scm_init_options (groups scm C) (scan-data T)) +(scm_init_opts (groups scm C) (scan-data T)) +(scm_init_pairs (groups scm C) (scan-data T)) +(scm_init_ports (groups scm C) (scan-data T)) +(scm_init_posix (groups scm C) (scan-data T)) +(scm_init_print (groups scm C) (scan-data T)) +(scm_init_procprop (groups scm C) (scan-data T)) +(scm_init_procs (groups scm C) (scan-data T)) +(scm_init_properties (groups scm C) (scan-data T)) +(scm_init_ramap (groups scm C) (scan-data T)) +(scm_init_random (groups scm C) (scan-data T)) +(scm_init_rdelim (groups scm C) (scan-data T)) +(scm_init_rdelim_builtins (groups scm C) (scan-data T)) +(scm_init_read (groups scm C) (scan-data T)) +(scm_init_regex_posix (groups scm C) (scan-data T)) +(scm_init_root (groups scm C) (scan-data T)) +(scm_init_rw (groups scm C) (scan-data T)) +(scm_init_rw_builtins (groups scm C) (scan-data T)) +(scm_init_scmsigs (groups scm C) (scan-data T)) +(scm_init_script (groups scm C) (scan-data T)) +(scm_init_simpos (groups scm C) (scan-data T)) +(scm_init_socket (groups scm C) (scan-data T)) +(scm_init_sort (groups scm C) (scan-data T)) +(scm_init_srcprop (groups scm C) (scan-data T)) +(scm_init_stackchk (groups scm C) (scan-data T)) +(scm_init_stacks (groups scm C) (scan-data T)) +(scm_init_stime (groups scm C) (scan-data T)) +(scm_init_storage (groups scm C) (scan-data T)) +(scm_init_strings (groups scm C) (scan-data T)) +(scm_init_strop (groups scm C) (scan-data T)) +(scm_init_strorder (groups scm C) (scan-data T)) +(scm_init_strports (groups scm C) (scan-data T)) +(scm_init_struct (groups scm C) (scan-data T)) +(scm_init_subr_table (groups scm C) (scan-data T)) +(scm_init_symbols (groups scm C) (scan-data T)) +(scm_init_threads (groups scm C) (scan-data T)) +(scm_init_throw (groups scm C) (scan-data T)) +(scm_init_unif (groups scm C) (scan-data T)) +(scm_init_values (groups scm C) (scan-data T)) +(scm_init_variable (groups scm C) (scan-data T)) +(scm_init_vectors (groups scm C) (scan-data T)) +(scm_init_version (groups scm C) (scan-data T)) +(scm_init_vports (groups scm C) (scan-data T)) +(scm_init_weaks (groups scm C) (scan-data T)) +(scm_initialized_p (groups scm C) (scan-data D)) +(scm_input_port_p (groups scm C) (scan-data T)) +(scm_instance_p (groups scm C) (scan-data T)) +(scm_int2num (groups scm C) (scan-data T)) +(scm_integer_expt (groups scm C) (scan-data T)) +(scm_integer_length (groups scm C) (scan-data T)) +(scm_integer_p (groups scm C) (scan-data T)) +(scm_integer_to_char (groups scm C) (scan-data T)) +(scm_interaction_environment (groups scm C) (scan-data T)) +(scm_internal_catch (groups scm C) (scan-data T)) +(scm_internal_cwdr (groups scm C) (scan-data T)) +(scm_internal_dynamic_wind (groups scm C) (scan-data T)) +(scm_internal_hash_fold (groups scm C) (scan-data T)) +(scm_internal_lazy_catch (groups scm C) (scan-data T)) +(scm_internal_parse_path (groups scm C) (scan-data T)) +(scm_internal_select (groups scm C) (scan-data T)) +(scm_internal_stack_catch (groups scm C) (scan-data T)) +(scm_intprint (groups scm C) (scan-data T)) +(scm_ints_disabled (groups scm C) (scan-data D)) +(scm_iprin1 (groups scm C) (scan-data T)) +(scm_iprlist (groups scm C) (scan-data T)) +(scm_ipruk (groups scm C) (scan-data T)) +(scm_isatty_p (groups scm C) (scan-data T)) +(scm_issue_deprecation_warning (groups scm C) (scan-data T)) +(scm_istr2bve (groups scm C) (scan-data T)) +(scm_isymnames (groups scm C) (scan-data D)) +(scm_ithrow (groups scm C) (scan-data T)) +(scm_join_thread (groups scm C) (scan-data T)) +(scm_keyword_dash_symbol (groups scm C) (scan-data T)) +(scm_keyword_p (groups scm C) (scan-data T)) +(scm_kill (groups scm C) (scan-data T)) +(scm_last_pair (groups scm C) (scan-data T)) +(scm_last_stack_frame (groups scm C) (scan-data T)) +(scm_lazy_catch (groups scm C) (scan-data T)) +(scm_lcm (groups scm C) (scan-data T)) +(scm_leaf_environment_p (groups scm C) (scan-data T)) +(scm_length (groups scm C) (scan-data T)) +(scm_leq_p (groups scm C) (scan-data T)) +(scm_less_p (groups scm C) (scan-data T)) +(scm_lfwrite (groups scm C) (scan-data T)) +(scm_link (groups scm C) (scan-data T)) +(scm_list (groups scm C) (scan-data T)) +(scm_list_1 (groups scm C) (scan-data T)) +(scm_list_2 (groups scm C) (scan-data T)) +(scm_list_3 (groups scm C) (scan-data T)) +(scm_list_4 (groups scm C) (scan-data T)) +(scm_list_5 (groups scm C) (scan-data T)) +(scm_list_cdr_set_x (groups scm C) (scan-data T)) +(scm_list_copy (groups scm C) (scan-data T)) +(scm_list_head (groups scm C) (scan-data T)) +(scm_list_n (groups scm C) (scan-data T)) +(scm_list_p (groups scm C) (scan-data T)) +(scm_list_ref (groups scm C) (scan-data T)) +(scm_list_set_x (groups scm C) (scan-data T)) +(scm_list_tail (groups scm C) (scan-data T)) +(scm_list_to_uniform_array (groups scm C) (scan-data T)) +(scm_listen (groups scm C) (scan-data T)) +(scm_listofnullstr (groups scm C) (scan-data B)) +(scm_lnaof (groups scm C) (scan-data T)) +(scm_load_extension (groups scm C) (scan-data T)) +(scm_load_goops (groups scm C) (scan-data T)) +(scm_load_startup_files (groups scm C) (scan-data T)) +(scm_local_eval (groups scm C) (scan-data T)) +(scm_localtime (groups scm C) (scan-data T)) +(scm_lock_mutex (groups scm C) (scan-data T)) +(scm_logand (groups scm C) (scan-data T)) +(scm_logbit_p (groups scm C) (scan-data T)) +(scm_logcount (groups scm C) (scan-data T)) +(scm_logior (groups scm C) (scan-data T)) +(scm_lognot (groups scm C) (scan-data T)) +(scm_logtest (groups scm C) (scan-data T)) +(scm_logxor (groups scm C) (scan-data T)) +(scm_long2num (groups scm C) (scan-data T)) +(scm_long_long2num (groups scm C) (scan-data T)) +(scm_lookup (groups scm C) (scan-data T)) +(scm_lookup_closure_module (groups scm C) (scan-data T)) +(scm_lookupcar (groups scm C) (scan-data T)) +(scm_lreadparen (groups scm C) (scan-data T)) +(scm_lreadr (groups scm C) (scan-data T)) +(scm_lreadrecparen (groups scm C) (scan-data T)) +(scm_lstat (groups scm C) (scan-data T)) +(scm_m_and (groups scm C) (scan-data T)) +(scm_m_apply (groups scm C) (scan-data T)) +(scm_m_at_call_with_values (groups scm C) (scan-data T)) +(scm_m_atbind (groups scm C) (scan-data T)) +(scm_m_atdispatch (groups scm C) (scan-data T)) +(scm_m_atfop (groups scm C) (scan-data T)) +(scm_m_atslot_ref (groups scm C) (scan-data T)) +(scm_m_atslot_set_x (groups scm C) (scan-data T)) +(scm_m_begin (groups scm C) (scan-data T)) +(scm_m_case (groups scm C) (scan-data T)) +(scm_m_cond (groups scm C) (scan-data T)) +(scm_m_cont (groups scm C) (scan-data T)) +(scm_m_define (groups scm C) (scan-data T)) +(scm_m_delay (groups scm C) (scan-data T)) +(scm_m_do (groups scm C) (scan-data T)) +(scm_m_expand_body (groups scm C) (scan-data T)) +(scm_m_generalized_set_x (groups scm C) (scan-data T)) +(scm_m_if (groups scm C) (scan-data T)) +(scm_m_lambda (groups scm C) (scan-data T)) +(scm_m_let (groups scm C) (scan-data T)) +(scm_m_letrec (groups scm C) (scan-data T)) +(scm_m_letstar (groups scm C) (scan-data T)) +(scm_m_nil_cond (groups scm C) (scan-data T)) +(scm_m_or (groups scm C) (scan-data T)) +(scm_m_quasiquote (groups scm C) (scan-data T)) +(scm_m_quote (groups scm C) (scan-data T)) +(scm_m_set_x (groups scm C) (scan-data T)) +(scm_m_undefine (groups scm C) (scan-data T)) +(scm_macro_name (groups scm C) (scan-data T)) +(scm_macro_p (groups scm C) (scan-data T)) +(scm_macro_transformer (groups scm C) (scan-data T)) +(scm_macro_type (groups scm C) (scan-data T)) +(scm_macroexp (groups scm C) (scan-data T)) +(scm_magnitude (groups scm C) (scan-data T)) +(scm_major_version (groups scm C) (scan-data T)) +(scm_makacro (groups scm C) (scan-data T)) +(scm_makcclo (groups scm C) (scan-data T)) +(scm_make (groups scm C) (scan-data T)) +(scm_make_arbiter (groups scm C) (scan-data T)) +(scm_make_class (groups scm C) (scan-data T)) +(scm_make_class_object (groups scm C) (scan-data T)) +(scm_make_complex (groups scm C) (scan-data T)) +(scm_make_condition_variable (groups scm C) (scan-data T)) +(scm_make_continuation (groups scm C) (scan-data T)) +(scm_make_debugobj (groups scm C) (scan-data T)) +(scm_make_doubly_weak_hash_table (groups scm C) (scan-data T)) +(scm_make_environment (groups scm C) (scan-data T)) +(scm_make_eval_environment (groups scm C) (scan-data T)) +(scm_make_export_environment (groups scm C) (scan-data T)) +(scm_make_extended_class (groups scm C) (scan-data T)) +(scm_make_fluid (groups scm C) (scan-data T)) +(scm_make_foreign_object (groups scm C) (scan-data T)) +(scm_make_guardian (groups scm C) (scan-data T)) +(scm_make_hook (groups scm C) (scan-data T)) +(scm_make_import_environment (groups scm C) (scan-data T)) +(scm_make_initial_fluids (groups scm C) (scan-data T)) +(scm_make_keyword_from_dash_symbol (groups scm C) (scan-data T)) +(scm_make_leaf_environment (groups scm C) (scan-data T)) +(scm_make_memoized (groups scm C) (scan-data T)) +(scm_make_method_cache (groups scm C) (scan-data T)) +(scm_make_mutex (groups scm C) (scan-data T)) +(scm_make_polar (groups scm C) (scan-data T)) +(scm_make_port_classes (groups scm C) (scan-data T)) +(scm_make_port_type (groups scm C) (scan-data T)) +(scm_make_print_state (groups scm C) (scan-data T)) +(scm_make_procedure_with_setter (groups scm C) (scan-data T)) +(scm_make_ra (groups scm C) (scan-data T)) +(scm_make_real (groups scm C) (scan-data T)) +(scm_make_rectangular (groups scm C) (scan-data T)) +(scm_make_regexp (groups scm C) (scan-data T)) +(scm_make_root (groups scm C) (scan-data T)) +(scm_make_shared_array (groups scm C) (scan-data T)) +(scm_make_smob (groups scm C) (scan-data T)) +(scm_make_smob_type (groups scm C) (scan-data T)) +(scm_make_soft_port (groups scm C) (scan-data T)) +(scm_make_srcprops (groups scm C) (scan-data T)) +(scm_make_stack (groups scm C) (scan-data T)) +(scm_make_string (groups scm C) (scan-data T)) +(scm_make_struct (groups scm C) (scan-data T)) +(scm_make_struct_layout (groups scm C) (scan-data T)) +(scm_make_subclass_object (groups scm C) (scan-data T)) +(scm_make_symbol (groups scm C) (scan-data T)) +(scm_make_synt (groups scm C) (scan-data T)) +(scm_make_undefined_variable (groups scm C) (scan-data T)) +(scm_make_uve (groups scm C) (scan-data T)) +(scm_make_variable (groups scm C) (scan-data T)) +(scm_make_vector (groups scm C) (scan-data T)) +(scm_make_vtable_vtable (groups scm C) (scan-data T)) +(scm_make_weak_key_hash_table (groups scm C) (scan-data T)) +(scm_make_weak_value_hash_table (groups scm C) (scan-data T)) +(scm_make_weak_vector (groups scm C) (scan-data T)) +(scm_makfrom0str (groups scm C) (scan-data T)) +(scm_makfrom0str_opt (groups scm C) (scan-data T)) +(scm_makfromstrs (groups scm C) (scan-data T)) +(scm_makmacro (groups scm C) (scan-data T)) +(scm_makmmacro (groups scm C) (scan-data T)) +(scm_makprom (groups scm C) (scan-data T)) +(scm_malloc (groups scm C) (scan-data T)) +(scm_malloc_obj (groups scm C) (scan-data T)) +(scm_mallocated (groups scm C) (scan-data D)) +(scm_map (groups scm C) (scan-data T)) +(scm_mark0 (groups scm C) (scan-data T)) +(scm_mark_locations (groups scm C) (scan-data T)) +(scm_mark_subr_table (groups scm C) (scan-data T)) +(scm_markcdr (groups scm C) (scan-data T)) +(scm_markstream (groups scm C) (scan-data T)) +(scm_mask_ints (groups scm C) (scan-data D)) +(scm_mask_signals (groups scm C) (scan-data T)) +(scm_masktab (groups scm C) (scan-data B)) +(scm_master_freelist (groups scm C) (scan-data D)) +(scm_master_freelist2 (groups scm C) (scan-data D)) +(scm_max (groups scm C) (scan-data T)) +(scm_max_segment_size (groups scm C) (scan-data B)) +(scm_mcache_compute_cmethod (groups scm C) (scan-data T)) +(scm_mcache_lookup_cmethod (groups scm C) (scan-data T)) +(scm_mem2string (groups scm C) (scan-data T)) +(scm_mem2symbol (groups scm C) (scan-data T)) +(scm_mem2uninterned_symbol (groups scm C) (scan-data T)) +(scm_member (groups scm C) (scan-data T)) +(scm_memoize_method (groups scm C) (scan-data T)) +(scm_memoized_environment (groups scm C) (scan-data T)) +(scm_memoized_p (groups scm C) (scan-data T)) +(scm_memory_alloc_key (groups scm C) (scan-data B)) +(scm_memory_error (groups scm C) (scan-data T)) +(scm_memq (groups scm C) (scan-data T)) +(scm_memv (groups scm C) (scan-data T)) +(scm_merge (groups scm C) (scan-data T)) +(scm_merge_x (groups scm C) (scan-data T)) +(scm_metaclass_operator (groups scm C) (scan-data B)) +(scm_metaclass_standard (groups scm C) (scan-data B)) +(scm_method_generic_function (groups scm C) (scan-data T)) +(scm_method_procedure (groups scm C) (scan-data T)) +(scm_method_specializers (groups scm C) (scan-data T)) +(scm_micro_version (groups scm C) (scan-data T)) +(scm_min (groups scm C) (scan-data T)) +(scm_minor_version (groups scm C) (scan-data T)) +(scm_misc_error (groups scm C) (scan-data T)) +(scm_misc_error_key (groups scm C) (scan-data B)) +(scm_mkdir (groups scm C) (scan-data T)) +(scm_mknod (groups scm C) (scan-data T)) +(scm_mkstemp (groups scm C) (scan-data T)) +(scm_mkstrport (groups scm C) (scan-data T)) +(scm_mktime (groups scm C) (scan-data T)) +(scm_mode_bits (groups scm C) (scan-data T)) +(scm_module_define (groups scm C) (scan-data T)) +(scm_module_goops (groups scm C) (scan-data B)) +(scm_module_lookup (groups scm C) (scan-data T)) +(scm_module_lookup_closure (groups scm C) (scan-data T)) +(scm_module_reverse_lookup (groups scm C) (scan-data T)) +(scm_module_system_booted_p (groups scm C) (scan-data D)) +(scm_module_tag (groups scm C) (scan-data B)) +(scm_module_transformer (groups scm C) (scan-data T)) +(scm_modules_prehistory (groups scm C) (scan-data T)) +(scm_modulo (groups scm C) (scan-data T)) +(scm_mtrigger (groups scm C) (scan-data B)) +(scm_mulbig (groups scm C) (scan-data T)) +(scm_must_free (groups scm C) (scan-data T)) +(scm_must_malloc (groups scm C) (scan-data T)) +(scm_must_realloc (groups scm C) (scan-data T)) +(scm_must_strdup (groups scm C) (scan-data T)) +(scm_must_strndup (groups scm C) (scan-data T)) +(scm_n_charnames (groups scm C) (scan-data D)) +(scm_n_heap_segs (groups scm C) (scan-data D)) +(scm_nan (groups scm C) (scan-data T)) +(scm_nan_p (groups scm C) (scan-data T)) +(scm_nconc2last (groups scm C) (scan-data T)) +(scm_negative_p (groups scm C) (scan-data T)) +(scm_newline (groups scm C) (scan-data T)) +(scm_nice (groups scm C) (scan-data T)) +(scm_no_applicable_method (groups scm C) (scan-data B)) +(scm_noop (groups scm C) (scan-data T)) +(scm_not (groups scm C) (scan-data T)) +(scm_ntohl (groups scm C) (scan-data T)) +(scm_ntohs (groups scm C) (scan-data T)) +(scm_null_p (groups scm C) (scan-data T)) +(scm_num2dbl (groups scm C) (scan-data T)) +(scm_num2double (groups scm C) (scan-data T)) +(scm_num2float (groups scm C) (scan-data T)) +(scm_num2int (groups scm C) (scan-data T)) +(scm_num2long (groups scm C) (scan-data T)) +(scm_num2long_long (groups scm C) (scan-data T)) +(scm_num2ptrdiff (groups scm C) (scan-data T)) +(scm_num2short (groups scm C) (scan-data T)) +(scm_num2size (groups scm C) (scan-data T)) +(scm_num2uint (groups scm C) (scan-data T)) +(scm_num2ulong (groups scm C) (scan-data T)) +(scm_num2ulong_long (groups scm C) (scan-data T)) +(scm_num2ushort (groups scm C) (scan-data T)) +(scm_num_eq_p (groups scm C) (scan-data T)) +(scm_num_overflow (groups scm C) (scan-data T)) +(scm_num_overflow_key (groups scm C) (scan-data B)) +(scm_number_p (groups scm C) (scan-data T)) +(scm_number_to_string (groups scm C) (scan-data T)) +(scm_numptob (groups scm C) (scan-data B)) +(scm_numsmob (groups scm C) (scan-data B)) +(scm_object_address (groups scm C) (scan-data T)) +(scm_object_properties (groups scm C) (scan-data T)) +(scm_object_property (groups scm C) (scan-data T)) +(scm_object_to_string (groups scm C) (scan-data T)) +(scm_odd_p (groups scm C) (scan-data T)) +(scm_open (groups scm C) (scan-data T)) +(scm_open_fdes (groups scm C) (scan-data T)) +(scm_open_file (groups scm C) (scan-data T)) +(scm_open_input_string (groups scm C) (scan-data T)) +(scm_open_output_string (groups scm C) (scan-data T)) +(scm_opendir (groups scm C) (scan-data T)) +(scm_operator_p (groups scm C) (scan-data T)) +(scm_options (groups scm C) (scan-data T)) +(scm_out_of_range (groups scm C) (scan-data T)) +(scm_out_of_range_key (groups scm C) (scan-data B)) +(scm_out_of_range_pos (groups scm C) (scan-data T)) +(scm_output_port_p (groups scm C) (scan-data T)) +(scm_pair_p (groups scm C) (scan-data T)) +(scm_parse_path (groups scm C) (scan-data T)) +(scm_pause (groups scm C) (scan-data T)) +(scm_peek_char (groups scm C) (scan-data T)) +(scm_permanent_object (groups scm C) (scan-data T)) +(scm_pipe (groups scm C) (scan-data T)) +(scm_port_class (groups scm C) (scan-data D)) +(scm_port_closed_p (groups scm C) (scan-data T)) +(scm_port_column (groups scm C) (scan-data T)) +(scm_port_filename (groups scm C) (scan-data T)) +(scm_port_for_each (groups scm C) (scan-data T)) +(scm_port_line (groups scm C) (scan-data T)) +(scm_port_mode (groups scm C) (scan-data T)) +(scm_port_non_buffer (groups scm C) (scan-data T)) +(scm_port_p (groups scm C) (scan-data T)) +(scm_port_print (groups scm C) (scan-data T)) +(scm_port_revealed (groups scm C) (scan-data T)) +(scm_port_table (groups scm C) (scan-data B)) +(scm_port_table_room (groups scm C) (scan-data D)) +(scm_port_table_size (groups scm C) (scan-data D)) +(scm_port_with_print_state (groups scm C) (scan-data T)) +(scm_ports_prehistory (groups scm C) (scan-data T)) +(scm_positive_p (groups scm C) (scan-data T)) +(scm_pre_modules_obarray (groups scm C) (scan-data B)) +(scm_primitive_eval (groups scm C) (scan-data T)) +(scm_primitive_eval_x (groups scm C) (scan-data T)) +(scm_primitive_exit (groups scm C) (scan-data T)) +(scm_primitive_generic_generic (groups scm C) (scan-data T)) +(scm_primitive_load (groups scm C) (scan-data T)) +(scm_primitive_load_path (groups scm C) (scan-data T)) +(scm_primitive_make_property (groups scm C) (scan-data T)) +(scm_primitive_move_to_fdes (groups scm C) (scan-data T)) +(scm_primitive_property_del_x (groups scm C) (scan-data T)) +(scm_primitive_property_ref (groups scm C) (scan-data T)) +(scm_primitive_property_set_x (groups scm C) (scan-data T)) +(scm_prin1 (groups scm C) (scan-data T)) +(scm_print_carefully_p (groups scm C) (scan-data B)) +(scm_print_complex (groups scm C) (scan-data T)) +(scm_print_options (groups scm C) (scan-data T)) +(scm_print_opts (groups scm C) (scan-data D)) +(scm_print_port_mode (groups scm C) (scan-data T)) +(scm_print_real (groups scm C) (scan-data T)) +(scm_print_state_vtable (groups scm C) (scan-data D)) +(scm_print_struct (groups scm C) (scan-data T)) +(scm_print_symbol_name (groups scm C) (scan-data T)) +(scm_printer_apply (groups scm C) (scan-data T)) +(scm_procedure (groups scm C) (scan-data T)) +(scm_procedure_documentation (groups scm C) (scan-data T)) +(scm_procedure_environment (groups scm C) (scan-data T)) +(scm_procedure_name (groups scm C) (scan-data T)) +(scm_procedure_p (groups scm C) (scan-data T)) +(scm_procedure_properties (groups scm C) (scan-data T)) +(scm_procedure_property (groups scm C) (scan-data T)) +(scm_procedure_source (groups scm C) (scan-data T)) +(scm_procedure_with_setter_p (groups scm C) (scan-data T)) +(scm_product (groups scm C) (scan-data T)) +(scm_program_arguments (groups scm C) (scan-data T)) +(scm_promise_p (groups scm C) (scan-data T)) +(scm_pseudolong (groups scm C) (scan-data T)) +(scm_ptobs (groups scm C) (scan-data B)) +(scm_ptrdiff2num (groups scm C) (scan-data T)) +(scm_putc (groups scm C) (scan-data T)) +(scm_putenv (groups scm C) (scan-data T)) +(scm_puts (groups scm C) (scan-data T)) +(scm_quotient (groups scm C) (scan-data T)) +(scm_ra2contig (groups scm C) (scan-data T)) +(scm_ra_difference (groups scm C) (scan-data T)) +(scm_ra_divide (groups scm C) (scan-data T)) +(scm_ra_eqp (groups scm C) (scan-data T)) +(scm_ra_greqp (groups scm C) (scan-data T)) +(scm_ra_grp (groups scm C) (scan-data T)) +(scm_ra_leqp (groups scm C) (scan-data T)) +(scm_ra_lessp (groups scm C) (scan-data T)) +(scm_ra_matchp (groups scm C) (scan-data T)) +(scm_ra_product (groups scm C) (scan-data T)) +(scm_ra_set_contp (groups scm C) (scan-data T)) +(scm_ra_sum (groups scm C) (scan-data T)) +(scm_raequal (groups scm C) (scan-data T)) +(scm_raise (groups scm C) (scan-data T)) +(scm_ramapc (groups scm C) (scan-data T)) +(scm_random (groups scm C) (scan-data T)) +(scm_random_exp (groups scm C) (scan-data T)) +(scm_random_hollow_sphere_x (groups scm C) (scan-data T)) +(scm_random_normal (groups scm C) (scan-data T)) +(scm_random_normal_vector_x (groups scm C) (scan-data T)) +(scm_random_solid_sphere_x (groups scm C) (scan-data T)) +(scm_random_uniform (groups scm C) (scan-data T)) +(scm_raprin1 (groups scm C) (scan-data T)) +(scm_read (groups scm C) (scan-data T)) +(scm_read_char (groups scm C) (scan-data T)) +(scm_read_delimited_x (groups scm C) (scan-data T)) +(scm_read_hash_extend (groups scm C) (scan-data T)) +(scm_read_line (groups scm C) (scan-data T)) +(scm_read_options (groups scm C) (scan-data T)) +(scm_read_opts (groups scm C) (scan-data D)) +(scm_read_string_x_partial (groups scm C) (scan-data T)) +(scm_read_token (groups scm C) (scan-data T)) +(scm_readdir (groups scm C) (scan-data T)) +(scm_readlink (groups scm C) (scan-data T)) +(scm_real_equalp (groups scm C) (scan-data T)) +(scm_real_p (groups scm C) (scan-data T)) +(scm_real_part (groups scm C) (scan-data T)) +(scm_realloc (groups scm C) (scan-data T)) +(scm_recv (groups scm C) (scan-data T)) +(scm_recvfrom (groups scm C) (scan-data T)) +(scm_redirect_port (groups scm C) (scan-data T)) +(scm_regexp_exec (groups scm C) (scan-data T)) +(scm_regexp_p (groups scm C) (scan-data T)) +(scm_release_arbiter (groups scm C) (scan-data T)) +(scm_remainder (groups scm C) (scan-data T)) +(scm_remember_upto_here (groups scm C) (scan-data T)) +(scm_remember_upto_here_1 (groups scm C) (scan-data T)) +(scm_remember_upto_here_2 (groups scm C) (scan-data T)) +(scm_remove_from_port_table (groups scm C) (scan-data T)) +(scm_remove_hook_x (groups scm C) (scan-data T)) +(scm_rename (groups scm C) (scan-data T)) +(scm_report_stack_overflow (groups scm C) (scan-data T)) +(scm_reset_hook_x (groups scm C) (scan-data T)) +(scm_resolve_module (groups scm C) (scan-data T)) +(scm_restore_signals (groups scm C) (scan-data T)) +(scm_restricted_vector_sort_x (groups scm C) (scan-data T)) +(scm_return_first (groups scm C) (scan-data T)) +(scm_return_first_int (groups scm C) (scan-data T)) +(scm_revealed_count (groups scm C) (scan-data T)) +(scm_reverse (groups scm C) (scan-data T)) +(scm_reverse_lookup (groups scm C) (scan-data T)) +(scm_reverse_x (groups scm C) (scan-data T)) +(scm_rewinddir (groups scm C) (scan-data T)) +(scm_rmdir (groups scm C) (scan-data T)) +(scm_round (groups scm C) (scan-data T)) +(scm_run_asyncs (groups scm C) (scan-data T)) +(scm_run_hook (groups scm C) (scan-data T)) +(scm_s_bindings (groups scm C) (scan-data R)) +(scm_s_body (groups scm C) (scan-data R)) +(scm_s_clauses (groups scm C) (scan-data R)) +(scm_s_duplicate_bindings (groups scm C) (scan-data R)) +(scm_s_duplicate_formals (groups scm C) (scan-data R)) +(scm_s_expression (groups scm C) (scan-data R)) +(scm_s_formals (groups scm C) (scan-data R)) +(scm_s_set_x (groups scm C) (scan-data R)) +(scm_s_slot_set_x (groups scm C) (scan-data D)) +(scm_s_test (groups scm C) (scan-data R)) +(scm_s_variable (groups scm C) (scan-data R)) +(scm_search_path (groups scm C) (scan-data T)) +(scm_seed_to_random_state (groups scm C) (scan-data T)) +(scm_seek (groups scm C) (scan-data T)) +(scm_select (groups scm C) (scan-data T)) +(scm_send (groups scm C) (scan-data T)) +(scm_sendto (groups scm C) (scan-data T)) +(scm_set_car_x (groups scm C) (scan-data T)) +(scm_set_cdr_x (groups scm C) (scan-data T)) +(scm_set_current_error_port (groups scm C) (scan-data T)) +(scm_set_current_input_port (groups scm C) (scan-data T)) +(scm_set_current_module (groups scm C) (scan-data T)) +(scm_set_current_output_port (groups scm C) (scan-data T)) +(scm_set_object_procedure_x (groups scm C) (scan-data T)) +(scm_set_object_properties_x (groups scm C) (scan-data T)) +(scm_set_object_property_x (groups scm C) (scan-data T)) +(scm_set_port_close (groups scm C) (scan-data T)) +(scm_set_port_column_x (groups scm C) (scan-data T)) +(scm_set_port_end_input (groups scm C) (scan-data T)) +(scm_set_port_equalp (groups scm C) (scan-data T)) +(scm_set_port_filename_x (groups scm C) (scan-data T)) +(scm_set_port_flush (groups scm C) (scan-data T)) +(scm_set_port_free (groups scm C) (scan-data T)) +(scm_set_port_input_waiting (groups scm C) (scan-data T)) +(scm_set_port_line_x (groups scm C) (scan-data T)) +(scm_set_port_mark (groups scm C) (scan-data T)) +(scm_set_port_print (groups scm C) (scan-data T)) +(scm_set_port_revealed_x (groups scm C) (scan-data T)) +(scm_set_port_seek (groups scm C) (scan-data T)) +(scm_set_port_truncate (groups scm C) (scan-data T)) +(scm_set_procedure_properties_x (groups scm C) (scan-data T)) +(scm_set_procedure_property_x (groups scm C) (scan-data T)) +(scm_set_program_arguments (groups scm C) (scan-data T)) +(scm_set_smob_apply (groups scm C) (scan-data T)) +(scm_set_smob_equalp (groups scm C) (scan-data T)) +(scm_set_smob_free (groups scm C) (scan-data T)) +(scm_set_smob_mark (groups scm C) (scan-data T)) +(scm_set_smob_print (groups scm C) (scan-data T)) +(scm_set_source_properties_x (groups scm C) (scan-data T)) +(scm_set_source_property_x (groups scm C) (scan-data T)) +(scm_set_struct_vtable_name_x (groups scm C) (scan-data T)) +(scm_setegid (groups scm C) (scan-data T)) +(scm_seteuid (groups scm C) (scan-data T)) +(scm_setgid (groups scm C) (scan-data T)) +(scm_setgrent (groups scm C) (scan-data T)) +(scm_sethost (groups scm C) (scan-data T)) +(scm_sethostname (groups scm C) (scan-data T)) +(scm_setitimer (groups scm C) (scan-data T)) +(scm_setlocale (groups scm C) (scan-data T)) +(scm_setnet (groups scm C) (scan-data T)) +(scm_setpgid (groups scm C) (scan-data T)) +(scm_setpriority (groups scm C) (scan-data T)) +(scm_setproto (groups scm C) (scan-data T)) +(scm_setpwent (groups scm C) (scan-data T)) +(scm_setserv (groups scm C) (scan-data T)) +(scm_setsid (groups scm C) (scan-data T)) +(scm_setsockopt (groups scm C) (scan-data T)) +(scm_setter (groups scm C) (scan-data T)) +(scm_setuid (groups scm C) (scan-data T)) +(scm_setvbuf (groups scm C) (scan-data T)) +(scm_shap2ra (groups scm C) (scan-data T)) +(scm_shared_array_increments (groups scm C) (scan-data T)) +(scm_shared_array_offset (groups scm C) (scan-data T)) +(scm_shared_array_root (groups scm C) (scan-data T)) +(scm_shell (groups scm C) (scan-data T)) +(scm_shell_usage (groups scm C) (scan-data T)) +(scm_short2num (groups scm C) (scan-data T)) +(scm_shutdown (groups scm C) (scan-data T)) +(scm_sigaction (groups scm C) (scan-data T)) +(scm_signal_condition_variable (groups scm C) (scan-data T)) +(scm_simple_format (groups scm C) (scan-data T)) +(scm_single_thread_p (groups scm C) (scan-data T)) +(scm_size2num (groups scm C) (scan-data T)) +(scm_sleep (groups scm C) (scan-data T)) +(scm_sloppy_assoc (groups scm C) (scan-data T)) +(scm_sloppy_assq (groups scm C) (scan-data T)) +(scm_sloppy_assv (groups scm C) (scan-data T)) +(scm_slot_bound_p (groups scm C) (scan-data T)) +(scm_slot_bound_using_class_p (groups scm C) (scan-data T)) +(scm_slot_exists_p (groups scm C) (scan-data T)) +(scm_slot_exists_using_class_p (groups scm C) (scan-data T)) +(scm_slot_ref (groups scm C) (scan-data T)) +(scm_slot_ref_using_class (groups scm C) (scan-data T)) +(scm_slot_set_using_class_x (groups scm C) (scan-data T)) +(scm_slot_set_x (groups scm C) (scan-data T)) +(scm_smob_class (groups scm C) (scan-data D)) +(scm_smob_free (groups scm C) (scan-data T)) +(scm_smob_prehistory (groups scm C) (scan-data T)) +(scm_smob_print (groups scm C) (scan-data T)) +(scm_smobs (groups scm C) (scan-data B)) +(scm_socket (groups scm C) (scan-data T)) +(scm_socketpair (groups scm C) (scan-data T)) +(scm_sort (groups scm C) (scan-data T)) +(scm_sort_list (groups scm C) (scan-data T)) +(scm_sort_list_x (groups scm C) (scan-data T)) +(scm_sort_x (groups scm C) (scan-data T)) +(scm_sorted_p (groups scm C) (scan-data T)) +(scm_source_properties (groups scm C) (scan-data T)) +(scm_source_property (groups scm C) (scan-data T)) +(scm_spawn_thread (groups scm C) (scan-data T)) +(scm_srcprops_to_plist (groups scm C) (scan-data T)) +(scm_stable_sort (groups scm C) (scan-data T)) +(scm_stable_sort_x (groups scm C) (scan-data T)) +(scm_stack_checking_enabled_p (groups scm C) (scan-data B)) +(scm_stack_id (groups scm C) (scan-data T)) +(scm_stack_length (groups scm C) (scan-data T)) +(scm_stack_p (groups scm C) (scan-data T)) +(scm_stack_ref (groups scm C) (scan-data T)) +(scm_stack_report (groups scm C) (scan-data T)) +(scm_stack_size (groups scm C) (scan-data T)) +(scm_stack_type (groups scm C) (scan-data B)) +(scm_standard_eval_closure (groups scm C) (scan-data T)) +(scm_standard_interface_eval_closure (groups scm C) (scan-data T)) +(scm_start_stack (groups scm C) (scan-data T)) +(scm_stat (groups scm C) (scan-data T)) +(scm_status_exit_val (groups scm C) (scan-data T)) +(scm_status_stop_sig (groups scm C) (scan-data T)) +(scm_status_term_sig (groups scm C) (scan-data T)) +(scm_str2string (groups scm C) (scan-data T)) +(scm_str2symbol (groups scm C) (scan-data T)) +(scm_strdup (groups scm C) (scan-data T)) +(scm_strerror (groups scm C) (scan-data T)) +(scm_strftime (groups scm C) (scan-data T)) +(scm_string (groups scm C) (scan-data T)) +(scm_string_append (groups scm C) (scan-data T)) +(scm_string_capitalize (groups scm C) (scan-data T)) +(scm_string_capitalize_x (groups scm C) (scan-data T)) +(scm_string_ci_equal_p (groups scm C) (scan-data T)) +(scm_string_ci_geq_p (groups scm C) (scan-data T)) +(scm_string_ci_gr_p (groups scm C) (scan-data T)) +(scm_string_ci_leq_p (groups scm C) (scan-data T)) +(scm_string_ci_less_p (groups scm C) (scan-data T)) +(scm_string_ci_to_symbol (groups scm C) (scan-data T)) +(scm_string_copy (groups scm C) (scan-data T)) +(scm_string_downcase (groups scm C) (scan-data T)) +(scm_string_downcase_x (groups scm C) (scan-data T)) +(scm_string_equal_p (groups scm C) (scan-data T)) +(scm_string_fill_x (groups scm C) (scan-data T)) +(scm_string_geq_p (groups scm C) (scan-data T)) +(scm_string_gr_p (groups scm C) (scan-data T)) +(scm_string_hash (groups scm C) (scan-data T)) +(scm_string_index (groups scm C) (scan-data T)) +(scm_string_length (groups scm C) (scan-data T)) +(scm_string_leq_p (groups scm C) (scan-data T)) +(scm_string_less_p (groups scm C) (scan-data T)) +(scm_string_null_p (groups scm C) (scan-data T)) +(scm_string_p (groups scm C) (scan-data T)) +(scm_string_ref (groups scm C) (scan-data T)) +(scm_string_rindex (groups scm C) (scan-data T)) +(scm_string_set_x (groups scm C) (scan-data T)) +(scm_string_split (groups scm C) (scan-data T)) +(scm_string_to_list (groups scm C) (scan-data T)) +(scm_string_to_number (groups scm C) (scan-data T)) +(scm_string_to_symbol (groups scm C) (scan-data T)) +(scm_string_upcase (groups scm C) (scan-data T)) +(scm_string_upcase_x (groups scm C) (scan-data T)) +(scm_strndup (groups scm C) (scan-data T)) +(scm_strport_to_string (groups scm C) (scan-data T)) +(scm_strptime (groups scm C) (scan-data T)) +(scm_struct_create_handle (groups scm C) (scan-data T)) +(scm_struct_free_0 (groups scm C) (scan-data T)) +(scm_struct_free_entity (groups scm C) (scan-data T)) +(scm_struct_free_light (groups scm C) (scan-data T)) +(scm_struct_free_standard (groups scm C) (scan-data T)) +(scm_struct_ihashq (groups scm C) (scan-data T)) +(scm_struct_p (groups scm C) (scan-data T)) +(scm_struct_prehistory (groups scm C) (scan-data T)) +(scm_struct_ref (groups scm C) (scan-data T)) +(scm_struct_set_x (groups scm C) (scan-data T)) +(scm_struct_table (groups scm C) (scan-data B)) +(scm_struct_vtable (groups scm C) (scan-data T)) +(scm_struct_vtable_name (groups scm C) (scan-data T)) +(scm_struct_vtable_p (groups scm C) (scan-data T)) +(scm_struct_vtable_tag (groups scm C) (scan-data T)) +(scm_structs_to_free (groups scm C) (scan-data B)) +(scm_subr_p (groups scm C) (scan-data T)) +(scm_subr_table (groups scm C) (scan-data B)) +(scm_subr_table_room (groups scm C) (scan-data D)) +(scm_subr_table_size (groups scm C) (scan-data D)) +(scm_substring (groups scm C) (scan-data T)) +(scm_substring_fill_x (groups scm C) (scan-data T)) +(scm_substring_move_x (groups scm C) (scan-data T)) +(scm_sum (groups scm C) (scan-data T)) +(scm_swap_bindings (groups scm C) (scan-data T)) +(scm_swap_fluids (groups scm C) (scan-data T)) +(scm_swap_fluids_reverse (groups scm C) (scan-data T)) +(scm_switch_counter (groups scm C) (scan-data D)) +(scm_sym2var (groups scm C) (scan-data T)) +(scm_sym_and (groups scm C) (scan-data B)) +(scm_sym_apply (groups scm C) (scan-data B)) +(scm_sym_apply_frame (groups scm C) (scan-data B)) +(scm_sym_arity (groups scm C) (scan-data B)) +(scm_sym_arrow (groups scm C) (scan-data B)) +(scm_sym_at_call_with_values (groups scm C) (scan-data B)) +(scm_sym_atapply (groups scm C) (scan-data B)) +(scm_sym_atcall_cc (groups scm C) (scan-data B)) +(scm_sym_begin (groups scm C) (scan-data B)) +(scm_sym_breakpoint (groups scm C) (scan-data B)) +(scm_sym_case (groups scm C) (scan-data B)) +(scm_sym_column (groups scm C) (scan-data B)) +(scm_sym_cond (groups scm C) (scan-data B)) +(scm_sym_copy (groups scm C) (scan-data B)) +(scm_sym_define (groups scm C) (scan-data B)) +(scm_sym_delay (groups scm C) (scan-data B)) +(scm_sym_do (groups scm C) (scan-data B)) +(scm_sym_dot (groups scm C) (scan-data B)) +(scm_sym_else (groups scm C) (scan-data B)) +(scm_sym_enter_frame (groups scm C) (scan-data B)) +(scm_sym_exit_frame (groups scm C) (scan-data B)) +(scm_sym_filename (groups scm C) (scan-data B)) +(scm_sym_if (groups scm C) (scan-data B)) +(scm_sym_lambda (groups scm C) (scan-data B)) +(scm_sym_let (groups scm C) (scan-data B)) +(scm_sym_letrec (groups scm C) (scan-data B)) +(scm_sym_letstar (groups scm C) (scan-data B)) +(scm_sym_line (groups scm C) (scan-data B)) +(scm_sym_name (groups scm C) (scan-data B)) +(scm_sym_or (groups scm C) (scan-data B)) +(scm_sym_quasiquote (groups scm C) (scan-data B)) +(scm_sym_quote (groups scm C) (scan-data B)) +(scm_sym_set_x (groups scm C) (scan-data B)) +(scm_sym_system_procedure (groups scm C) (scan-data B)) +(scm_sym_trace (groups scm C) (scan-data B)) +(scm_sym_unquote (groups scm C) (scan-data B)) +(scm_sym_uq_splicing (groups scm C) (scan-data B)) +(scm_symbol_fref (groups scm C) (scan-data T)) +(scm_symbol_fset_x (groups scm C) (scan-data T)) +(scm_symbol_hash (groups scm C) (scan-data T)) +(scm_symbol_interned_p (groups scm C) (scan-data T)) +(scm_symbol_p (groups scm C) (scan-data T)) +(scm_symbol_pref (groups scm C) (scan-data T)) +(scm_symbol_pset_x (groups scm C) (scan-data T)) +(scm_symbol_to_string (groups scm C) (scan-data T)) +(scm_symbols_prehistory (groups scm C) (scan-data T)) +(scm_symlink (groups scm C) (scan-data T)) +(scm_sync (groups scm C) (scan-data T)) +(scm_sys_allocate_instance (groups scm C) (scan-data T)) +(scm_sys_atan2 (groups scm C) (scan-data T)) +(scm_sys_compute_applicable_methods (groups scm C) (scan-data T)) +(scm_sys_compute_slots (groups scm C) (scan-data T)) +(scm_sys_expt (groups scm C) (scan-data T)) +(scm_sys_fast_slot_ref (groups scm C) (scan-data T)) +(scm_sys_fast_slot_set_x (groups scm C) (scan-data T)) +(scm_sys_inherit_magic_x (groups scm C) (scan-data T)) +(scm_sys_initialize_object (groups scm C) (scan-data T)) +(scm_sys_invalidate_class (groups scm C) (scan-data T)) +(scm_sys_invalidate_method_cache_x (groups scm C) (scan-data T)) +(scm_sys_library_dir (groups scm C) (scan-data T)) +(scm_sys_make_void_port (groups scm C) (scan-data T)) +(scm_sys_method_more_specific_p (groups scm C) (scan-data T)) +(scm_sys_modify_class (groups scm C) (scan-data T)) +(scm_sys_modify_instance (groups scm C) (scan-data T)) +(scm_sys_package_data_dir (groups scm C) (scan-data T)) +(scm_sys_prep_layout_x (groups scm C) (scan-data T)) +(scm_sys_protects (groups scm C) (scan-data B)) +(scm_sys_search_load_path (groups scm C) (scan-data T)) +(scm_sys_set_object_setter_x (groups scm C) (scan-data T)) +(scm_sys_site_dir (groups scm C) (scan-data T)) +(scm_sys_tag_body (groups scm C) (scan-data T)) +(scm_syserror (groups scm C) (scan-data T)) +(scm_syserror_msg (groups scm C) (scan-data T)) +(scm_system (groups scm C) (scan-data T)) +(scm_system_async (groups scm C) (scan-data T)) +(scm_system_async_mark (groups scm C) (scan-data T)) +(scm_system_async_mark_from_signal_handler (groups scm C) (scan-data T)) +(scm_system_environment (groups scm C) (scan-data B)) +(scm_system_error_key (groups scm C) (scan-data B)) +(scm_system_module_env_p (groups scm C) (scan-data T)) +(scm_tables_prehistory (groups scm C) (scan-data T)) +(scm_take0str (groups scm C) (scan-data T)) +(scm_take_from_input_buffers (groups scm C) (scan-data T)) +(scm_take_str (groups scm C) (scan-data T)) +(scm_tc16_allocated (groups scm C) (scan-data B)) +(scm_tc16_array (groups scm C) (scan-data B)) +(scm_tc16_condvar (groups scm C) (scan-data B)) +(scm_tc16_continuation (groups scm C) (scan-data B)) +(scm_tc16_debugobj (groups scm C) (scan-data B)) +(scm_tc16_dir (groups scm C) (scan-data B)) +(scm_tc16_dynamic_obj (groups scm C) (scan-data B)) +(scm_tc16_environment (groups scm C) (scan-data B)) +(scm_tc16_eval_closure (groups scm C) (scan-data B)) +(scm_tc16_fluid (groups scm C) (scan-data B)) +(scm_tc16_fport (groups scm C) (scan-data B)) +(scm_tc16_hook (groups scm C) (scan-data B)) +(scm_tc16_keyword (groups scm C) (scan-data B)) +(scm_tc16_macro (groups scm C) (scan-data B)) +(scm_tc16_malloc (groups scm C) (scan-data B)) +(scm_tc16_memoized (groups scm C) (scan-data B)) +(scm_tc16_mutex (groups scm C) (scan-data B)) +(scm_tc16_observer (groups scm C) (scan-data B)) +(scm_tc16_port_with_ps (groups scm C) (scan-data B)) +(scm_tc16_promise (groups scm C) (scan-data B)) +(scm_tc16_regex (groups scm C) (scan-data B)) +(scm_tc16_root (groups scm C) (scan-data B)) +(scm_tc16_rstate (groups scm C) (scan-data B)) +(scm_tc16_srcprops (groups scm C) (scan-data B)) +(scm_tc16_strport (groups scm C) (scan-data B)) +(scm_tc16_thread (groups scm C) (scan-data B)) +(scm_tc16_void_port (groups scm C) (scan-data D)) +(scm_tcgetpgrp (groups scm C) (scan-data T)) +(scm_tcsetpgrp (groups scm C) (scan-data T)) +(scm_the_last_stack_fluid_var (groups scm C) (scan-data B)) +(scm_the_rng (groups scm C) (scan-data B)) +(scm_thread_count (groups scm C) (scan-data D)) +(scm_thread_sleep (groups scm C) (scan-data T)) +(scm_thread_usleep (groups scm C) (scan-data T)) +(scm_threads_init (groups scm C) (scan-data T)) +(scm_threads_mark_stacks (groups scm C) (scan-data T)) +(scm_throw (groups scm C) (scan-data T)) +(scm_thunk_p (groups scm C) (scan-data T)) +(scm_times (groups scm C) (scan-data T)) +(scm_tmpnam (groups scm C) (scan-data T)) +(scm_top_level_env (groups scm C) (scan-data T)) +(scm_transpose_array (groups scm C) (scan-data T)) +(scm_truncate (groups scm C) (scan-data T)) +(scm_truncate_file (groups scm C) (scan-data T)) +(scm_try_arbiter (groups scm C) (scan-data T)) +(scm_ttyname (groups scm C) (scan-data T)) +(scm_type_eval_environment (groups scm C) (scan-data D)) +(scm_type_export_environment (groups scm C) (scan-data D)) +(scm_type_import_environment (groups scm C) (scan-data D)) +(scm_type_leaf_environment (groups scm C) (scan-data D)) +(scm_tzset (groups scm C) (scan-data T)) +(scm_uint2num (groups scm C) (scan-data T)) +(scm_ulong2num (groups scm C) (scan-data T)) +(scm_ulong_long2num (groups scm C) (scan-data T)) +(scm_umask (groups scm C) (scan-data T)) +(scm_uname (groups scm C) (scan-data T)) +(scm_ungetc (groups scm C) (scan-data T)) +(scm_ungets (groups scm C) (scan-data T)) +(scm_uniform_array_read_x (groups scm C) (scan-data T)) +(scm_uniform_array_write (groups scm C) (scan-data T)) +(scm_uniform_element_size (groups scm C) (scan-data T)) +(scm_uniform_vector_length (groups scm C) (scan-data T)) +(scm_uniform_vector_ref (groups scm C) (scan-data T)) +(scm_unlock_mutex (groups scm C) (scan-data T)) +(scm_unmask_signals (groups scm C) (scan-data T)) +(scm_unmemocar (groups scm C) (scan-data T)) +(scm_unmemocopy (groups scm C) (scan-data T)) +(scm_unmemoize (groups scm C) (scan-data T)) +(scm_unread_char (groups scm C) (scan-data T)) +(scm_unread_string (groups scm C) (scan-data T)) +(scm_upcase (groups scm C) (scan-data T)) +(scm_usage_name (groups scm C) (scan-data D)) +(scm_ushort2num (groups scm C) (scan-data T)) +(scm_usleep (groups scm C) (scan-data T)) +(scm_utime (groups scm C) (scan-data T)) +(scm_valid_object_procedure_p (groups scm C) (scan-data T)) +(scm_valid_oport_value_p (groups scm C) (scan-data T)) +(scm_values (groups scm C) (scan-data T)) +(scm_values_vtable (groups scm C) (scan-data B)) +(scm_var_random_state (groups scm C) (scan-data B)) +(scm_variable_bound_p (groups scm C) (scan-data T)) +(scm_variable_p (groups scm C) (scan-data T)) +(scm_variable_ref (groups scm C) (scan-data T)) +(scm_variable_set_x (groups scm C) (scan-data T)) +(scm_vector (groups scm C) (scan-data T)) +(scm_vector_equal_p (groups scm C) (scan-data T)) +(scm_vector_fill_x (groups scm C) (scan-data T)) +(scm_vector_length (groups scm C) (scan-data T)) +(scm_vector_move_left_x (groups scm C) (scan-data T)) +(scm_vector_move_right_x (groups scm C) (scan-data T)) +(scm_vector_p (groups scm C) (scan-data T)) +(scm_vector_ref (groups scm C) (scan-data T)) +(scm_vector_set_x (groups scm C) (scan-data T)) +(scm_vector_to_list (groups scm C) (scan-data T)) +(scm_version (groups scm C) (scan-data T)) +(scm_void_port (groups scm C) (scan-data T)) +(scm_wait_condition_variable (groups scm C) (scan-data T)) +(scm_waitpid (groups scm C) (scan-data T)) +(scm_weak_key_hash_table_p (groups scm C) (scan-data T)) +(scm_weak_value_hash_table_p (groups scm C) (scan-data T)) +(scm_weak_vector (groups scm C) (scan-data T)) +(scm_weak_vector_p (groups scm C) (scan-data T)) +(scm_weak_vectors (groups scm C) (scan-data B)) +(scm_weaks_prehistory (groups scm C) (scan-data T)) +(scm_with_fluids (groups scm C) (scan-data T)) +(scm_with_traps (groups scm C) (scan-data T)) +(scm_wrap_component (groups scm C) (scan-data T)) +(scm_wrap_object (groups scm C) (scan-data T)) +(scm_write (groups scm C) (scan-data T)) +(scm_write_char (groups scm C) (scan-data T)) +(scm_write_line (groups scm C) (scan-data T)) +(scm_write_string_partial (groups scm C) (scan-data T)) +(scm_wrong_num_args (groups scm C) (scan-data T)) +(scm_wrong_type_arg (groups scm C) (scan-data T)) +(scm_wrong_type_arg_msg (groups scm C) (scan-data T)) +(scm_yield (groups scm C) (scan-data T)) +(scm_your_base (groups scm C) (scan-data D)) +(scm_zero_p (groups scm C) (scan-data T)) +(search-path (groups Scheme) (scan-data "#<primitive-procedure search-path>")) +(seed->random-state (groups Scheme) (scan-data "#<primitive-procedure seed->random-state>")) +(seek (groups Scheme) (scan-data "#<primitive-procedure seek>")) +(select (groups POSIX Scheme) (scan-data "#<primitive-procedure select>")) +(send (groups Scheme) (scan-data "#<primitive-procedure send>")) +(sendto (groups Scheme) (scan-data "#<primitive-procedure sendto>")) +(servent:aliases (groups Scheme) (scan-data "#<procedure servent:aliases (obj)>")) +(servent:name (groups Scheme) (scan-data "#<procedure servent:name (obj)>")) +(servent:port (groups Scheme) (scan-data "#<procedure servent:port (obj)>")) +(servent:proto (groups Scheme) (scan-data "#<procedure servent:proto (obj)>")) +(set! (groups Scheme) (scan-data "")) +(set-autoloaded! (groups Scheme) (scan-data "#<procedure set-autoloaded! (p m done?)>")) +(set-batch-mode?! (groups Scheme) (scan-data "#<procedure set-batch-mode?! (arg)>")) +(set-car! (groups Scheme) (scan-data "#<primitive-procedure set-car!>")) +(set-cdr! (groups Scheme) (scan-data "#<primitive-procedure set-cdr!>")) +(set-current-error-port (groups Scheme) (scan-data "#<primitive-procedure set-current-error-port>")) +(set-current-input-port (groups Scheme) (scan-data "#<primitive-procedure set-current-input-port>")) +(set-current-module (groups Scheme) (scan-data "#<primitive-procedure set-current-module>")) +(set-current-output-port (groups Scheme) (scan-data "#<primitive-procedure set-current-output-port>")) +(set-defmacro-transformer! (groups Scheme) (scan-data "#<procedure set-defmacro-transformer! (m t)>")) +(set-module-binder! (groups Scheme) (scan-data "#<procedure set-module-binder! (obj val)>")) +(set-module-eval-closure! (groups Scheme) (scan-data "#<procedure set-module-eval-closure! (module closure)>")) +(set-module-kind! (groups Scheme) (scan-data "#<procedure set-module-kind! (obj val)>")) +(set-module-name! (groups Scheme) (scan-data "#<procedure set-module-name! (obj val)>")) +(set-module-obarray! (groups Scheme) (scan-data "#<procedure set-module-obarray! (obj val)>")) +(set-module-observer-id! (groups Scheme) (scan-data "#<procedure set-module-observer-id! (obj val)>")) +(set-module-observers! (groups Scheme) (scan-data "#<procedure set-module-observers! (obj val)>")) +(set-module-public-interface! (groups Scheme) (scan-data "#<procedure set-module-public-interface! (m i)>")) +(set-module-transformer! (groups Scheme) (scan-data "#<procedure set-module-transformer! (obj val)>")) +(set-module-uses! (groups Scheme) (scan-data "#<procedure set-module-uses! (obj val)>")) +(set-object-procedure! (groups Scheme) (scan-data "#<primitive-procedure set-object-procedure!>")) +(set-object-properties! (groups Scheme) (scan-data "#<primitive-procedure set-object-properties!>")) +(set-object-property! (groups Scheme) (scan-data "#<primitive-procedure set-object-property!>")) +(set-port-column! (groups Scheme) (scan-data "#<primitive-procedure set-port-column!>")) +(set-port-filename! (groups Scheme) (scan-data "#<primitive-procedure set-port-filename!>")) +(set-port-line! (groups Scheme) (scan-data "#<primitive-procedure set-port-line!>")) +(set-port-revealed! (groups POSIX Scheme) (scan-data "#<primitive-procedure set-port-revealed!>")) +(set-procedure-properties! (groups Scheme) (scan-data "#<primitive-procedure set-procedure-properties!>")) +(set-procedure-property! (groups Scheme) (scan-data "#<primitive-procedure set-procedure-property!>")) +(set-repl-prompt! (groups Scheme) (scan-data "#<procedure set-repl-prompt! (v)>")) +(set-source-properties! (groups Scheme) (scan-data "#<primitive-procedure set-source-properties!>")) +(set-source-property! (groups Scheme) (scan-data "#<primitive-procedure set-source-property!>")) +(set-struct-vtable-name! (groups Scheme) (scan-data "#<primitive-procedure set-struct-vtable-name!>")) +(set-symbol-property! (groups Scheme) (scan-data "#<procedure set-symbol-property! (sym prop val)>")) +(set-system-module! (groups Scheme) (scan-data "#<procedure set-system-module! (m s)>")) +(set-tm:gmtoff (groups POSIX Scheme) (scan-data "#<procedure set-tm:gmtoff (obj val)>")) +(set-tm:hour (groups POSIX Scheme) (scan-data "#<procedure set-tm:hour (obj val)>")) +(set-tm:isdst (groups POSIX Scheme) (scan-data "#<procedure set-tm:isdst (obj val)>")) +(set-tm:mday (groups POSIX Scheme) (scan-data "#<procedure set-tm:mday (obj val)>")) +(set-tm:min (groups POSIX Scheme) (scan-data "#<procedure set-tm:min (obj val)>")) +(set-tm:mon (groups POSIX Scheme) (scan-data "#<procedure set-tm:mon (obj val)>")) +(set-tm:sec (groups POSIX Scheme) (scan-data "#<procedure set-tm:sec (obj val)>")) +(set-tm:wday (groups POSIX Scheme) (scan-data "#<procedure set-tm:wday (obj val)>")) +(set-tm:yday (groups POSIX Scheme) (scan-data "#<procedure set-tm:yday (obj val)>")) +(set-tm:year (groups POSIX Scheme) (scan-data "#<procedure set-tm:year (obj val)>")) +(set-tm:zone (groups POSIX Scheme) (scan-data "#<procedure set-tm:zone (obj val)>")) +(setegid (groups POSIX Scheme) (scan-data "#<primitive-procedure setegid>")) +(setenv (groups POSIX Scheme) (scan-data "#<procedure setenv (name value)>")) +(seteuid (groups POSIX Scheme) (scan-data "#<primitive-procedure seteuid>")) +(setgid (groups POSIX Scheme) (scan-data "#<primitive-procedure setgid>")) +(setgr (groups POSIX Scheme) (scan-data "#<primitive-procedure setgr>")) +(setgrent (groups POSIX Scheme) (scan-data "#<procedure setgrent ()>")) +(sethost (groups Scheme) (scan-data "#<primitive-procedure sethost>")) +(sethostent (groups Scheme) (scan-data "#<procedure sethostent stayopen>")) +(sethostname (groups POSIX Scheme) (scan-data "#<primitive-procedure sethostname>")) +(setitimer (groups POSIX Scheme) (scan-data "#<primitive-procedure setitimer>")) +(setlocale (groups POSIX Scheme) (scan-data "#<primitive-procedure setlocale>")) +(setnet (groups Scheme) (scan-data "#<primitive-procedure setnet>")) +(setnetent (groups Scheme) (scan-data "#<procedure setnetent stayopen>")) +(setpgid (groups POSIX Scheme) (scan-data "#<primitive-procedure setpgid>")) +(setpriority (groups POSIX Scheme) (scan-data "#<primitive-procedure setpriority>")) +(setproto (groups Scheme) (scan-data "#<primitive-procedure setproto>")) +(setprotoent (groups Scheme) (scan-data "#<procedure setprotoent stayopen>")) +(setpw (groups POSIX Scheme) (scan-data "#<primitive-procedure setpw>")) +(setpwent (groups POSIX Scheme) (scan-data "#<procedure setpwent ()>")) +(setserv (groups Scheme) (scan-data "#<primitive-procedure setserv>")) +(setservent (groups Scheme) (scan-data "#<procedure setservent stayopen>")) +(setsid (groups POSIX Scheme) (scan-data "#<primitive-procedure setsid>")) +(setsockopt (groups Scheme) (scan-data "#<primitive-procedure setsockopt>")) +(setter (groups Scheme) (scan-data "#<primitive-procedure setter>")) +(setuid (groups POSIX Scheme) (scan-data "#<primitive-procedure setuid>")) +(setvbuf (groups POSIX Scheme) (scan-data "#<primitive-procedure setvbuf>")) +(shared-array-increments (groups Scheme) (scan-data "#<primitive-procedure shared-array-increments>")) +(shared-array-offset (groups Scheme) (scan-data "#<primitive-procedure shared-array-offset>")) +(shared-array-root (groups Scheme) (scan-data "#<primitive-procedure shared-array-root>")) +(shutdown (groups Scheme) (scan-data "#<primitive-procedure shutdown>")) +(sigaction (groups POSIX Scheme) (scan-data "#<primitive-procedure sigaction>")) +(signal-condition-variable (groups Scheme) (scan-data "#<primitive-procedure signal-condition-variable>")) +(signal-handlers (groups Scheme) (scan-data "")) +(simple-format (groups Scheme) (scan-data "#<primitive-procedure simple-format>")) +(sin (groups Scheme) (scan-data "#<procedure sin (z)>")) +(single-active-thread? (groups Scheme) (scan-data "#<primitive-procedure single-active-thread?>")) +(sinh (groups Scheme) (scan-data "#<procedure sinh (z)>")) +(sleep (groups POSIX Scheme) (scan-data "#<primitive-procedure sleep>")) +(sloppy-assoc (groups Scheme) (scan-data "#<primitive-procedure sloppy-assoc>")) +(sloppy-assq (groups Scheme) (scan-data "#<primitive-procedure sloppy-assq>")) +(sloppy-assv (groups Scheme) (scan-data "#<primitive-procedure sloppy-assv>")) +(sockaddr:addr (groups Scheme) (scan-data "#<procedure sockaddr:addr (obj)>")) +(sockaddr:fam (groups Scheme) (scan-data "#<procedure sockaddr:fam (obj)>")) +(sockaddr:path (groups Scheme) (scan-data "#<procedure sockaddr:path (obj)>")) +(sockaddr:port (groups Scheme) (scan-data "#<procedure sockaddr:port (obj)>")) +(socket (groups Scheme) (scan-data "#<primitive-procedure socket>")) +(socketpair (groups Scheme) (scan-data "#<primitive-procedure socketpair>")) +(sort (groups Scheme) (scan-data "#<primitive-procedure sort>")) +(sort! (groups Scheme) (scan-data "#<primitive-procedure sort!>")) +(sort-list (groups Scheme) (scan-data "#<primitive-procedure sort-list>")) +(sort-list! (groups Scheme) (scan-data "#<primitive-procedure sort-list!>")) +(sorted? (groups Scheme) (scan-data "#<primitive-procedure sorted?>")) +(source-properties (groups Scheme) (scan-data "#<primitive-procedure source-properties>")) +(source-property (groups Scheme) (scan-data "#<primitive-procedure source-property>")) +(source-whash (groups Scheme) (scan-data "")) +(sqrt (groups Scheme) (scan-data "#<procedure sqrt (z)>")) +(stable-sort (groups Scheme) (scan-data "#<primitive-procedure stable-sort>")) +(stable-sort! (groups Scheme) (scan-data "#<primitive-procedure stable-sort!>")) +(stack-id (groups Scheme) (scan-data "#<primitive-procedure stack-id>")) +(stack-length (groups Scheme) (scan-data "#<primitive-procedure stack-length>")) +(stack-ref (groups Scheme) (scan-data "#<primitive-procedure stack-ref>")) +(stack-saved? (groups Scheme) (scan-data "")) +(stack? (groups Scheme) (scan-data "#<primitive-procedure stack?>")) +(standard-eval-closure (groups Scheme) (scan-data "#<primitive-procedure standard-eval-closure>")) +(standard-interface-eval-closure (groups Scheme) (scan-data "#<primitive-procedure standard-interface-eval-closure>")) +(start-stack (groups Scheme) (scan-data "")) +(stat (groups POSIX Scheme) (scan-data "#<primitive-procedure stat>")) +(stat:atime (groups POSIX Scheme) (scan-data "#<procedure stat:atime (f)>")) +(stat:blksize (groups POSIX Scheme) (scan-data "#<procedure stat:blksize (f)>")) +(stat:blocks (groups POSIX Scheme) (scan-data "#<procedure stat:blocks (f)>")) +(stat:ctime (groups POSIX Scheme) (scan-data "#<procedure stat:ctime (f)>")) +(stat:dev (groups POSIX Scheme) (scan-data "#<procedure stat:dev (f)>")) +(stat:gid (groups POSIX Scheme) (scan-data "#<procedure stat:gid (f)>")) +(stat:ino (groups POSIX Scheme) (scan-data "#<procedure stat:ino (f)>")) +(stat:mode (groups POSIX Scheme) (scan-data "#<procedure stat:mode (f)>")) +(stat:mtime (groups POSIX Scheme) (scan-data "#<procedure stat:mtime (f)>")) +(stat:nlink (groups POSIX Scheme) (scan-data "#<procedure stat:nlink (f)>")) +(stat:perms (groups POSIX Scheme) (scan-data "#<procedure stat:perms (f)>")) +(stat:rdev (groups POSIX Scheme) (scan-data "#<procedure stat:rdev (f)>")) +(stat:size (groups POSIX Scheme) (scan-data "#<procedure stat:size (f)>")) +(stat:type (groups POSIX Scheme) (scan-data "#<procedure stat:type (f)>")) +(stat:uid (groups POSIX Scheme) (scan-data "#<procedure stat:uid (f)>")) +(status:exit-val (groups POSIX Scheme) (scan-data "#<primitive-procedure status:exit-val>")) +(status:stop-sig (groups POSIX Scheme) (scan-data "#<primitive-procedure status:stop-sig>")) +(status:term-sig (groups POSIX Scheme) (scan-data "#<primitive-procedure status:term-sig>")) +(strerror (groups Scheme) (scan-data "#<primitive-procedure strerror>")) +(strftime (groups POSIX Scheme) (scan-data "#<primitive-procedure strftime>")) +(string (groups Scheme) (scan-data "#<primitive-procedure string>")) +(string->list (groups Scheme) (scan-data "#<primitive-procedure string->list>")) +(string->number (groups Scheme) (scan-data "#<primitive-procedure string->number>")) +(string->symbol (groups Scheme) (scan-data "#<primitive-procedure string->symbol>")) +(string-append (groups Scheme) (scan-data "#<primitive-procedure string-append>")) +(string-capitalize (groups Scheme) (scan-data "#<primitive-procedure string-capitalize>")) +(string-capitalize! (groups Scheme) (scan-data "#<primitive-procedure string-capitalize!>")) +(string-ci->symbol (groups Scheme) (scan-data "#<primitive-procedure string-ci->symbol>")) +(string-ci<=? (groups Scheme) (scan-data "#<primitive-procedure string-ci<=?>")) +(string-ci<? (groups Scheme) (scan-data "#<primitive-procedure string-ci<?>")) +(string-ci=? (groups Scheme) (scan-data "#<primitive-procedure string-ci=?>")) +(string-ci>=? (groups Scheme) (scan-data "#<primitive-procedure string-ci>=?>")) +(string-ci>? (groups Scheme) (scan-data "#<primitive-procedure string-ci>?>")) +(string-copy (groups Scheme) (scan-data "#<primitive-procedure string-copy>")) +(string-downcase (groups Scheme) (scan-data "#<primitive-procedure string-downcase>")) +(string-downcase! (groups Scheme) (scan-data "#<primitive-procedure string-downcase!>")) +(string-fill! (groups Scheme) (scan-data "#<primitive-procedure string-fill!>")) +(string-index (groups Scheme) (scan-data "#<primitive-procedure string-index>")) +(string-length (groups Scheme) (scan-data "#<primitive-procedure string-length>")) +(string-null? (groups Scheme) (scan-data "#<primitive-procedure string-null?>")) +(string-ref (groups Scheme) (scan-data "#<primitive-procedure string-ref>")) +(string-rindex (groups Scheme) (scan-data "#<primitive-procedure string-rindex>")) +(string-set! (groups Scheme) (scan-data "#<primitive-procedure string-set!>")) +(string-split (groups Scheme) (scan-data "#<primitive-procedure string-split>")) +(string-upcase (groups Scheme) (scan-data "#<primitive-procedure string-upcase>")) +(string-upcase! (groups Scheme) (scan-data "#<primitive-procedure string-upcase!>")) +(string<=? (groups Scheme) (scan-data "#<primitive-procedure string<=?>")) +(string<? (groups Scheme) (scan-data "#<primitive-procedure string<?>")) +(string=? (groups Scheme) (scan-data "#<primitive-procedure string=?>")) +(string>=? (groups Scheme) (scan-data "#<primitive-procedure string>=?>")) +(string>? (groups Scheme) (scan-data "#<primitive-procedure string>?>")) +(string? (groups Scheme) (scan-data "#<primitive-procedure string?>")) +(strptime (groups POSIX Scheme) (scan-data "#<primitive-procedure strptime>")) +(struct-layout (groups Scheme) (scan-data "#<procedure struct-layout (s)>")) +(struct-ref (groups Scheme) (scan-data "#<primitive-procedure struct-ref>")) +(struct-set! (groups Scheme) (scan-data "#<primitive-procedure struct-set!>")) +(struct-vtable (groups Scheme) (scan-data "#<primitive-procedure struct-vtable>")) +(struct-vtable-name (groups Scheme) (scan-data "#<primitive-procedure struct-vtable-name>")) +(struct-vtable-tag (groups Scheme) (scan-data "#<primitive-procedure struct-vtable-tag>")) +(struct-vtable? (groups Scheme) (scan-data "#<primitive-procedure struct-vtable?>")) +(struct? (groups Scheme) (scan-data "#<primitive-procedure struct?>")) +(substring (groups Scheme) (scan-data "#<primitive-procedure substring>")) +(substring-fill! (groups Scheme) (scan-data "#<primitive-procedure substring-fill!>")) +(substring-move! (groups Scheme) (scan-data "#<primitive-procedure substring-move!>")) +(symbol (groups Scheme) (scan-data "#<procedure symbol args>")) +(symbol->keyword (groups Scheme) (scan-data "#<procedure symbol->keyword (symbol)>")) +(symbol->string (groups Scheme) (scan-data "#<primitive-procedure symbol->string>")) +(symbol-append (groups Scheme) (scan-data "#<procedure symbol-append args>")) +(symbol-fref (groups Scheme) (scan-data "#<primitive-procedure symbol-fref>")) +(symbol-fset! (groups Scheme) (scan-data "#<primitive-procedure symbol-fset!>")) +(symbol-hash (groups Scheme) (scan-data "#<primitive-procedure symbol-hash>")) +(symbol-interned? (groups Scheme) (scan-data "#<primitive-procedure symbol-interned?>")) +(symbol-pref (groups Scheme) (scan-data "#<primitive-procedure symbol-pref>")) +(symbol-prefix-proc (groups Scheme) (scan-data "#<procedure symbol-prefix-proc (prefix)>")) +(symbol-property (groups Scheme) (scan-data "#<procedure symbol-property (sym prop)>")) +(symbol-property-remove! (groups Scheme) (scan-data "#<procedure symbol-property-remove! (sym prop)>")) +(symbol-pset! (groups Scheme) (scan-data "#<primitive-procedure symbol-pset!>")) +(symbol? (groups Scheme) (scan-data "#<primitive-procedure symbol?>")) +(symlink (groups POSIX Scheme) (scan-data "#<primitive-procedure symlink>")) +(sync (groups POSIX Scheme) (scan-data "#<primitive-procedure sync>")) +(system (groups POSIX Scheme) (scan-data "#<primitive-procedure system>")) +(system-async (groups Scheme) (scan-data "#<primitive-procedure system-async>")) +(system-async-mark (groups Scheme) (scan-data "#<primitive-procedure system-async-mark>")) +(system-error-errno (groups Scheme) (scan-data "#<procedure system-error-errno (args)>")) +(tan (groups Scheme) (scan-data "#<procedure tan (z)>")) +(tanh (groups Scheme) (scan-data "#<procedure tanh (z)>")) +(tcgetpgrp (groups POSIX Scheme) (scan-data "#<primitive-procedure tcgetpgrp>")) +(tcsetpgrp (groups POSIX Scheme) (scan-data "#<primitive-procedure tcsetpgrp>")) +(the-environment (groups Scheme) (scan-data "")) +(the-eof-object (groups Scheme) (scan-data "")) +(the-last-stack (groups Scheme) (scan-data "")) +(the-root-environment (groups Scheme) (scan-data "")) +(the-root-module (groups Scheme) (scan-data "")) +(the-scm-module (groups Scheme) (scan-data "")) +(throw (groups Scheme) (scan-data "#<primitive-procedure throw>")) +(thunk? (groups Scheme) (scan-data "#<primitive-procedure thunk?>")) +(times (groups POSIX Scheme) (scan-data "#<primitive-procedure times>")) +(tm:gmtoff (groups POSIX Scheme) (scan-data "#<procedure tm:gmtoff (obj)>")) +(tm:hour (groups POSIX Scheme) (scan-data "#<procedure tm:hour (obj)>")) +(tm:isdst (groups POSIX Scheme) (scan-data "#<procedure tm:isdst (obj)>")) +(tm:mday (groups POSIX Scheme) (scan-data "#<procedure tm:mday (obj)>")) +(tm:min (groups POSIX Scheme) (scan-data "#<procedure tm:min (obj)>")) +(tm:mon (groups POSIX Scheme) (scan-data "#<procedure tm:mon (obj)>")) +(tm:sec (groups POSIX Scheme) (scan-data "#<procedure tm:sec (obj)>")) +(tm:wday (groups POSIX Scheme) (scan-data "#<procedure tm:wday (obj)>")) +(tm:yday (groups POSIX Scheme) (scan-data "#<procedure tm:yday (obj)>")) +(tm:year (groups POSIX Scheme) (scan-data "#<procedure tm:year (obj)>")) +(tm:zone (groups POSIX Scheme) (scan-data "#<procedure tm:zone (obj)>")) +(tmpnam (groups POSIX Scheme) (scan-data "#<primitive-procedure tmpnam>")) +(tms:clock (groups POSIX Scheme) (scan-data "#<procedure tms:clock (obj)>")) +(tms:cstime (groups POSIX Scheme) (scan-data "#<procedure tms:cstime (obj)>")) +(tms:cutime (groups POSIX Scheme) (scan-data "#<procedure tms:cutime (obj)>")) +(tms:stime (groups POSIX Scheme) (scan-data "#<procedure tms:stime (obj)>")) +(tms:utime (groups POSIX Scheme) (scan-data "#<procedure tms:utime (obj)>")) +(top-repl (groups Scheme) (scan-data "#<procedure top-repl ()>")) +(transform-usage-lambda (groups Scheme) (scan-data "#<procedure transform-usage-lambda (cases)>")) +(transpose-array (groups Scheme) (scan-data "#<primitive-procedure transpose-array>")) +(trap-disable (groups Scheme) (scan-data "#<procedure trap-disable flags>")) +(trap-enable (groups Scheme) (scan-data "#<procedure trap-enable flags>")) +(trap-set! (groups Scheme) (scan-data "")) +(traps (groups Scheme) (scan-data "#<procedure traps args>")) +(truncate (groups Scheme) (scan-data "#<primitive-procedure truncate>")) +(truncate-file (groups Scheme) (scan-data "#<primitive-procedure truncate-file>")) +(try-arbiter (groups Scheme) (scan-data "#<primitive-procedure try-arbiter>")) +(try-load-module (groups Scheme) (scan-data "#<procedure try-load-module (name)>")) +(try-module-autoload (groups Scheme) (scan-data "#<procedure try-module-autoload (module-name)>")) +(ttyname (groups POSIX Scheme) (scan-data "#<primitive-procedure ttyname>")) +(turn-on-debugging (groups Scheme) (scan-data "#<procedure turn-on-debugging ()>")) +(tzset (groups POSIX Scheme) (scan-data "#<primitive-procedure tzset>")) +(umask (groups POSIX Scheme) (scan-data "#<primitive-procedure umask>")) +(uname (groups POSIX Scheme) (scan-data "#<primitive-procedure uname>")) +(undefine (groups Scheme) (scan-data "")) +(uniform-array-read! (groups Scheme) (scan-data "#<primitive-procedure uniform-array-read!>")) +(uniform-array-set1! (groups Scheme) (scan-data "#<primitive-procedure uniform-array-set1!>")) +(uniform-array-write (groups Scheme) (scan-data "#<primitive-procedure uniform-array-write>")) +(uniform-vector-fill! (groups Scheme) (scan-data "#<primitive-procedure array-fill!>")) +(uniform-vector-length (groups Scheme) (scan-data "#<primitive-procedure uniform-vector-length>")) +(uniform-vector-read! (groups Scheme) (scan-data "#<primitive-procedure uniform-array-read!>")) +(uniform-vector-ref (groups Scheme) (scan-data "#<primitive-procedure uniform-vector-ref>")) +(uniform-vector-set! (groups Scheme) (scan-data "#<procedure uniform-vector-set! (u i o)>")) +(uniform-vector-write (groups Scheme) (scan-data "#<primitive-procedure uniform-array-write>")) +(uniform-vector? (groups Scheme) (scan-data "#<primitive-procedure array?>")) +(unlock-mutex (groups Scheme) (scan-data "#<primitive-procedure unlock-mutex>")) +(unmask-signals (groups Scheme) (scan-data "#<primitive-procedure unmask-signals>")) +(unmemoize (groups Scheme) (scan-data "#<primitive-procedure unmemoize>")) +(unread-char (groups POSIX Scheme) (scan-data "#<primitive-procedure unread-char>")) +(unread-string (groups POSIX Scheme) (scan-data "#<primitive-procedure unread-string>")) +(unsetenv (groups Scheme) (scan-data "#<procedure unsetenv (name)>")) +(unspecified? (groups Scheme) (scan-data "#<procedure unspecified? (v)>")) +(use-emacs-interface (groups Scheme) (scan-data "")) +(use-modules (groups Scheme) (scan-data "")) +(use-srfis (groups Scheme) (scan-data "#<procedure use-srfis (srfis)>")) +(use-syntax (groups Scheme) (scan-data "")) +(using-readline? (groups Scheme) (scan-data "#<procedure-with-setter>")) +(usleep (groups POSIX Scheme) (scan-data "#<primitive-procedure usleep>")) +(utime (groups POSIX Scheme) (scan-data "#<primitive-procedure utime>")) +(utsname:machine (groups POSIX Scheme) (scan-data "#<procedure utsname:machine (obj)>")) +(utsname:nodename (groups POSIX Scheme) (scan-data "#<procedure utsname:nodename (obj)>")) +(utsname:release (groups POSIX Scheme) (scan-data "#<procedure utsname:release (obj)>")) +(utsname:sysname (groups POSIX Scheme) (scan-data "#<procedure utsname:sysname (obj)>")) +(utsname:version (groups POSIX Scheme) (scan-data "#<procedure utsname:version (obj)>")) +(valid-object-procedure? (groups Scheme) (scan-data "#<primitive-procedure valid-object-procedure?>")) +(values (groups Scheme) (scan-data "#<primitive-procedure values>")) +(variable-bound? (groups Scheme) (scan-data "#<primitive-procedure variable-bound?>")) +(variable-ref (groups Scheme) (scan-data "#<primitive-procedure variable-ref>")) +(variable-set! (groups Scheme) (scan-data "#<primitive-procedure variable-set!>")) +(variable? (groups Scheme) (scan-data "#<primitive-procedure variable?>")) +(vector (groups Scheme) (scan-data "#<primitive-procedure vector>")) +(vector->list (groups Scheme) (scan-data "#<primitive-procedure vector->list>")) +(vector-fill! (groups Scheme) (scan-data "#<primitive-procedure vector-fill!>")) +(vector-length (groups Scheme) (scan-data "#<primitive-procedure vector-length>")) +(vector-move-left! (groups Scheme) (scan-data "#<primitive-procedure vector-move-left!>")) +(vector-move-right! (groups Scheme) (scan-data "#<primitive-procedure vector-move-right!>")) +(vector-ref (groups Scheme) (scan-data "#<primitive-procedure vector-ref>")) +(vector-set! (groups Scheme) (scan-data "#<primitive-procedure vector-set!>")) +(vector? (groups Scheme) (scan-data "#<primitive-procedure vector?>")) +(version (groups Scheme) (scan-data "#<primitive-procedure version>")) +(vtable-index-layout (groups Scheme) (scan-data "")) +(vtable-index-printer (groups Scheme) (scan-data "")) +(vtable-index-vtable (groups Scheme) (scan-data "")) +(vtable-offset-user (groups Scheme) (scan-data "")) +(wait-condition-variable (groups Scheme) (scan-data "#<primitive-procedure wait-condition-variable>")) +(waitpid (groups POSIX Scheme) (scan-data "#<primitive-procedure waitpid>")) +(warn (groups Scheme) (scan-data "#<procedure warn stuff>")) +(weak-key-hash-table? (groups Scheme) (scan-data "#<primitive-procedure weak-key-hash-table?>")) +(weak-value-hash-table? (groups Scheme) (scan-data "#<primitive-procedure weak-value-hash-table?>")) +(weak-vector (groups Scheme) (scan-data "#<primitive-procedure weak-vector>")) +(weak-vector? (groups Scheme) (scan-data "#<primitive-procedure weak-vector?>")) +(while (groups Scheme) (scan-data "")) +(with-error-to-file (groups Scheme) (scan-data "#<procedure with-error-to-file (file thunk)>")) +(with-error-to-port (groups Scheme) (scan-data "#<procedure with-error-to-port (port thunk)>")) +(with-error-to-string (groups Scheme) (scan-data "#<procedure with-error-to-string (thunk)>")) +(with-fluids (groups Scheme) (scan-data "")) +(with-fluids* (groups Scheme) (scan-data "#<primitive-procedure with-fluids*>")) +(with-input-from-file (groups Scheme) (scan-data "#<procedure with-input-from-file (file thunk)>")) +(with-input-from-port (groups Scheme) (scan-data "#<procedure with-input-from-port (port thunk)>")) +(with-input-from-string (groups Scheme) (scan-data "#<procedure with-input-from-string (string thunk)>")) +(with-output-to-file (groups Scheme) (scan-data "#<procedure with-output-to-file (file thunk)>")) +(with-output-to-port (groups Scheme) (scan-data "#<procedure with-output-to-port (port thunk)>")) +(with-output-to-string (groups Scheme) (scan-data "#<procedure with-output-to-string (thunk)>")) +(with-traps (groups Scheme) (scan-data "#<primitive-procedure with-traps>")) +(write (groups Scheme) (scan-data "#<primitive-procedure write>")) +(write-char (groups Scheme) (scan-data "#<primitive-procedure write-char>")) +(xformer-table (groups Scheme) (scan-data "")) +(yield (groups Scheme) (scan-data "#<primitive-procedure yield>")) +(zero? (groups Scheme) (scan-data "#<primitive-procedure zero?>")) +) ;; end of interface +) ;; eof diff --git a/doc/guile.1 b/doc/guile.1 new file mode 100644 index 000000000..6097ac2e9 --- /dev/null +++ b/doc/guile.1 @@ -0,0 +1,258 @@ +.\" Written by Robert Merkel (rgmerk@mira.net) +.\" augmented by Rob Browning <rlb@cs.utexas.edu> +.\" Process this file with +.\" groff -man -Tascii foo.1 +.\" +.\" title section date source manual +.TH GUILE 1 "2017-05-22" GNU "GNU Guile 3.0" +. +.SH NAME +guile \- The GNU Project Extension Language +. +.SH SYNOPSIS +.B guile +.RB [\| \-L +.IR DIRECTORY \|] +.RB [\| \-l +.IR FILE \|] +.RB [\| \-e +.IR FUNCTION \|] +.\".RI [\| \\\\ \|] +.RB [\| \e \|] +.RB [\| \-c +.IR EXPR \|] +.RB [\| \-s +.IR SCRIPT \|] +.RB [\| \-\- \|] +.RI [\| SCRIPT +.RI [\| ARGs\ for\ SCRIPT \|]\c +.RI ] + +Only the most useful options are listed here; +see below for the remainder. +. +.SH DESCRIPTION +GNU Guile is an implementation of the Scheme programming language. +It extends the R5RS and R6RS language standards, +providing additional features necessary for real-world use. + +Guile works well for interactive use, +basic scripting, +and extension of larger applications, +as well as for stand-alone Scheme application development. + +The +.B guile +executable itself provides a stand-alone interactive compiler and +run-time for Scheme programs, +both for interactive use and for executing Scheme scripts or programs. + +This manual page provides only brief instruction in invoking +.B guile +from the command line. +Please consult the Guile info documentation for more information, +(type \fB info "(guile)Invoking Guile"\fR at a command prompt). +. +.SH OPTIONS +.TP +.BI -L \ DIRECTORY +Add \fIDIRECTORY\fR to the front of Guile's module load path. +. +.TP +.BI -l \ FILE +Load Scheme source code from \fIFILE\fR. +. +.TP +.BI -e \ FUNCTION +After reading \fISCRIPT\fR, apply \fIFUNCTION\fR to command-line arguments. +Note that \fIFUNCTION\fR is evaluated, +so, for example, +.B (@ (my-module) my-proc) +is valid here. +. +.TP +.B \e +The "meta switch", used to work around limitations in #! scripts. +See "The Meta Switch" in the texinfo documentation for more details. +. +.TP +.B -- +Stop argument processing, and start +.B guile +in interactive mode. +. +.TP +.BI -c \ EXPR +Stop argument processing, +and evaluate \fIEXPR\fR as a Scheme expression. +. +.TP +.BI -s \ SCRIPT-FILE +Load Scheme source from \fISCRIPT-FILE\fR and execute as a script. +Note that in many cases it is not necessary to use \fB-s\fR; +one may invoke +.B guile +simply as +.B guile +.I SCRIPT-FILE ARG... +. +.TP +.B -ds +Carry out \fB\-s \fISCRIPT\fR at this point in the option sequence. +Note that this argument must be used in conjunction with \fB\-s\fR. +. +.TP +.B --debug +Start +.B guile +with the debugging VM. +By default, debugging is on when +.B guile +is invoked interactively; +it is off otherwise. +. +.TP +.B --no-debug +Start +.B guile +without the debugging VM, +even if +.B guile +is being run interactively. +. +.TP +.B --auto-compile +Compile source files automatically (default behavior). +. +.TP +.B --no-auto-compile +Disable automatic source file compilation. +. +.TP +\fB\-\-listen\fR[=\fIP\fR] +Listen on a port or socket for remote REPL connections. +See the manual for more details. +. +.TP +\fB\-\-use\-srfi\fR=\fIN,M\fR... +Load SRFI extensions \fIN\fR, \fIM\fR, etc. +For example, +\fB \-\-use\-srfi\fR=\fI8,13\fR. +. +.TP +.BI -x \ EXTENSION +Add \fIEXTENSION\fR to the +.B guile +load extension list. +. +.TP +\fB\-h\fR, \fB\-\-help\fR +Describe command-line options and exit. +. +.TP +\fB\-v\fR, \fB\-\-version\fR +Display guile version and exit. +. +.TP +.B -q +In interactive mode, +suppress loading the user's initialization file, +.I ~/.guile. +. +.SH ENVIRONMENT +.\".TP \w'MANROFFSEQ\ \ 'u +.TP +.B GUILE_LOAD_PATH +If +.RB $ GUILE_LOAD_PATH +is set before +.B guile +is started, +its value is used to augment the path to search for Scheme files when +loading. +It should be a colon-separated list of directories, +which will be prefixed to the default +.B %load-path. +.TP +.B GUILE_LOAD_COMPILED_PATH +If +.RB $ GUILE_LOAD_COMPILED_PATH +is set before +.B guile +is started, +its value is used to augment the path to search for compiled +Scheme files (.go files) when loading. +It should be a colon-separated list of directories, +which will be prefixed to the default +.B %load-compiled-path. +. +.SH FILES +.TP +.I ~/.guile +A Guile script that is executed before any other processing occurs. +For example, the following +.I .guile +activates guile's readline interface: + +.RS 9 +.B (use-modules (ice-9 readline)) +.RS 0 +.B (activate-readline) +. +.SH "SEE ALSO" +The full documentation for Guile is maintained as a Texinfo manual. +If the +.B info +and +.B guile +programs are properly installed at your site, +the command +.IP +.B info guile +.PP +should give you access to the complete manual. + +http://www.schemers.org provides a general introduction to the +Scheme language. +. +.SH "REPORTING BUGS" +There is a mailing list, +bug-guile@gnu.org, +for reporting Guile bugs and fixes. +But before reporting something as a bug, +please try to be sure that it really is a bug, +not a misunderstanding or a deliberate feature. +We ask you to read the section ``Reporting Bugs'' in the Guile reference +manual (or Info system) for hints on how and when to report bugs. +Also, include the version number of the Guile you are running in every bug +report that you send in. +Bugs tend actually to get fixed if they can be isolated, +so it is in your interest to report them in such a way that they can be +easily reproduced. +. +.SH COPYING +Copyright (C) 2010, 2011 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of this +document provided the copyright notice and this permission notice are +preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +document under the conditions for verbatim copying, +provided that the entire resulting derived work is distributed under the +terms of a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this +document into another language, +under the above conditions for modified versions, +except that this permission notice may be stated in a +translation approved by the Free Software Foundation. +. +.SH AUTHORS +Robert Merkel <rgmerk@mira.net> wrote this manpage. +Rob Browning <rlb@cs.utexas.edu> has added to it. + +.B guile +is GNU software. +Guile is originally based on Aubrey Jaffer's SCM interpreter, +and is the work of many individuals. diff --git a/doc/hacks.el b/doc/hacks.el new file mode 100644 index 000000000..c5a3f576b --- /dev/null +++ b/doc/hacks.el @@ -0,0 +1,16 @@ +;;;; hacks.el --- a few functions to help me work on the manual +;;;; Jim Blandy <jimb@red-bean.com> --- October 1998 + +(defun jh-exemplify-region (start end) + (interactive "r") + (save-excursion + (save-restriction + (narrow-to-region start end) + + ;; Texinfo doesn't handle tabs well. + (untabify (point-min) (point-max)) + + ;; Quote any characters special to texinfo. + (goto-char (point-min)) + (while (re-search-forward "[{}@]" nil t) + (replace-match "@\\&"))))) diff --git a/doc/r5rs/ChangeLog-2008 b/doc/r5rs/ChangeLog-2008 new file mode 100644 index 000000000..b5e4e9a3c --- /dev/null +++ b/doc/r5rs/ChangeLog-2008 @@ -0,0 +1,17 @@ +2004-11-05 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * r5rs.texi: Use @ifnottex instead of @ifinfo around the "Top" + node declaration so that html can be generated. Use only lower + case inside @sc. Move editors outside of author table, which + looks better in html. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + * Makefile.am (TEXINFO_TEX): Added; avoids shipping multiple copies of + texinfo.tex in a single distribution. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + The change log for files in this directory continues backwards + from 2001-08-27 in ../ChangeLog, as all the Guile documentation + prior to this date was contained in a single directory. diff --git a/doc/r5rs/Makefile.am b/doc/r5rs/Makefile.am new file mode 100644 index 000000000..c64e4ffb1 --- /dev/null +++ b/doc/r5rs/Makefile.am @@ -0,0 +1,26 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 1998, 2006, 2008 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE is free software; you can redistribute it and/or modify it +## under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 3, or +## (at your option) any later version. +## +## GUILE is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with GUILE; see the file COPYING.LESSER. If not, +## write to the Free Software Foundation, Inc., 51 Franklin Street, +## Fifth Floor, Boston, MA 02110-1301 USA + +AUTOMAKE_OPTIONS = gnu + +info_TEXINFOS = r5rs.texi + +EXTRA_DIST = ChangeLog-2008 diff --git a/doc/r5rs/r5rs.texi b/doc/r5rs/r5rs.texi new file mode 100644 index 000000000..775c93094 --- /dev/null +++ b/doc/r5rs/r5rs.texi @@ -0,0 +1,8536 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename r5rs.info +@settitle Revised(5) Scheme + +@c This copy of r5rs.texi differs from Aubrey Jaffer's master copy +@c by a set of changes to allow the building of r5rs.dvi from r5rs.texi. +@c Aubrey Jaffer's view - which I agree with - is that, given that +@c people have the option of building r5rs.dvi from the original +@c LaTeX distribution for R5RS, it is not worth fixing his master +@c copy of r5rs.texi and the tool which autogenerates it. On the +@c other hand, it is a marginal convenience for people to be able to +@c build hardcopy from r5rs.texi, even if the results are less good +@c than with the original LaTeX. Hence the following fixes. +@c (lines 714, 725, 728, 1614, 2258): Remove invalid parentheses from +@c @deffn statements. +@c (line 2316): Change @deffnx to @deffn, and insert `@end deffn' to +@c terminate preceding @deffn. +@c (line 7320): Insert `@c ' at beginning of lines that are intended +@c to be @ignore'd. +@c +@c NJ 2001/1/26 + +@c \documentclass[twoside]{algol60} + +@c \pagestyle{headings} +@c \showboxdepth=0 + + + +@c \def\headertitle{Revised$^{5}$ Scheme} +@c \def\integerversion{5} + +@c Sizes and dimensions + +@c \topmargin -.375in % Nominal distance from top of page to top of + +@c box containing running head. +@c \headsep 15pt % Space between running head and text. + +@c \textheight 663pt % Height of text (including footnotes and figures, + +@c excluding running head and foot). + +@c \textwidth 523pt % Width of text line. +@c \columnsep 15pt % Space between columns +@c \columnseprule 0pt % Width of rule between columns. + +@c \parskip 5pt plus 2pt minus 2pt % Extra vertical space between paragraphs. +@c \parindent 0pt % Width of paragraph indentation. +@c \topsep 0pt plus 2pt % Extra vertical space, in addition to + +@c \parskip, added above and below list and + +@c paragraphing environments. + +@c \oddsidemargin -.5in % Left margin on odd-numbered pages. +@c \evensidemargin -.5in % Left margin on even-numbered pages. + +@c % End of sizes and dimensions + +@paragraphindent 0 +@c %**end of header +@c syncodeindex fn cp + +@ifinfo +@dircategory The Algorithmic Language Scheme +@direntry +* R5RS: (r5rs). The Revised(5) Report on Scheme. +@end direntry +@end ifinfo + + +@c \parindent 0pt %!! 15pt % Width of paragraph indentation. + + @b{20 February 1998} +@c \hfil \today{} + +@c @include{first} +@titlepage + +@c HTML first page +@title Scheme +@subtitle Revised(5) Report on the Algorithmic Language Scheme +@c First page + +@c \thispagestyle{empty} + +@c \todo{"another" report?} + + +@author R@sc{ICHARD} K@sc{ELSEY}, W@sc{ILLIAM} C@sc{LINGER, AND} J@sc{ONATHAN} R@sc{EES} (@i{Editors}) +@author H. A@sc{BELSON} +@author R. K. D@sc{YBVIG} +@author C. T. H@sc{AYNES} +@author G. J. R@sc{OZAS} +@author N. I. A@sc{DAMS IV} +@author D. P. F@sc{RIEDMAN} +@author E. K@sc{OHLBECKER} +@author G. L. S@sc{TEELE} J@sc{R}. +@author D. H. B@sc{ARTLEY} +@author R. H@sc{ALSTEAD} +@author D. O@sc{XLEY} +@author G. J. S@sc{USSMAN} +@author G. B@sc{ROOKS} +@author C. H@sc{ANSON} +@author K. M. P@sc{ITMAN} +@author M. W@sc{AND} + + +@c {\it Dedicated to the Memory of ALGOL 60} +@i{Dedicated to the Memory of Robert Hieb} +@c [For the macros in R5RS -RK] + + + + +@majorheading Summary + + +The report gives a defining description of the programming language +Scheme. Scheme is a statically scoped and properly tail-recursive +dialect of the Lisp programming language invented by Guy Lewis +Steele Jr.@: and Gerald Jay Sussman. It was designed to have an +exceptionally clear and simple semantics and few different ways to +form expressions. A wide variety of programming paradigms, including +imperative, functional, and message passing styles, find convenient +expression in Scheme. + +The introduction offers a brief history of the language and of +the report. + +The first three chapters present the fundamental ideas of the +language and describe the notational conventions used for describing the +language and for writing programs in the language. + +Chapters @ref{Expressions} and @ref{Program structure} describe +the syntax and semantics of expressions, programs, and definitions. + +Chapter @ref{Standard procedures} describes Scheme's built-in +procedures, which include all of the language's data manipulation and +input/output primitives. + +Chapter @ref{Formal syntax and semantics} provides a formal syntax for Scheme +written in extended BNF, along with a formal denotational semantics. +An example of the use of the language follows the formal syntax and +semantics. + +The report concludes with a list of references and an +alphabetic index. + +@ignore todo +expand the summary so that it fills up the column. +@end ignore + + +@c \vfill +@c \begin{center} +@c {\large \bf +@c *** DRAFT*** \\ +@c %August 31, 1989 +@c \today +@c }\end{center} + + + + + +@c \addvspace{3.5pt} % don't shrink this gap +@c \renewcommand{\tocshrink}{-3.5pt} % value determined experimentally + + + + + + +@page + +@end titlepage + +@c INFO first page +@ifnottex + +@c First page + +@c \thispagestyle{empty} + +@c \todo{"another" report?} + + +@node top, Introduction, (dir), (dir) +@top Revised(5) Report on the Algorithmic Language Scheme + +@sp 1 + + +@quotation +R@sc{ichard} K@sc{elsey}, W@sc{illiam} C@sc{linger, and} J@sc{onathan} R@sc{ees} (@i{Editors}) +@sp 1 +@multitable @columnfractions 0.25 0.25 0.25 0.25 +@item H. A@sc{belson} @tab R. K. D@sc{ybvig} @tab C. T. H@sc{aynes} @tab G. J. R@sc{ozas} +@item N. I. A@sc{dams IV} @tab D. P. F@sc{riedman} @tab E. K@sc{ohlbecker} @tab G. L. S@sc{teele} J@sc{r}. +@item D. H. B@sc{artley} @tab R. H@sc{alstead} @tab D. O@sc{xley} @tab G. J. S@sc{ussman} +@item G. B@sc{rooks} @tab C. H@sc{anson} @tab K. M. P@sc{itman} @tab M. W@sc{and} +@item +@end multitable +@end quotation + + +@sp 2 + +@c {\it Dedicated to the Memory of ALGOL 60} +@i{Dedicated to the Memory of Robert Hieb} +@c [For the macros in R5RS -RK] + +@sp 3 + + + + +@majorheading Summary + + +The report gives a defining description of the programming language +Scheme. Scheme is a statically scoped and properly tail-recursive +dialect of the Lisp programming language invented by Guy Lewis +Steele Jr.@: and Gerald Jay Sussman. It was designed to have an +exceptionally clear and simple semantics and few different ways to +form expressions. A wide variety of programming paradigms, including +imperative, functional, and message passing styles, find convenient +expression in Scheme. + +The introduction offers a brief history of the language and of +the report. + +The first three chapters present the fundamental ideas of the +language and describe the notational conventions used for describing the +language and for writing programs in the language. + +Chapters @ref{Expressions} and @ref{Program structure} describe +the syntax and semantics of expressions, programs, and definitions. + +Chapter @ref{Standard procedures} describes Scheme's built-in +procedures, which include all of the language's data manipulation and +input/output primitives. + +Chapter @ref{Formal syntax and semantics} provides a formal syntax for Scheme +written in extended BNF, along with a formal denotational semantics. +An example of the use of the language follows the formal syntax and +semantics. + +The report concludes with a list of references and an +alphabetic index. + +@ignore todo +expand the summary so that it fills up the column. +@end ignore + + +@c \vfill +@c \begin{center} +@c {\large \bf +@c *** DRAFT*** \\ +@c %August 31, 1989 +@c \today +@c }\end{center} + + + + + +@c \addvspace{3.5pt} % don't shrink this gap +@c \renewcommand{\tocshrink}{-3.5pt} % value determined experimentally + +@unnumbered Contents + +@menu +* Introduction:: +* Overview of Scheme:: +* Lexical conventions:: +* Basic concepts:: +* Expressions:: +* Program structure:: +* Standard procedures:: +* Formal syntax and semantics:: +* Notes:: +* Additional material:: +* Example:: +* Bibliography:: +* Index:: +@end menu + + + + + +@page + +@end ifnottex + + +@c @include{intro} +@node Introduction, Overview of Scheme, top, top +@unnumbered Introduction + +@menu +* Background:: +* Acknowledgements:: +@end menu + + + + +Programming languages should be designed not by piling feature on top of +feature, but by removing the weaknesses and restrictions that make additional +features appear necessary. Scheme demonstrates that a very small number +of rules for forming expressions, with no restrictions on how they are +composed, suffice to form a practical and efficient programming language +that is flexible enough to support most of the major programming +paradigms in use today. + +@c Scheme has influenced the evolution of Lisp. +Scheme +was one of the first programming languages to incorporate first class +procedures as in the lambda calculus, thereby proving the usefulness of +static scope rules and block structure in a dynamically typed language. +Scheme was the first major dialect of Lisp to distinguish procedures +from lambda expressions and symbols, to use a single lexical +environment for all variables, and to evaluate the operator position +of a procedure call in the same way as an operand position. By relying +entirely on procedure calls to express iteration, Scheme emphasized the +fact that tail-recursive procedure calls are essentially goto's that +pass arguments. Scheme was the first widely used programming language to +embrace first class escape procedures, from which all previously known +sequential control structures can be synthesized. A subsequent +version of Scheme introduced the concept of exact and inexact numbers, +an extension of Common Lisp's generic arithmetic. +More recently, Scheme became the first programming language to support +hygienic macros, which permit the syntax of a block-structured language +to be extended in a consistent and reliable manner. +@c A few +@c of these innovations have recently been incorporated into Common Lisp, while +@c others remain to be adopted. + +@ignore todo +Ramsdell: +I would like to make a few comments on presentation. The most +important comment is about section organization. Newspaper writers +spend most of their time writing the first three paragraphs of any +article. This part of the article is often the only part read by +readers, and is important in enticing readers to continue. In the +same way, The first page is most likely to be the only page read by +many SIGPLAN readers. If I had my choice of what I would ask them to +read, it would be the material in section 1.1, the Semantics section +that notes that scheme is lexically scoped, tail recursive, weakly +typed, ... etc. I would expand on the discussion on continuations, +as they represent one important difference between Scheme and other +languages. The introduction, with its history of scheme, its history +of scheme reports and meetings, and acknowledgements giving names of +people that the reader will not likely know, is not that one page I +would like all to read. I suggest moving the history to the back of +the report, and use the first couple of pages to convince the reader +that the language documented in this report is worth studying. + +@end ignore + + +@node Background, Acknowledgements, Introduction, Introduction +@unnumberedsec Background + + +The first description of Scheme was written in +1975 [Scheme75]. A revised report [Scheme78] +@ignore todo +italicize or not? +@end ignore + appeared in 1978, which described the evolution +of the language as its MIT implementation was upgraded to support an +innovative compiler [Rabbit]. Three distinct projects began in +1981 and 1982 to use variants of Scheme for courses at MIT, Yale, and +Indiana University [Rees82], [MITScheme], [Scheme311]. An introductory +computer science textbook using Scheme was published in +1984 [SICP]. + +@c \vest As might be expected of a language used primarily for education and +@c research, Scheme has always evolved rapidly. This was no problem when +@c Scheme was used only within MIT, but +As Scheme became more widespread, +local dialects began to diverge until students and researchers +occasionally found it difficult to understand code written at other +sites. +Fifteen representatives of the major implementations of Scheme therefore +met in October 1984 to work toward a better and more widely accepted +standard for Scheme. +@c Participating in this workshop were Hal Abelson, Norman Adams, David +@c Bartley, Gary Brooks, William Clinger, Daniel Friedman, Robert Halstead, +@c Chris Hanson, Christopher Haynes, Eugene Kohlbecker, Don Oxley, Jonathan Rees, +@c Guillermo Rozas, Gerald Jay Sussman, and Mitchell Wand. Kent Pitman +@c made valuable contributions to the agenda for the workshop but was +@c unable to attend the sessions. + +@c Subsequent electronic mail discussions and committee work completed the +@c definition of the language. +@c Gerry Sussman drafted the section on numbers, Chris Hanson drafted the +@c sections on characters and strings, and Gary Brooks and William Clinger +@c drafted the sections on input and output. +@c William Clinger recorded the decisions of the workshop and +@c compiled the pieces into a coherent document. +@c The ``Revised revised report on Scheme''~\cite{RRRS} +Their report [RRRS] +was published at MIT and Indiana University in the summer of 1985. +Further revision took place in the spring of 1986 [R3RS], +@c , again accomplished +@c almost entirely by electronic mail, resulted in the present report. +and in the spring of 1988 [R4RS]. +The present report reflects further revisions agreed upon in a meeting +at Xerox PARC in June 1992. + +@c \vest The number 3 in the title is part of the title, not a reference to +@c a footnote. The word ``revised'' is raised to the third power because +@c the report is a revision of a report that was already twice revised. + +@ignore todo +Write an editors' note? +@end ignore + + + +@sp 3 + +We intend this report to belong to the entire Scheme community, and so +we grant permission to copy it in whole or in part without fee. In +particular, we encourage implementors of Scheme to use this report as +a starting point for manuals and other documentation, modifying it as +necessary. + + + + +@node Acknowledgements, , Background, Introduction +@unnumberedsec Acknowledgements + + +We would like to thank the following people for their help: Alan Bawden, Michael +Blair, George Carrette, Andy Cromarty, Pavel Curtis, Jeff Dalton, Olivier Danvy, +Ken Dickey, Bruce Duba, Marc Feeley, +Andy Freeman, Richard Gabriel, Yekta G"ursel, Ken Haase, Robert +Hieb, Paul Hudak, Morry Katz, Chris Lindblad, Mark Meyer, Jim Miller, Jim Philbin, +John Ramsdell, Mike Shaff, Jonathan Shapiro, Julie Sussman, +Perry Wagle, Daniel Weise, Henry Wu, and Ozan Yigit. +We thank Carol Fessenden, Daniel +Friedman, and Christopher Haynes for permission to use text from the Scheme 311 +version 4 reference manual. We thank Texas Instruments, Inc. for permission to +use text from the @emph{TI Scheme Language Reference Manual}[TImanual85]. +We gladly acknowledge the influence of manuals for MIT Scheme[MITScheme], +T[Rees84], Scheme 84[Scheme84],Common Lisp[CLtL], +and Algol 60[Naur63]. + +We also thank Betty Dexter for the extreme effort she put into +setting this report in @TeX{}, and Donald Knuth for designing the program +that caused her troubles. + +The Artificial Intelligence Laboratory of the +Massachusetts Institute of Technology, the Computer Science +Department of Indiana University, the Computer and Information +Sciences Department of the University of Oregon, and the NEC Research +Institute supported the preparation of this report. Support for the MIT +work was provided in part by +the Advanced Research Projects Agency of the Department of Defense under Office +of Naval Research contract N00014-80-C-0505. Support for the Indiana +University work was provided by NSF grants NCS 83-04567 and NCS +83-03325. + + + + +@sp 2 + +@c \clearchapterstar{Description of the language} %\unskip\vskip -2ex +@c @include{struct} + +@c 1. Structure of the language + +@node Overview of Scheme, Lexical conventions, Introduction, top +@chapter Overview of Scheme + +@menu +* Semantics:: +* Syntax:: +* Notation and terminology:: +@end menu + + +@node Semantics, Syntax, Overview of Scheme, Overview of Scheme +@section Semantics + + + +This section gives an overview of Scheme's semantics. A +detailed informal semantics is the subject of +chapters @ref{Basic concepts} through @ref{Standard procedures}. For reference +purposes, section @ref{Formal semantics} provides a formal +semantics of Scheme. + +Following Algol, Scheme is a statically scoped programming +language. Each use of a variable is associated with a lexically +apparent binding of that variable. + +Scheme has latent as opposed to manifest types. Types +are associated with values (also called objects) rather than +@cindex @w{object} +with variables. (Some authors refer to languages with latent types as +weakly typed or dynamically typed languages.) Other languages with +latent types are APL, Snobol, and other dialects of Lisp. Languages +with manifest types (sometimes referred to as strongly typed or +statically typed languages) include Algol 60, Pascal, and C. + +All objects created in the course of a Scheme computation, including +procedures and continuations, have unlimited extent. +No Scheme object is ever destroyed. The reason that +implementations of Scheme do not (usually!) run out of storage is that +they are permitted to reclaim the storage occupied by an object if +they can prove that the object cannot possibly matter to any future +computation. Other languages in which most objects have unlimited +extent include APL and other Lisp dialects. + +Implementations of Scheme are required to be properly tail-recursive. +This allows the execution of an iterative computation in constant space, +even if the iterative computation is described by a syntactically +recursive procedure. Thus with a properly tail-recursive implementation, +iteration can be expressed using the ordinary procedure-call +mechanics, so that special iteration constructs are useful only as +syntactic sugar. See section @ref{Proper tail recursion}. + +Scheme procedures are objects in their own right. Procedures can be +created dynamically, stored in data structures, returned as results of +procedures, and so on. Other languages with these properties include +Common Lisp and ML. +@ignore todo +Rozas: Scheme had them first. +@end ignore + + +One distinguishing feature of Scheme is that continuations, which +in most other languages only operate behind the scenes, also have +``first-class'' status. Continuations are useful for implementing a +wide variety of advanced control constructs, including non-local exits, +backtracking, and coroutines. See section @ref{Control features}. + +Arguments to Scheme procedures are always passed by value, which +means that the actual argument expressions are evaluated before the +procedure gains control, whether the procedure needs the result of the +evaluation or not. ML, C, and APL are three other languages that always +pass arguments by value. +This is distinct from the lazy-evaluation semantics of Haskell, +or the call-by-name semantics of Algol 60, where an argument +expression is not evaluated unless its value is needed by the +procedure. + +@ignore todo +Lisp's call by value should be explained more +accurately. What's funny is that all values are references. +@end ignore + + +Scheme's model of arithmetic is designed to remain as independent as +possible of the particular ways in which numbers are represented within a +computer. In Scheme, every integer is a rational number, every rational is a +real, and every real is a complex number. Thus the distinction between integer +and real arithmetic, so important to many programming languages, does not +appear in Scheme. In its place is a distinction between exact arithmetic, +which corresponds to the mathematical ideal, and inexact arithmetic on +approximations. As in Common Lisp, exact arithmetic is not limited to +integers. + +@node Syntax, Notation and terminology, Semantics, Overview of Scheme +@section Syntax + + +Scheme, like most dialects of Lisp, employs a fully parenthesized prefix +notation for programs and (other) data; the grammar of Scheme generates a +sublanguage of the language used for data. An important +consequence of this simple, uniform representation is the susceptibility of +Scheme programs and data to uniform treatment by other Scheme programs. +For example, the @samp{eval} procedure evaluates a Scheme program expressed +as data. + +The @samp{read} procedure performs syntactic as well as lexical decomposition of +the data it reads. The @samp{read} procedure parses its input as data +(section @pxref{External representation}), not as program. + +The formal syntax of Scheme is described in section @ref{Formal syntax}. + + +@node Notation and terminology, , Syntax, Overview of Scheme +@section Notation and terminology + +@menu +* Primitive; library; and optional features:: +* Error situations and unspecified behavior:: +* Entry format:: +* Evaluation examples:: +* Naming conventions:: +@end menu + + + +@node Primitive; library; and optional features, Error situations and unspecified behavior, Notation and terminology, Notation and terminology +@subsection Primitive; library; and optional features + + + +It is required that every implementation of Scheme support all +features that are not marked as being @dfn{optional}. Implementations are +@cindex @w{optional} +free to omit optional features of Scheme or to add extensions, +provided the extensions are not in conflict with the language reported +here. In particular, implementations must support portable code by +providing a syntactic mode that preempts no lexical conventions of this +report. + +To aid in understanding and implementing Scheme, some features are marked +as @dfn{library}. These can be easily implemented in terms of the other, +@cindex @w{library} +primitive, features. They are redundant in the strict sense of +the word, but they capture common patterns of usage, and are therefore +provided as convenient abbreviations. + +@node Error situations and unspecified behavior, Entry format, Primitive; library; and optional features, Notation and terminology +@subsection Error situations and unspecified behavior + + + +@cindex @w{error} +When speaking of an error situation, this report uses the phrase ``an +error is signalled'' to indicate that implementations must detect and +report the error. If such wording does not appear in the discussion of +an error, then implementations are not required to detect or report the +error, though they are encouraged to do so. An error situation that +implementations are not required to detect is usually referred to simply +as ``an error.'' + +For example, it is an error for a procedure to be passed an argument that +the procedure is not explicitly specified to handle, even though such +domain errors are seldom mentioned in this report. Implementations may +extend a procedure's domain of definition to include such arguments. + +This report uses the phrase ``may report a violation of an +implementation restriction'' to indicate circumstances under which an +implementation is permitted to report that it is unable to continue +execution of a correct program because of some restriction imposed by the +implementation. Implementation restrictions are of course discouraged, +but implementations are encouraged to report violations of implementation +restrictions. +@cindex @w{implementation restriction} + +For example, an implementation may report a violation of an +implementation restriction if it does not have enough storage to run a +program. + +If the value of an expression is said to be ``unspecified,'' then +the expression must evaluate to some object without signalling an error, +but the value depends on the implementation; this report explicitly does +not say what value should be returned. +@cindex @w{unspecified} + +@ignore todo +Talk about unspecified behavior vs. unspecified values. +@end ignore + + +@ignore todo +Look at KMP's situations paper. +@end ignore + + + +@node Entry format, Evaluation examples, Error situations and unspecified behavior, Notation and terminology +@subsection Entry format + + +Chapters @ref{Expressions} and @ref{Standard procedures} are organized +into entries. Each entry describes one language feature or a group of +related features, where a feature is either a syntactic construct or a +built-in procedure. An entry begins with one or more header lines of the form + + +@noindent +@deffn {@var{category}} @var{template} + +@end deffn + +for required, primitive features, or + + +@noindent +@deffn {@var{qualifier} @var{category}} @var{template} + +@end deffn + +where @var{qualifier} is either ``library'' or ``optional'' as defined + in section @ref{Primitive; library; and optional features}. + +If @var{category} is ``syntax'', the entry describes an expression +type, and the template gives the syntax of the expression type. +Components of expressions are designated by syntactic variables, which +are written using angle brackets, for example, @r{<expression>}, +@r{<variable>}. Syntactic variables should be understood to denote segments of +program text; for example, @r{<expression>} stands for any string of +characters which is a syntactically valid expression. The notation + +@format + @r{<thing1>} @dots{} +@end format + +indicates zero or more occurrences of a @r{<thing>}, and + +@format + @r{<thing1>} @r{<thing2>} @dots{} +@end format + +indicates one or more occurrences of a @r{<thing>}. + +If @var{category} is ``procedure'', then the entry describes a procedure, and +the header line gives a template for a call to the procedure. Argument +names in the template are @var{italicized}. Thus the header line + + +@noindent +@deffn {procedure} vector-ref @var{vector} @var{k} + +@end deffn + +indicates that the built-in procedure @t{vector-ref} takes +two arguments, a vector @var{vector} and an exact non-negative integer +@var{k} (see below). The header lines + + +@noindent + +@deffn {procedure} make-vector @var{k} + + +@deffnx {procedure} make-vector @var{k} @var{fill} + +@end deffn + +indicate that the @t{make-vector} procedure must be defined to take +either one or two arguments. + + +It is an error for an operation to be presented with an argument that it +is not specified to handle. For succinctness, we follow the convention +that if an argument name is also the name of a type listed in +section @ref{Disjointness of types}, then that argument must be of the named type. +For example, the header line for @t{vector-ref} given above dictates that the +first argument to @t{vector-ref} must be a vector. The following naming +conventions also imply type restrictions: +@c \newcommand{\foo}[1]{\vr{#1}, \vri{#1}, $\ldots$ \vrj{#1}, $\ldots$} + + +@center @c begin-tabular +@quotation +@table @asis +@item @var{obj} +any object +@item @var{list}, @var{list1}, @dots{} @var{listj}, @dots{} +list (see section @pxref{Pairs and lists}) +@item @var{z}, @var{z1}, @dots{} @var{zj}, @dots{} +complex number +@item @var{x}, @var{x1}, @dots{} @var{xj}, @dots{} +real number +@item @var{y}, @var{y1}, @dots{} @var{yj}, @dots{} +real number +@item @var{q}, @var{q1}, @dots{} @var{qj}, @dots{} +rational number +@item @var{n}, @var{n1}, @dots{} @var{nj}, @dots{} +integer +@item @var{k}, @var{k1}, @dots{} @var{kj}, @dots{} +exact non-negative integer +@item +@end table +@end quotation + + + + +@ignore todo +Provide an example entry?? +@end ignore + + + +@node Evaluation examples, Naming conventions, Entry format, Notation and terminology +@subsection Evaluation examples + + +The symbol ``@result{}'' used in program examples should be read +``evaluates to.'' For example, + + +@example + +(* 5 8) ==> 40 + +@end example + + +means that the expression @t{(* 5 8)} evaluates to the object @t{40}. +Or, more precisely: the expression given by the sequence of characters +``@t{(* 5 8)}'' evaluates, in the initial environment, to an object +that may be represented externally by the sequence of characters ``@t{40}''. See section @ref{External representations} for a discussion of external +representations of objects. + +@node Naming conventions, , Evaluation examples, Notation and terminology +@subsection Naming conventions + + +By convention, the names of procedures that always return a boolean +value usually end +in ``@code{?}''. Such procedures are called predicates. +@vindex @w{?} + +By convention, the names of procedures that store values into previously +allocated locations (see section @pxref{Storage model}) usually end in +``@code{!}''. +@vindex @w{!} +Such procedures are called mutation procedures. +By convention, the value returned by a mutation procedure is unspecified. + +By convention, ``@code{->}'' appears within the names of procedures that +@vindex @w{->} +take an object of one type and return an analogous object of another type. +For example, @samp{list->vector} takes a list and returns a vector whose +elements are the same as those of the list. + + + +@ignore todo +Terms that need defining: thunk, command (what else?). +@end ignore + + +@c @include{lex} + +@c Lexical structure + +@c %\vfill\eject +@node Lexical conventions, Basic concepts, Overview of Scheme, top +@chapter Lexical conventions + +@menu +* Identifiers:: +* Whitespace and comments:: +* Other notations:: +@end menu + + +This section gives an informal account of some of the lexical +conventions used in writing Scheme programs. For a formal syntax of +Scheme, see section @ref{Formal syntax}. + +Upper and lower case forms of a letter are never distinguished +except within character and string constants. For example, @samp{Foo} is +the same identifier as @samp{FOO}, and @t{#x1AB} is the same number as +@t{#X1ab}. + +@node Identifiers, Whitespace and comments, Lexical conventions, Lexical conventions +@section Identifiers + + + +Most identifiers allowed by other programming +@cindex @w{identifier} +languages are also acceptable to Scheme. The precise rules for forming +identifiers vary among implementations of Scheme, but in all +implementations a sequence of letters, digits, and ``extended alphabetic +characters'' that begins with a character that cannot begin a number is +an identifier. In addition, @code{+}, @code{-}, and @code{...} are identifiers. +@vindex @w{...} +@vindex @w{-} +@vindex @w{+} +Here are some examples of identifiers: + + +@example + +lambda q +list->vector soup ++ V17a +<=? a34kTMNs +the-word-recursion-has-many-meanings + +@end example + + +Extended alphabetic characters may be used within identifiers as if +they were letters. The following are extended alphabetic characters: + + +@example + +! $ % & * + - . / : < = > ? @@ ^ _ ~ +@end example + + +See section @ref{Lexical structure} for a formal syntax of identifiers. + +Identifiers have two uses within Scheme programs: + + +@itemize @bullet + +@item +Any identifier may be used as a variable +or as a syntactic keyword +(see sections @pxref{Variables; syntactic keywords; and regions} and @pxref{Macros}). + +@item +When an identifier appears as a literal or within a literal +(see section @pxref{Literal expressions}), it is being used to denote a @emph{symbol} +(see section @pxref{Symbols}). + + +@end itemize + +@cindex @w{syntactic keyword} +@cindex @w{variable} + +@c \label{keywordsection} +@c The following identifiers are syntactic keywords, and should not be used +@c as variables: + +@c \begin{scheme} +@c => do or +@c and else quasiquote +@c begin if quote +@c case lambda set! +@c cond let unquote +@c define let* unquote-splicing +@c delay letrec% +@c \end{scheme} + +@c Some implementations allow all identifiers, including syntactic +@c keywords, to be used as variables. This is a compatible extension to +@c the language, but ambiguities in the language result when the +@c restriction is relaxed, and the ways in which these ambiguities are +@c resolved vary between implementations. + + +@node Whitespace and comments, Other notations, Identifiers, Lexical conventions +@section Whitespace and comments + + +@dfn{Whitespace} characters are spaces and newlines. +@cindex @w{Whitespace} +(Implementations typically provide additional whitespace characters such +as tab or page break.) Whitespace is used for improved readability and +as necessary to separate tokens from each other, a token being an +indivisible lexical unit such as an identifier or number, but is +otherwise insignificant. Whitespace may occur between any two tokens, +but not within a token. Whitespace may also occur inside a string, +where it is significant. + +A semicolon (@t{;}) indicates the start of a +comment. The comment continues to the +@cindex @w{;} +@cindex @w{comment} +end of the line on which the semicolon appears. Comments are invisible +to Scheme, but the end of the line is visible as whitespace. This +prevents a comment from appearing in the middle of an identifier or +number. + + +@example + +;;; The FACT procedure computes the factorial +;;; of a non-negative integer. +(define fact + (lambda (n) + (if (= n 0) + 1 ;Base case: return 1 + (* n (fact (- n 1)))))) + +@end example + + + +@node Other notations, , Whitespace and comments, Lexical conventions +@section Other notations + + +@ignore todo +Rewrite? +@end ignore + + +For a description of the notations used for numbers, see +section @ref{Numbers}. + + +@table @t + + +@item @t{.@: + -} +These are used in numbers, and may also occur anywhere in an identifier +except as the first character. A delimited plus or minus sign by itself +is also an identifier. +A delimited period (not occurring within a number or identifier) is used +in the notation for pairs (section @pxref{Pairs and lists}), and to indicate a +rest-parameter in a formal parameter list (section @pxref{Procedures}). +A delimited sequence of three successive periods is also an identifier. + +@item @t{( )} +Parentheses are used for grouping and to notate lists +(section @pxref{Pairs and lists}). + +@item @t{'} +The single quote character is used to indicate literal data (section @pxref{Literal expressions}). + +@item @t{`} +The backquote character is used to indicate almost-constant +data (section @pxref{Quasiquotation}). + +@item @t{, ,@@} +The character comma and the sequence comma at-sign are used in conjunction +with backquote (section @pxref{Quasiquotation}). + +@item @t{"} +The double quote character is used to delimit strings (section @pxref{Strings}). + +@item \ +Backslash is used in the syntax for character constants +(section @pxref{Characters}) and as an escape character within string +constants (section @pxref{Strings}). + +@c A box used because \verb is not allowed in command arguments. + +@item @w{@t{[ ] @{ @} |}} +Left and right square brackets and curly braces and vertical bar +are reserved for possible future extensions to the language. + +@item # + Sharp sign is used for a variety of purposes depending on +the character that immediately follows it: + +@item @t{#t} @t{#f} +These are the boolean constants (section @pxref{Booleans}). + +@item #\ +This introduces a character constant (section @pxref{Characters}). + +@item #@t{(} +This introduces a vector constant (section @pxref{Vectors}). Vector constants +are terminated by @t{)} . + +@item @t{#e #i #b #o #d #x} +These are used in the notation for numbers (section @pxref{Syntax of numerical constants}). + +@end table + + +@c @include{basic} + +@c \vfill\eject +@node Basic concepts, Expressions, Lexical conventions, top +@chapter Basic concepts + +@menu +* Variables; syntactic keywords; and regions:: +* Disjointness of types:: +* External representations:: +* Storage model:: +* Proper tail recursion:: +@end menu + + + +@node Variables; syntactic keywords; and regions, Disjointness of types, Basic concepts, Basic concepts +@section Variables; syntactic keywords; and regions + + + + +An identifier may name a type of syntax, or it may name +@cindex @w{identifier} +a location where a value can be stored. An identifier that names a type +of syntax is called a @emph{syntactic keyword} +@cindex @w{syntactic keyword} +and is said to be @emph{bound} to that syntax. An identifier that names a +location is called a @emph{variable} and is said to be +@cindex @w{variable} +@emph{bound} to that location. The set of all visible +bindings in effect at some point in a program is +@cindex @w{binding} +known as the @emph{environment} in effect at that point. The value +stored in the location to which a variable is bound is called the +variable's value. By abuse of terminology, the variable is sometimes +said to name the value or to be bound to the value. This is not quite +accurate, but confusion rarely results from this practice. + +@ignore todo +Define ``assigned'' and ``unassigned'' perhaps? +@end ignore + + +@ignore todo +In programs without side effects, one can safely pretend that the +variables are bound directly to the arguments. Or: +In programs without @code{set!}, one can safely pretend that the +@vindex @w{set!} +variable is bound directly to the value. +@end ignore + + +Certain expression types are used to create new kinds of syntax +and bind syntactic keywords to those new syntaxes, while other +expression types create new locations and bind variables to those +locations. These expression types are called @emph{binding constructs}. + +@cindex @w{binding construct} +Those that bind syntactic keywords are listed in section @ref{Macros}. +The most fundamental of the variable binding constructs is the +@samp{lambda} expression, because all other variable binding constructs +can be explained in terms of @samp{lambda} expressions. The other +variable binding constructs are @samp{let}, @samp{let*}, @samp{letrec}, +and @samp{do} expressions (see sections @pxref{Procedures}, @pxref{Binding constructs}, and +@pxref{Iteration}). + +@c Note: internal definitions not mentioned here. + +Like Algol and Pascal, and unlike most other dialects of Lisp +except for Common Lisp, Scheme is a statically scoped language with +block structure. To each place where an identifier is bound in a program +there corresponds a @dfn{region} of the program text within which +@cindex @w{region} +the binding is visible. The region is determined by the particular +binding construct that establishes the binding; if the binding is +established by a @samp{lambda} expression, for example, then its region +is the entire @samp{lambda} expression. Every mention of an identifier +refers to the binding of the identifier that established the +innermost of the regions containing the use. If there is no binding of +the identifier whose region contains the use, then the use refers to the +binding for the variable in the top level environment, if any +(chapters @pxref{Expressions} and @pxref{Standard procedures}); if there is no +binding for the identifier, +it is said to be @dfn{unbound}. +@cindex @w{top level environment} +@cindex @w{bound} +@cindex @w{unbound} + +@ignore todo +Mention that some implementations have multiple top level environments? +@end ignore + + +@ignore todo +Pitman sez: needs elaboration in case of @t{(let ...)} +@end ignore + + +@ignore todo +Pitman asks: say something about vars created after scheme starts? +@t{(define x 3) (define (f) x) (define (g) y) (define y 4)} +Clinger replies: The language was explicitly +designed to permit a view in which no variables are created after +Scheme starts. In files, you can scan out the definitions beforehand. +I think we're agreed on the principle that interactive use should +approximate that behavior as closely as possible, though we don't yet +agree on which programming environment provides the best approximation. +@end ignore + + +@node Disjointness of types, External representations, Variables; syntactic keywords; and regions, Basic concepts +@section Disjointness of types + + + +No object satisfies more than one of the following predicates: + + +@example + +boolean? pair? +symbol? number? +char? string? +vector? port? +procedure? + +@end example + + +These predicates define the types @emph{boolean}, @emph{pair}, @emph{symbol}, @emph{number}, @emph{char} (or @emph{character}), @emph{string}, @emph{vector}, @emph{port}, and @emph{procedure}. The empty list is a special +object of its own type; it satisfies none of the above predicates. + +@vindex symbol? +@vindex pair? +@vindex boolean? +@cindex @w{type} + +@vindex vector? +@vindex string? +@vindex char? +@vindex number? + +@cindex @w{empty list} +@vindex procedure? +@vindex port? + +Although there is a separate boolean type, +any Scheme value can be used as a boolean value for the purpose of a +conditional test. As explained in section @ref{Booleans}, all +values count as true in such a test except for @t{#f}. +@c and possibly the empty list. +@c The only value that is guaranteed to count as +@c false is \schfalse{}. It is explicitly unspecified whether the empty list +@c counts as true or as false. +This report uses the word ``true'' to refer to any +Scheme value except @t{#f}, and the word ``false'' to refer to +@t{#f}. +@cindex @w{false} +@cindex @w{true} + +@node External representations, Storage model, Disjointness of types, Basic concepts +@section External representations + + + +An important concept in Scheme (and Lisp) is that of the @emph{external +representation} of an object as a sequence of characters. For example, +an external representation of the integer 28 is the sequence of +characters ``@t{28}'', and an external representation of a list consisting +of the integers 8 and 13 is the sequence of characters ``@t{(8 13)}''. + +The external representation of an object is not necessarily unique. The +integer 28 also has representations ``@t{#e28.000}'' and ``@t{#x1c}'', and the +list in the previous paragraph also has the representations ``@t{( 08 13 +)}'' and ``@t{(8 .@: (13 .@: ()))}'' (see section @pxref{Pairs and lists}). + +Many objects have standard external representations, but some, such as +procedures, do not have standard representations (although particular +implementations may define representations for them). + +An external representation may be written in a program to obtain the +corresponding object (see @samp{quote}, section @pxref{Literal expressions}). + +External representations can also be used for input and output. The +procedure @samp{read} (section @pxref{Input}) parses external +representations, and the procedure @samp{write} (section @pxref{Output}) +generates them. Together, they provide an elegant and powerful +input/output facility. + +Note that the sequence of characters ``@t{(+ 2 6)}'' is @emph{not} an +external representation of the integer 8, even though it @emph{is} an +expression evaluating to the integer 8; rather, it is an external +representation of a three-element list, the elements of which are the symbol +@t{+} and the integers 2 and 6. Scheme's syntax has the property that +any sequence of characters that is an expression is also the external +representation of some object. This can lead to confusion, since it may +not be obvious out of context whether a given sequence of characters is +intended to denote data or program, but it is also a source of power, +since it facilitates writing programs such as interpreters and +compilers that treat programs as data (or vice versa). + +The syntax of external representations of various kinds of objects +accompanies the description of the primitives for manipulating the +objects in the appropriate sections of chapter @ref{Standard procedures}. + +@node Storage model, Proper tail recursion, External representations, Basic concepts +@section Storage model + + + +Variables and objects such as pairs, vectors, and strings implicitly +denote locations or sequences of locations. A string, for +@cindex @w{location} +example, denotes as many locations as there are characters in the string. +(These locations need not correspond to a full machine word.) A new value may be +stored into one of these locations using the @t{string-set!} procedure, but +the string continues to denote the same locations as before. + +An object fetched from a location, by a variable reference or by +a procedure such as @samp{car}, @samp{vector-ref}, or @samp{string-ref}, is +equivalent in the sense of @code{eqv?} +@c and \ide{eq?} ?? +(section @pxref{Equivalence predicates}) +@vindex @w{eqv?} +to the object last stored in the location before the fetch. + +Every location is marked to show whether it is in use. +No variable or object ever refers to a location that is not in use. +Whenever this report speaks of storage being allocated for a variable +or object, what is meant is that an appropriate number of locations are +chosen from the set of locations that are not in use, and the chosen +locations are marked to indicate that they are now in use before the variable +or object is made to denote them. + +In many systems it is desirable for constants (i.e. the values of +@cindex @w{constant} +literal expressions) to reside in read-only-memory. To express this, it is +convenient to imagine that every object that denotes locations is associated +with a flag telling whether that object is mutable or +@cindex @w{mutable} +immutable. In such systems literal constants and the strings +@cindex @w{immutable} +returned by @code{symbol->string} are immutable objects, while all objects +@vindex @w{symbol->string} +created by the other procedures listed in this report are mutable. It is an +error to attempt to store a new value into a location that is denoted by an +immutable object. + +@node Proper tail recursion, , Storage model, Basic concepts +@section Proper tail recursion + + + +Implementations of Scheme are required to be +@emph{properly tail-recursive}. +@cindex @w{proper tail recursion} +Procedure calls that occur in certain syntactic +contexts defined below are `tail calls'. A Scheme implementation is +properly tail-recursive if it supports an unbounded number of active +tail calls. A call is @emph{active} if the called procedure may still +return. Note that this includes calls that may be returned from either +by the current continuation or by continuations captured earlier by +@samp{call-with-current-continuation} that are later invoked. +In the absence of captured continuations, calls could +return at most once and the active calls would be those that had not +yet returned. +A formal definition of proper tail recursion can be found +in [propertailrecursion]. + + +@quotation +@emph{Rationale:} + +Intuitively, no space is needed for an active tail call because the +continuation that is used in the tail call has the same semantics as the +continuation passed to the procedure containing the call. Although an improper +implementation might use a new continuation in the call, a return +to this new continuation would be followed immediately by a return +to the continuation passed to the procedure. A properly tail-recursive +implementation returns to that continuation directly. + +Proper tail recursion was one of the central ideas in Steele and +Sussman's original version of Scheme. Their first Scheme interpreter +implemented both functions and actors. Control flow was expressed using +actors, which differed from functions in that they passed their results +on to another actor instead of returning to a caller. In the terminology +of this section, each actor finished with a tail call to another actor. + +Steele and Sussman later observed that in their interpreter the code +for dealing with actors was identical to that for functions and thus +there was no need to include both in the language. + +@end quotation + + +A @emph{tail call} is a procedure call that occurs +@cindex @w{tail call} +in a @emph{tail context}. Tail contexts are defined inductively. Note +that a tail context is always determined with respect to a particular lambda +expression. + + + +@itemize @bullet + +@item +The last expression within the body of a lambda expression, +shown as @r{<tail expression>} below, occurs in a tail context. + +@format +@t{(lambda <formals> + <definition>* <expression>* <tail expression>) +} + +@end format + + + +@item +If one of the following expressions is in a tail context, +then the subexpressions shown as <tail expression> are in a tail context. +These were derived from rules in the grammar given in +chapter @ref{Formal syntax and semantics} by replacing some occurrences of <expression> +with <tail expression>. Only those rules that contain tail contexts +are shown here. + + +@format +@t{(if <expression> <tail expression> <tail expression>) +(if <expression> <tail expression>) + +(cond <cond clause>+) +(cond <cond clause>* (else <tail sequence>)) + +(case <expression> + <case clause>+) +(case <expression> + <case clause>* + (else <tail sequence>)) + +(and <expression>* <tail expression>) +(or <expression>* <tail expression>) + +(let (<binding spec>*) <tail body>) +(let <variable> (<binding spec>*) <tail body>) +(let* (<binding spec>*) <tail body>) +(letrec (<binding spec>*) <tail body>) + +(let-syntax (<syntax spec>*) <tail body>) +(letrec-syntax (<syntax spec>*) <tail body>) + +(begin <tail sequence>) + +(do (<iteration spec>*) + (<test> <tail sequence>) + <expression>*) + +@r{where} + +<cond clause> --> (<test> <tail sequence>) +<case clause> --> ((<datum>*) <tail sequence>) + +<tail body> --> <definition>* <tail sequence> +<tail sequence> --> <expression>* <tail expression> +} + +@end format + + + +@item +If a @samp{cond} expression is in a tail context, and has a clause of +the form @samp{(@r{<expression1>} => @r{<expression2>})} +then the (implied) call to +the procedure that results from the evaluation of @r{<expression2>} is in a +tail context. @r{<expression2>} itself is not in a tail context. + + +@end itemize + + +Certain built-in procedures are also required to perform tail calls. +The first argument passed to @code{apply} and to +@vindex @w{apply} +@code{call-with-current-continuation}, and the second argument passed to +@vindex @w{call-with-current-continuation} +@code{call-with-values}, must be called via a tail call. +@vindex @w{call-with-values} +Similarly, @code{eval} must evaluate its argument as if it +@vindex @w{eval} +were in tail position within the @code{eval} procedure. +@vindex @w{eval} + +In the following example the only tail call is the call to @samp{f}. +None of the calls to @samp{g} or @samp{h} are tail calls. The reference to +@samp{x} is in a tail context, but it is not a call and thus is not a +tail call. + +@example + +(lambda () + (if (g) + (let ((x (h))) + x) + (and (g) (f)))) + +@end example + + + +@quotation +@emph{Note:} +Implementations are allowed, but not required, to +recognize that some non-tail calls, such as the call to @samp{h} +above, can be evaluated as though they were tail calls. +In the example above, the @samp{let} expression could be compiled +as a tail call to @samp{h}. (The possibility of @samp{h} returning +an unexpected number of values can be ignored, because in that +case the effect of the @samp{let} is explicitly unspecified and +implementation-dependent.) +@end quotation + + + +@c @include{expr} + +@c \vfill\eject +@node Expressions, Program structure, Basic concepts, top +@chapter Expressions + +@menu +* Primitive expression types:: +* Derived expression types:: +* Macros:: +@end menu + + + +@c \newcommand{\syntax}{{\em Syntax: }} +@c \newcommand{\semantics}{{\em Semantics: }} + +@c [Deleted for R5RS because of multiple-value returns. -RK] +@c A Scheme expression is a construct that returns a value, such as a +@c variable reference, literal, procedure call, or conditional. + +Expression types are categorized as @emph{primitive} or @emph{derived}. +Primitive expression types include variables and procedure calls. +Derived expression types are not semantically primitive, but can instead +be defined as macros. +With the exception of @samp{quasiquote}, whose macro definition is complex, +the derived expressions are classified as library features. +Suitable definitions are given in section @ref{Derived expression type}. + +@node Primitive expression types, Derived expression types, Expressions, Expressions +@section Primitive expression types + +@menu +* Variable references:: +* Literal expressions:: +* Procedure calls:: +* Procedures:: +* Conditionals:: +* Assignments:: +@end menu + + + +@node Variable references, Literal expressions, Primitive expression types, Primitive expression types +@subsection Variable references + + + +@deffn {syntax} @r{<variable>} + + +An expression consisting of a variable +@cindex @w{variable} +(section @pxref{Variables; syntactic keywords; and regions}) is a variable reference. The value of +the variable reference is the value stored in the location to which the +variable is bound. It is an error to reference an +unbound variable. +@cindex @w{unbound} + + +@format +@t{(define x 28) +x ==> 28 +} +@end format + +@end deffn + +@node Literal expressions, Procedure calls, Variable references, Primitive expression types +@subsection Literal expressions + + + + +@deffn {syntax} quote @r{<datum>} + +@deffnx {syntax} @t{'}@r{<datum>} + + +@deffnx {syntax} @r{<constant>} + + +@samp{(quote @r{<datum>})} evaluates to @r{<datum>}. +@cindex @w{'} +@r{<Datum>} +may be any external representation of a Scheme object (see +section @pxref{External representations}). This notation is used to include literal +constants in Scheme code. + + +@format +@t{ +(quote a) ==> a +(quote #(a b c)) ==> #(a b c) +(quote (+ 1 2)) ==> (+ 1 2) +} +@end format + + +@samp{(quote @r{<datum>})} may be abbreviated as +@t{'}@r{<datum>}. The two notations are equivalent in all +respects. + + +@format +@t{'a ==> a +'#(a b c) ==> #(a b c) +'() ==> () +'(+ 1 2) ==> (+ 1 2) +'(quote a) ==> (quote a) +''a ==> (quote a) +} +@end format + + +Numerical constants, string constants, character constants, and boolean +constants evaluate ``to themselves''; they need not be quoted. + + +@format +@t{'"abc" ==> "abc" +"abc" ==> "abc" +'145932 ==> 145932 +145932 ==> 145932 +'#t ==> #t +#t ==> #t +} +@end format + + +As noted in section @ref{Storage model}, it is an error to alter a constant +(i.e. the value of a literal expression) using a mutation procedure like +@samp{set-car!} or @samp{string-set!}. + +@end deffn + + +@node Procedure calls, Procedures, Literal expressions, Primitive expression types +@subsection Procedure calls + + + +@deffn {syntax} @r{<operator>} @r{<operand1>} @dots{}, + + +A procedure call is written by simply enclosing in parentheses +expressions for the procedure to be called and the arguments to be +passed to it. The operator and operand expressions are evaluated (in an +unspecified order) and the resulting procedure is passed the resulting +arguments. +@cindex @w{procedure call} +@cindex @w{call} + +@format +@t{ +(+ 3 4) ==> 7 +((if #f + *) 3 4) ==> 12 +} +@end format + + +A number of procedures are available as the values of variables in the +initial environment; for example, the addition and multiplication +procedures in the above examples are the values of the variables @samp{+} +and @samp{*}. New procedures are created by evaluating lambda expressions +(see section @pxref{Procedures}). +@ignore todo +At Friedman's request, flushed mention of other ways. +@end ignore + +@c or definitions (see section~\ref{define}). + +Procedure calls may return any number of values (see @code{values} in +@vindex @w{values} +section @pxref{Control features}). With the exception of @samp{values} +the procedures available in the initial environment return one +value or, for procedures such as @samp{apply}, pass on the values returned +by a call to one of their arguments. + +Procedure calls are also called @emph{combinations}. + +@cindex @w{combination} + + +@quotation +@emph{Note:} In contrast to other dialects of Lisp, the order of +evaluation is unspecified, and the operator expression and the operand +expressions are always evaluated with the same evaluation rules. +@end quotation + + + +@quotation +@emph{Note:} +Although the order of evaluation is otherwise unspecified, the effect of +any concurrent evaluation of the operator and operand expressions is +constrained to be consistent with some sequential order of evaluation. +The order of evaluation may be chosen differently for each procedure call. +@end quotation + + + +@quotation +@emph{Note:} In many dialects of Lisp, the empty combination, @t{()}, is a legitimate expression. In Scheme, combinations must have at +least one subexpression, so @t{()} is not a syntactically valid +expression. +@ignore todo +Dybvig: ``it should be obvious from the syntax.'' +@end ignore + +@end quotation + + +@ignore todo +Freeman: +I think an explanation as to why evaluation order is not specified +should be included. It should not include any reference to parallel +evaluation. Does any existing compiler generate better code because +the evaluation order is unspecified? Clinger: yes: T3, MacScheme v2, +probably MIT Scheme and Chez Scheme. But that's not the main reason +for leaving the order unspecified. +@end ignore + + +@end deffn + + +@node Procedures, Conditionals, Procedure calls, Primitive expression types +@subsection Procedures + + + + +@deffn {syntax} lambda @r{<formals>} @r{<body>} + +@emph{Syntax:} +@r{<Formals>} should be a formal arguments list as described below, +and @r{<body>} should be a sequence of one or more expressions. + +@emph{Semantics:} +A lambda expression evaluates to a procedure. The environment in +effect when the lambda expression was evaluated is remembered as part of the +procedure. When the procedure is later called with some actual +arguments, the environment in which the lambda expression was evaluated will +be extended by binding the variables in the formal argument list to +fresh locations, the corresponding actual argument values will be stored +in those locations, and the expressions in the body of the lambda expression +will be evaluated sequentially in the extended environment. +The result(s) of the last expression in the body will be returned as +the result(s) of the procedure call. + + +@format +@t{(lambda (x) (+ x x)) ==> @emph{}a procedure +((lambda (x) (+ x x)) 4) ==> 8 + +(define reverse-subtract + (lambda (x y) (- y x))) +(reverse-subtract 7 10) ==> 3 + +(define add4 + (let ((x 4)) + (lambda (y) (+ x y)))) +(add4 6) ==> 10 +} +@end format + + +@r{<Formals>} should have one of the following forms: + + + +@itemize @bullet + +@item +@t{(@r{<variable1>} @dots{},)}: +The procedure takes a fixed number of arguments; when the procedure is +called, the arguments will be stored in the bindings of the +corresponding variables. + +@item +@r{<variable>}: +The procedure takes any number of arguments; when the procedure is +called, the sequence of actual arguments is converted into a newly +allocated list, and the list is stored in the binding of the +@r{<variable>}. + +@item +@t{(@r{<variable1>} @dots{}, @r{<variable_n>} @b{.} +@r{<variable_n+1>})}: +If a space-delimited period precedes the last variable, then +the procedure takes n or more arguments, where n is the +number of formal arguments before the period (there must +be at least one). +The value stored in the binding of the last variable will be a +newly allocated +list of the actual arguments left over after all the other actual +arguments have been matched up against the other formal arguments. + +@end itemize + + +It is an error for a @r{<variable>} to appear more than once in +@r{<formals>}. + + +@format +@t{((lambda x x) 3 4 5 6) ==> (3 4 5 6) +((lambda (x y . z) z) + 3 4 5 6) ==> (5 6) +} +@end format + + +Each procedure created as the result of evaluating a lambda expression is +(conceptually) tagged +with a storage location, in order to make @code{eqv?} and +@vindex @w{eqv?} +@code{eq?} work on procedures (see section @pxref{Equivalence predicates}). +@vindex @w{eq?} + +@end deffn + + +@node Conditionals, Assignments, Procedures, Primitive expression types +@subsection Conditionals + + + +@deffn {syntax} if @r{<test>} @r{<consequent>} @r{<alternate>} +@deffnx {syntax} if @r{<test>} @r{<consequent>} +@c \/ if hyper = italic + +@emph{Syntax:} +@r{<Test>}, @r{<consequent>}, and @r{<alternate>} may be arbitrary +expressions. + +@emph{Semantics:} +An @samp{if} expression is evaluated as follows: first, +@r{<test>} is evaluated. If it yields a true value (see +@cindex @w{true} +section @pxref{Booleans}), then @r{<consequent>} is evaluated and +its value(s) is(are) returned. Otherwise @r{<alternate>} is evaluated and its +value(s) is(are) returned. If @r{<test>} yields a false value and no +@r{<alternate>} is specified, then the result of the expression is +unspecified. + + +@format +@t{(if (> 3 2) 'yes 'no) ==> yes +(if (> 2 3) 'yes 'no) ==> no +(if (> 3 2) + (- 3 2) + (+ 3 2)) ==> 1 +} +@end format + + +@end deffn + + +@node Assignments, , Conditionals, Primitive expression types +@subsection Assignments + + + + +@deffn {syntax} set! @r{<variable>} @r{<expression>} + +@r{<Expression>} is evaluated, and the resulting value is stored in +the location to which @r{<variable>} is bound. @r{<Variable>} must +be bound either in some region enclosing the @samp{set!} expression +@cindex @w{region} +or at top level. The result of the @samp{set!} expression is +unspecified. + + +@format +@t{(define x 2) +(+ x 1) ==> 3 +(set! x 4) ==> @emph{unspecified} +(+ x 1) ==> 5 +} +@end format + + +@end deffn + + +@node Derived expression types, Macros, Primitive expression types, Expressions +@section Derived expression types + +@menu +* Conditional:: +* Binding constructs:: +* Sequencing:: +* Iteration:: +* Delayed evaluation:: +* Quasiquotation:: +@end menu + + + +The constructs in this section are hygienic, as discussed in +section @ref{Macros}. +For reference purposes, section @ref{Derived expression type} gives macro definitions +that will convert most of the constructs described in this section +into the primitive constructs described in the previous section. + +@ignore todo +Mention that no definition of backquote is provided? +@end ignore + + +@node Conditional, Binding constructs, Derived expression types, Derived expression types +@subsection Conditionals + + + +@deffn {library syntax} cond <clause1> <clause2> @dots{}, + +@emph{Syntax:} +Each @r{<clause>} should be of the form + +@format +@t{(@r{<test>} @r{<expression1>} @dots{},) +} +@end format + +where @r{<test>} is any expression. Alternatively, a @r{<clause>} may be +of the form + +@format +@t{(@r{<test>} => @r{<expression>}) +} +@end format + +The last @r{<clause>} may be +an ``else clause,'' which has the form + +@format +@t{(else @r{<expression1>} @r{<expression2>} @dots{},)@r{.} +} +@end format + + +@cindex @w{else} + +@cindex @w{=>} + +@emph{Semantics:} +A @samp{cond} expression is evaluated by evaluating the @r{<test>} +expressions of successive @r{<clause>}s in order until one of them +evaluates to a true value (see +@cindex @w{true} +section @pxref{Booleans}). When a @r{<test>} evaluates to a true +value, then the remaining @r{<expression>}s in its @r{<clause>} are +evaluated in order, and the result(s) of the last @r{<expression>} in the +@r{<clause>} is(are) returned as the result(s) of the entire @samp{cond} +expression. If the selected @r{<clause>} contains only the +@r{<test>} and no @r{<expression>}s, then the value of the +@r{<test>} is returned as the result. If the selected @r{<clause>} uses the +@code{=>} alternate form, then the @r{<expression>} is evaluated. +@vindex @w{=>} +Its value must be a procedure that accepts one argument; this procedure is then +called on the value of the @r{<test>} and the value(s) returned by this +procedure is(are) returned by the @samp{cond} expression. +If all @r{<test>}s evaluate +to false values, and there is no else clause, then the result of +the conditional expression is unspecified; if there is an else +clause, then its @r{<expression>}s are evaluated, and the value(s) of +the last one is(are) returned. + + +@format +@t{(cond ((> 3 2) 'greater) + ((< 3 2) 'less)) ==> greater + +(cond ((> 3 3) 'greater) + ((< 3 3) 'less) + (else 'equal)) ==> equal + +(cond ((assv 'b '((a 1) (b 2))) => cadr) + (else #f)) ==> 2 +} +@end format + + + +@end deffn + + + +@deffn {library syntax} case @r{<key>} <clause1> <clause2> @dots{}, + +@emph{Syntax:} +@r{<Key>} may be any expression. Each @r{<clause>} should have +the form + +@format +@t{((@r{<datum1>} @dots{},) @r{<expression1>} @r{<expression2>} @dots{},)@r{,} +} +@end format + +where each @r{<datum>} is an external representation of some object. +All the @r{<datum>}s must be distinct. +The last @r{<clause>} may be an ``else clause,'' which has the form + +@format +@t{(else @r{<expression1>} @r{<expression2>} @dots{},)@r{.} +} +@end format + + +@vindex else + +@emph{Semantics:} +A @samp{case} expression is evaluated as follows. @r{<Key>} is +evaluated and its result is compared against each @r{<datum>}. If the +result of evaluating @r{<key>} is equivalent (in the sense of +@samp{eqv?}; see section @pxref{Equivalence predicates}) to a @r{<datum>}, then the +expressions in the corresponding @r{<clause>} are evaluated from left +to right and the result(s) of the last expression in the @r{<clause>} is(are) +returned as the result(s) of the @samp{case} expression. If the result of +evaluating @r{<key>} is different from every @r{<datum>}, then if +there is an else clause its expressions are evaluated and the +result(s) of the last is(are) the result(s) of the @samp{case} expression; +otherwise the result of the @samp{case} expression is unspecified. + + +@format +@t{(case (* 2 3) + ((2 3 5 7) 'prime) + ((1 4 6 8 9) 'composite)) ==> composite +(case (car '(c d)) + ((a) 'a) + ((b) 'b)) ==> @emph{unspecified} +(case (car '(c d)) + ((a e i o u) 'vowel) + ((w y) 'semivowel) + (else 'consonant)) ==> consonant +} +@end format + + +@end deffn + + + +@deffn {library syntax} and <test1> @dots{}, + +The @r{<test>} expressions are evaluated from left to right, and the +value of the first expression that evaluates to a false value (see +section @pxref{Booleans}) is returned. Any remaining expressions +are not evaluated. If all the expressions evaluate to true values, the +value of the last expression is returned. If there are no expressions +then @t{#t} is returned. + + +@format +@t{(and (= 2 2) (> 2 1)) ==> #t +(and (= 2 2) (< 2 1)) ==> #f +(and 1 2 'c '(f g)) ==> (f g) +(and) ==> #t +} +@end format + + +@end deffn + + + +@deffn {library syntax} or <test1> @dots{}, + +The @r{<test>} expressions are evaluated from left to right, and the value of the +first expression that evaluates to a true value (see +section @pxref{Booleans}) is returned. Any remaining expressions +are not evaluated. If all expressions evaluate to false values, the +value of the last expression is returned. If there are no +expressions then @t{#f} is returned. + + +@format +@t{(or (= 2 2) (> 2 1)) ==> #t +(or (= 2 2) (< 2 1)) ==> #t +(or #f #f #f) ==> #f +(or (memq 'b '(a b c)) + (/ 3 0)) ==> (b c) +} +@end format + + +@end deffn + + +@node Binding constructs, Sequencing, Conditional, Derived expression types +@subsection Binding constructs + + +The three binding constructs @samp{let}, @samp{let*}, and @samp{letrec} +give Scheme a block structure, like Algol 60. The syntax of the three +constructs is identical, but they differ in the regions they establish +@cindex @w{region} +for their variable bindings. In a @samp{let} expression, the initial +values are computed before any of the variables become bound; in a +@samp{let*} expression, the bindings and evaluations are performed +sequentially; while in a @samp{letrec} expression, all the bindings are in +effect while their initial values are being computed, thus allowing +mutually recursive definitions. + + +@deffn {library syntax} let @r{<bindings>} @r{<body>} + +@emph{Syntax:} +@r{<Bindings>} should have the form + +@format +@t{((@r{<variable1>} @r{<init1>}) @dots{},)@r{,} +} +@end format + +where each @r{<init>} is an expression, and @r{<body>} should be a +sequence of one or more expressions. It is +an error for a @r{<variable>} to appear more than once in the list of variables +being bound. + +@emph{Semantics:} +The @r{<init>}s are evaluated in the current environment (in some +unspecified order), the @r{<variable>}s are bound to fresh locations +holding the results, the @r{<body>} is evaluated in the extended +environment, and the value(s) of the last expression of @r{<body>} +is(are) returned. Each binding of a @r{<variable>} has @r{<body>} as its +region. +@cindex @w{region} + + +@format +@t{(let ((x 2) (y 3)) + (* x y)) ==> 6 + +(let ((x 2) (y 3)) + (let ((x 7) + (z (+ x y))) + (* z x))) ==> 35 +} +@end format + + +See also named @samp{let}, section @ref{Iteration}. + +@end deffn + + + +@deffn {library syntax} let* @r{<bindings>} @r{<body>} + + +@emph{Syntax:} +@r{<Bindings>} should have the form + +@format +@t{((@r{<variable1>} @r{<init1>}) @dots{},)@r{,} +} +@end format + +and @r{<body>} should be a sequence of +one or more expressions. + +@emph{Semantics:} +@samp{Let*} is similar to @samp{let}, but the bindings are performed +sequentially from left to right, and the region of a binding indicated +@cindex @w{region} +by @samp{(@r{<variable>} @r{<init>})} is that part of the @samp{let*} +expression to the right of the binding. Thus the second binding is done +in an environment in which the first binding is visible, and so on. + + +@format +@t{(let ((x 2) (y 3)) + (let* ((x 7) + (z (+ x y))) + (* z x))) ==> 70 +} +@end format + + +@end deffn + + + +@deffn {library syntax} letrec @r{<bindings>} @r{<body>} + +@emph{Syntax:} +@r{<Bindings>} should have the form + +@format +@t{((@r{<variable1>} @r{<init1>}) @dots{},)@r{,} +} +@end format + +and @r{<body>} should be a sequence of +one or more expressions. It is an error for a @r{<variable>} to appear more +than once in the list of variables being bound. + +@emph{Semantics:} +The @r{<variable>}s are bound to fresh locations holding undefined +values, the @r{<init>}s are evaluated in the resulting environment (in +some unspecified order), each @r{<variable>} is assigned to the result +of the corresponding @r{<init>}, the @r{<body>} is evaluated in the +resulting environment, and the value(s) of the last expression in +@r{<body>} is(are) returned. Each binding of a @r{<variable>} has the +entire @samp{letrec} expression as its region, making it possible to +@cindex @w{region} +define mutually recursive procedures. + + +@format +@t{(letrec ((even? + (lambda (n) + (if (zero? n) + #t + (odd? (- n 1))))) + (odd? + (lambda (n) + (if (zero? n) + #f + (even? (- n 1)))))) + (even? 88)) + ==> #t +} +@end format + + +One restriction on @samp{letrec} is very important: it must be possible +to evaluate each @r{<init>} without assigning or referring to the value of any +@r{<variable>}. If this restriction is violated, then it is an error. The +restriction is necessary because Scheme passes arguments by value rather than by +name. In the most common uses of @samp{letrec}, all the @r{<init>}s are +lambda expressions and the restriction is satisfied automatically. + +@c \todo{use or uses? --- Jinx.} + +@end deffn + + +@node Sequencing, Iteration, Binding constructs, Derived expression types +@subsection Sequencing + + + +@deffn {library syntax} begin <expression1> <expression2> @dots{}, + +The @r{<expression>}s are evaluated sequentially from left to right, +and the value(s) of the last @r{<expression>} is(are) returned. This +expression type is used to sequence side effects such as input and +output. + + +@format +@t{(define x 0) + +(begin (set! x 5) + (+ x 1)) ==> 6 + +(begin (display "4 plus 1 equals ") + (display (+ 4 1))) ==> @emph{unspecified} + @emph{and prints} 4 plus 1 equals 5 +} +@end format + + +@end deffn + + +@node Iteration, Delayed evaluation, Sequencing, Derived expression types +@subsection Iteration + +@c \unsection + + +@noindent + +@deffn {library syntax} do ((@r{<variable1>} @r{<init1>} @r{<step1>}) @dots{}) (@r{<test>} @r{<expression>} @dots{}) @r{<command>} @dots{} +@cindex @w{do} + +@samp{Do} is an iteration construct. It specifies a set of variables to +be bound, how they are to be initialized at the start, and how they are +to be updated on each iteration. When a termination condition is met, +the loop exits after evaluating the @r{<expression>}s. + +@samp{Do} expressions are evaluated as follows: +The @r{<init>} expressions are evaluated (in some unspecified order), +the @r{<variable>}s are bound to fresh locations, the results of the +@r{<init>} expressions are stored in the bindings of the +@r{<variable>}s, and then the iteration phase begins. + +Each iteration begins by evaluating @r{<test>}; if the result is +false (see section @pxref{Booleans}), then the @r{<command>} +expressions are evaluated in order for effect, the @r{<step>} +expressions are evaluated in some unspecified order, the +@r{<variable>}s are bound to fresh locations, the results of the +@r{<step>}s are stored in the bindings of the +@r{<variable>}s, and the next iteration begins. + +If @r{<test>} evaluates to a true value, then the +@r{<expression>}s are evaluated from left to right and the value(s) of +the last @r{<expression>} is(are) returned. If no @r{<expression>}s +are present, then the value of the @samp{do} expression is unspecified. + +The region of the binding of a @r{<variable>} +@cindex @w{region} +consists of the entire @samp{do} expression except for the @r{<init>}s. +It is an error for a @r{<variable>} to appear more than once in the +list of @samp{do} variables. + +A @r{<step>} may be omitted, in which case the effect is the +same as if @samp{(@r{<variable>} @r{<init>} @r{<variable>})} had +been written instead of @samp{(@r{<variable>} @r{<init>})}. + + +@format +@t{(do ((vec (make-vector 5)) + (i 0 (+ i 1))) + ((= i 5) vec) + (vector-set! vec i i)) ==> #(0 1 2 3 4) + +(let ((x '(1 3 5 7 9))) + (do ((x x (cdr x)) + (sum 0 (+ sum (car x)))) + ((null? x) sum))) ==> 25 +} +@end format + + +@c \end{entry} +@end deffn + + +@deffn {library syntax} let @r{<variable>} @r{<bindings>} @r{<body>} + + +``Named @samp{let}'' is a variant on the syntax of @code{let} which provides +@vindex @w{let} +a more general looping construct than @samp{do} and may also be used to express +recursions. +It has the same syntax and semantics as ordinary @samp{let} +except that @r{<variable>} is bound within @r{<body>} to a procedure +whose formal arguments are the bound variables and whose body is +@r{<body>}. Thus the execution of @r{<body>} may be repeated by +invoking the procedure named by @r{<variable>}. + +@c | <-- right margin + +@format +@t{(let loop ((numbers '(3 -2 1 6 -5)) + (nonneg '()) + (neg '())) + (cond ((null? numbers) (list nonneg neg)) + ((>= (car numbers) 0) + (loop (cdr numbers) + (cons (car numbers) nonneg) + neg)) + ((< (car numbers) 0) + (loop (cdr numbers) + nonneg + (cons (car numbers) neg))))) + ==> ((6 1 3) (-5 -2)) +} +@end format + + +@end deffn + + +@node Delayed evaluation, Quasiquotation, Iteration, Derived expression types +@subsection Delayed evaluation + + + +@deffn {library syntax} delay @r{<expression>} + +@ignore todo +Fix. +@end ignore + + +The @samp{delay} construct is used together with the procedure @code{force} to +@vindex @w{force} +implement @dfn{lazy evaluation} or @dfn{call by need}. +@cindex @w{call by need} +@cindex @w{lazy evaluation} +@t{(delay @r{<expression>})} returns an object called a +@dfn{promise} which at some point in the future may be asked (by +@cindex @w{promise} +the @samp{force} procedure) +@ignore todo +Bartley's white lie; OK? +@end ignore + to evaluate +@r{<expression>}, and deliver the resulting value. +The effect of @r{<expression>} returning multiple values +is unspecified. + +See the description of @samp{force} (section @pxref{Control features}) for a +more complete description of @samp{delay}. + +@end deffn + + +@node Quasiquotation, , Delayed evaluation, Derived expression types +@subsection Quasiquotation + + + + +@deffn {syntax} quasiquote @r{<qq template>} + +@deffnx {syntax} @t{`}@r{<qq template>} + + +``Backquote'' or ``quasiquote'' expressions are useful +@cindex @w{backquote} +for constructing a list or vector structure when most but not all of the +desired structure is known in advance. If no +commas appear within the @r{<qq template>}, the result of +@cindex @w{comma} +evaluating +@t{`}@r{<qq template>} is equivalent to the result of evaluating +@t{'}@r{<qq template>}. If a comma appears within the +@cindex @w{,} +@r{<qq template>}, however, the expression following the comma is +evaluated (``unquoted'') and its result is inserted into the structure +instead of the comma and the expression. If a comma appears followed +immediately by an at-sign (@@), then the following +@cindex @w{,@@} +expression must evaluate to a list; the opening and closing parentheses +of the list are then ``stripped away'' and the elements of the list are +inserted in place of the comma at-sign expression sequence. A comma +at-sign should only appear within a list or vector @r{<qq template>}. + +@c struck: "(in the sense of {\cf equal?})" after "equivalent" + + +@format +@t{`(list ,(+ 1 2) 4) ==> (list 3 4) +(let ((name 'a)) `(list ,name ',name)) + ==> (list a (quote a)) +`(a ,(+ 1 2) ,@@(map abs '(4 -5 6)) b) + ==> (a 3 4 5 6 b) +`((@samp{foo} ,(- 10 3)) ,@@(cdr '(c)) . ,(car '(cons))) + ==> ((foo 7) . cons) +`#(10 5 ,(sqrt 4) ,@@(map sqrt '(16 9)) 8) + ==> #(10 5 2 4 3 8) +} +@end format + + +Quasiquote forms may be nested. Substitutions are made only for +unquoted components appearing at the same nesting level +as the outermost backquote. The nesting level increases by one inside +each successive quasiquotation, and decreases by one inside each +unquotation. + + +@format +@t{`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) + ==> (a `(b ,(+ 1 2) ,(foo 4 d) e) f) +(let ((name1 'x) + (name2 'y)) + `(a `(b ,,name1 ,',name2 d) e)) + ==> (a `(b ,x ,'y d) e) +} +@end format + + +The two notations + @t{`}@r{<qq template>} and @t{(quasiquote @r{<qq template>})} + are identical in all respects. + @samp{,@r{<expression>}} is identical to @samp{(unquote @r{<expression>})}, + and + @samp{,@@@r{<expression>}} is identical to @samp{(unquote-splicing @r{<expression>})}. +The external syntax generated by @code{write} for two-element lists whose +@vindex @w{write} +car is one of these symbols may vary between implementations. + +@cindex @w{`} + + +@format +@t{(quasiquote (list (unquote (+ 1 2)) 4)) + ==> (list 3 4) +'(quasiquote (list (unquote (+ 1 2)) 4)) + ==> `(list ,(+ 1 2) 4) + @emph{}i.e., (quasiquote (list (unquote (+ 1 2)) 4)) +} +@end format + + +Unpredictable behavior can result if any of the symbols +@code{quasiquote}, @code{unquote}, or @code{unquote-splicing} appear in +@vindex @w{unquote-splicing} +@vindex @w{unquote} +@vindex @w{quasiquote} +positions within a @r{<qq template>} otherwise than as described above. + +@end deffn + +@node Macros, , Derived expression types, Expressions +@section Macros + +@menu +* Binding constructs for syntactic keywords:: +* Pattern language:: +@end menu + + + +Scheme programs can define and use new derived expression types, + called @emph{macros}. +@cindex @w{macro} +Program-defined expression types have the syntax + +@example + +(@r{<keyword>} @r{<datum>} ...) + +@end example + +where @r{<keyword>} is an identifier that uniquely determines the +expression type. This identifier is called the @emph{syntactic +keyword}, or simply @emph{keyword}, of the macro. The +@cindex @w{macro keyword} +@cindex @w{keyword} +@cindex @w{syntactic keyword} +number of the @r{<datum>}s, and their syntax, depends on the +expression type. + +Each instance of a macro is called a @emph{use} +@cindex @w{macro use} +of the macro. +The set of rules that specifies +how a use of a macro is transcribed into a more primitive expression +is called the @emph{transformer} +@cindex @w{macro transformer} +of the macro. + +The macro definition facility consists of two parts: + + + +@itemize @bullet + +@item +A set of expressions used to establish that certain identifiers +are macro keywords, associate them with macro transformers, and control +the scope within which a macro is defined, and + +@item +a pattern language for specifying macro transformers. + +@end itemize + + +The syntactic keyword of a macro may shadow variable bindings, and local +variable bindings may shadow keyword bindings. All macros +@cindex @w{keyword} +defined using the pattern language are ``hygienic'' and ``referentially +transparent'' and thus preserve Scheme's lexical scoping [Kohlbecker86], [ +hygienic], [Bawden88], [macrosthatwork], [syntacticabstraction]: + +@cindex @w{hygienic} + +@cindex @w{referentially transparent} + + + + +@itemize @bullet + + +@item +If a macro transformer inserts a binding for an identifier +(variable or keyword), the identifier will in effect be renamed +throughout its scope to avoid conflicts with other identifiers. +Note that a @code{define} at top level may or may not introduce a binding; +see section @ref{Definitions}. + +@item +If a macro transformer inserts a free reference to an +identifier, the reference refers to the binding that was visible +where the transformer was specified, regardless of any local +bindings that may surround the use of the macro. + + +@end itemize + +@vindex @w{define} + +@c The low-level facility permits non-hygienic macros to be written, +@c and may be used to implement the high-level pattern language. + +@c The fourth section describes some features that would make the +@c low-level macro facility easier to use directly. + +@node Binding constructs for syntactic keywords, Pattern language, Macros, Macros +@subsection Binding constructs for syntactic keywords + + + +@samp{Let-syntax} and @samp{letrec-syntax} are +analogous to @samp{let} and @samp{letrec}, but they bind +syntactic keywords to macro transformers instead of binding variables +to locations that contain values. Syntactic keywords may also be +bound at top level; see section @ref{Syntax definitions}. + + +@deffn {syntax} let-syntax @r{<bindings>} @r{<body>} + +@emph{Syntax:} +@r{<Bindings>} should have the form + +@format +@t{((@r{<keyword>} @r{<transformer spec>}) @dots{},) +} +@end format + +Each @r{<keyword>} is an identifier, +each @r{<transformer spec>} is an instance of @samp{syntax-rules}, and +@r{<body>} should be a sequence of one or more expressions. It is an error +for a @r{<keyword>} to appear more than once in the list of keywords +being bound. + +@emph{Semantics:} +The @r{<body>} is expanded in the syntactic environment +obtained by extending the syntactic environment of the +@samp{let-syntax} expression with macros whose keywords are +the @r{<keyword>}s, bound to the specified transformers. +Each binding of a @r{<keyword>} has @r{<body>} as its region. + + +@format +@t{(let-syntax ((when (syntax-rules () + ((when test stmt1 stmt2 ...) + (if test + (begin stmt1 + stmt2 ...)))))) + (let ((if #t)) + (when if (set! if 'now)) + if)) ==> now + +(let ((x 'outer)) + (let-syntax ((m (syntax-rules () ((m) x)))) + (let ((x 'inner)) + (m)))) ==> outer +} +@end format + + +@end deffn + + +@deffn {syntax} letrec-syntax @r{<bindings>} @r{<body>} + +@emph{Syntax:} +Same as for @samp{let-syntax}. + +@emph{Semantics:} + The @r{<body>} is expanded in the syntactic environment obtained by +extending the syntactic environment of the @samp{letrec-syntax} +expression with macros whose keywords are the +@r{<keyword>}s, bound to the specified transformers. +Each binding of a @r{<keyword>} has the @r{<bindings>} +as well as the @r{<body>} within its region, +so the transformers can +transcribe expressions into uses of the macros +introduced by the @samp{letrec-syntax} expression. + + +@format +@t{(letrec-syntax + ((my-or (syntax-rules () + ((my-or) #f) + ((my-or e) e) + ((my-or e1 e2 ...) + (let ((temp e1)) + (if temp + temp + (my-or e2 ...))))))) + (let ((x #f) + (y 7) + (temp 8) + (let odd?) + (if even?)) + (my-or x + (let temp) + (if y) + y))) ==> 7 +} +@end format + + +@end deffn + +@node Pattern language, , Binding constructs for syntactic keywords, Macros +@subsection Pattern language + + + +A @r{<transformer spec>} has the following form: + + +@deffn {} syntax-rules @r{<literals>} @r{<syntax rule>} @dots{}, + +@emph{Syntax:} +@r{<Literals>} is a list of identifiers and each @r{<syntax rule>} +should be of the form + +@format +@t{(@r{<pattern>} @r{<template>}) +} +@end format + +The @r{<pattern>} in a @r{<syntax rule>} is a list @r{<pattern>} +that begins with the keyword for the macro. + +A @r{<pattern>} is either an identifier, a constant, or one of the +following + +@format +@t{(@r{<pattern>} @dots{}) +(@r{<pattern>} @r{<pattern>} @dots{} . @r{<pattern>}) +(@r{<pattern>} @dots{} @r{<pattern>} @r{<ellipsis>}) +#(@r{<pattern>} @dots{}) +#(@r{<pattern>} @dots{} @r{<pattern>} @r{<ellipsis>}) +} +@end format + +and a template is either an identifier, a constant, or one of the following + +@format +@t{(@r{<element>} @dots{}) +(@r{<element>} @r{<element>} @dots{} . @r{<template>}) +#(@r{<element>} @dots{}) +} +@end format + +where an @r{<element>} is a @r{<template>} optionally +followed by an @r{<ellipsis>} and +an @r{<ellipsis>} is the identifier ``@samp{...}'' (which cannot be used as +an identifier in either a template or a pattern). +@vindex ... + +@emph{Semantics:} An instance of @samp{syntax-rules} produces a new macro +transformer by specifying a sequence of hygienic rewrite rules. A use +of a macro whose keyword is associated with a transformer specified by +@samp{syntax-rules} is matched against the patterns contained in the +@r{<syntax rule>}s, beginning with the leftmost @r{<syntax rule>}. +When a match is found, the macro use is transcribed hygienically +according to the template. + +An identifier that appears in the pattern of a @r{<syntax rule>} is +a @emph{pattern variable}, unless it is the keyword that begins the pattern, +is listed in @r{<literals>}, or is the identifier ``@samp{...}''. +Pattern variables match arbitrary input elements and +are used to refer to elements of the input in the template. It is an +error for the same pattern variable to appear more than once in a +@r{<pattern>}. + +The keyword at the beginning of the pattern in a +@r{<syntax rule>} is not involved in the matching and +is not considered a pattern variable or literal identifier. + + +@quotation +@emph{Rationale:} +The scope of the keyword is determined by the expression or syntax +definition that binds it to the associated macro transformer. +If the keyword were a pattern variable or literal +identifier, then +the template that follows the pattern would be within its scope +regardless of whether the keyword were bound by @samp{let-syntax} +or by @samp{letrec-syntax}. +@end quotation + + +Identifiers that appear in @r{<literals>} are interpreted as literal +identifiers to be matched against corresponding subforms of the input. +A subform +in the input matches a literal identifier if and only if it is an +identifier +and either both its occurrence in the macro expression and its +occurrence in the macro definition have the same lexical binding, or +the two identifiers are equal and both have no lexical binding. + +@c [Bill Rozas suggested the term "noise word" for these literal +@c identifiers, but in their most interesting uses, such as a setf +@c macro, they aren't noise words at all. -- Will] + +A subpattern followed by @samp{...} can match zero or more elements of the +input. It is an error for @samp{...} to appear in @r{<literals>}. +Within a pattern the identifier @samp{...} must follow the last element of +a nonempty sequence of subpatterns. + +More formally, an input form F matches a pattern P if and only if: + + + +@itemize @bullet + +@item +P is a non-literal identifier; or + +@item +P is a literal identifier and F is an identifier with the same +binding; or + +@item +P is a list @samp{(P_1 @dots{} P_n)} and F is a +list of n +forms that match P_1 through P_n, respectively; or + +@item +P is an improper list +@samp{(P_1 P_2 @dots{} P_n . P_n+1)} +and F is a list or +improper list of n or more forms that match P_1 through P_n, +respectively, and whose nth ``cdr'' matches P_n+1; or + +@item +P is of the form +@samp{(P_1 @dots{} P_n P_n+1 <ellipsis>)} +where <ellipsis> is the identifier @samp{...} +and F is +a proper list of at least n forms, the first n of which match +P_1 through P_n, respectively, and each remaining element of F +matches P_n+1; or + +@item +P is a vector of the form @samp{#(P_1 @dots{} P_n)} +and F is a vector +of n forms that match P_1 through P_n; or + +@item +P is of the form +@samp{#(P_1 @dots{} P_n P_n+1 <ellipsis>)} +where <ellipsis> is the identifier @samp{...} +and F is a vector of n +or more forms the first n of which match +P_1 through P_n, respectively, and each remaining element of F +matches P_n+1; or + +@item +P is a datum and F is equal to P in the sense of +the @samp{equal?} procedure. + +@end itemize + + +It is an error to use a macro keyword, within the scope of its +binding, in an expression that does not match any of the patterns. + +When a macro use is transcribed according to the template of the +matching @r{<syntax rule>}, pattern variables that occur in the +template are replaced by the subforms they match in the input. +Pattern variables that occur in subpatterns followed by one or more +instances of the identifier +@samp{...} are allowed only in subtemplates that are +followed by as many instances of @samp{...}. +They are replaced in the +output by all of the subforms they match in the input, distributed as +indicated. It is an error if the output cannot be built up as +specified. + +@c %% This description of output construction is very vague. It should +@c %% probably be formalized, but that is not easy... + +Identifiers that appear in the template but are not pattern variables +or the identifier +@samp{...} are inserted into the output as literal identifiers. If a +literal identifier is inserted as a free identifier then it refers to the +binding of that identifier within whose scope the instance of +@samp{syntax-rules} appears. +If a literal identifier is inserted as a bound identifier then it is +in effect renamed to prevent inadvertent captures of free identifiers. + +As an example, if @code{let} and @code{cond} are defined as in +@vindex @w{cond} +@vindex @w{let} +section @ref{Derived expression type} then they are hygienic (as required) and +the following is not an error. + + +@format +@t{(let ((=> #f)) + (cond (#t => 'ok))) ==> ok +} +@end format + + +The macro transformer for @samp{cond} recognizes @samp{=>} +as a local variable, and hence an expression, and not as the +top-level identifier @samp{=>}, which the macro transformer treats +as a syntactic keyword. Thus the example expands into + + +@format +@t{(let ((=> #f)) + (if #t (begin => 'ok))) +} +@end format + + +instead of + + +@format +@t{(let ((=> #f)) + (let ((temp #t)) + (if temp ('ok temp)))) +} +@end format + + +which would result in an invalid procedure call. + +@end deffn + + +@page + +@c @include{prog} +@node Program structure, Standard procedures, Expressions, top +@chapter Program structure + +@menu +* Programs:: +* Definitions:: +* Syntax definitions:: +@end menu + + + +@node Programs, Definitions, Program structure, Program structure +@section Programs + + +A Scheme program consists of a sequence of expressions, definitions, +and syntax definitions. +Expressions are described in chapter @ref{Expressions}; +definitions and syntax definitions are the subject of the rest of the +present chapter. + +Programs are typically stored in files or entered interactively to a +running Scheme system, although other paradigms are possible; +questions of user interface lie outside the scope of this report. +(Indeed, Scheme would still be useful as a notation for expressing +computational methods even in the absence of a mechanical +implementation.) + +Definitions and syntax definitions occurring at the top level of a program +can be interpreted +declaratively. +They cause bindings to be created in the top level +environment or modify the value of existing top-level bindings. +Expressions occurring at the top level of a program are +interpreted imperatively; they are executed in order when the program is +invoked or loaded, and typically perform some kind of initialization. + +At the top level of a program @t{(begin @r{<form1>} @dots{},)} is +equivalent to the sequence of expressions, definitions, and syntax definitions +that form the body of the @code{begin}. +@vindex @w{begin} + +@ignore todo +Cromarty, etc.: disclaimer about top level? +@end ignore + + +@node Definitions, Syntax definitions, Programs, Program structure +@section Definitions + +@menu +* Top level definitions:: +* Internal definitions:: +@end menu + + + +Definitions are valid in some, but not all, contexts where expressions +are allowed. They are valid only at the top level of a @r{<program>} +and at the beginning of a @r{<body>}. + +@cindex @w{definition} + +A definition should have one of the following forms: +@cindex @w{define} + + + +@itemize @bullet + + +@item @t{(define @r{<variable>} @r{<expression>})} + +@item @t{(define (@r{<variable>} @r{<formals>}) @r{<body>})} + +@r{<Formals>} should be either a +sequence of zero or more variables, or a sequence of one or more +variables followed by a space-delimited period and another variable (as +in a lambda expression). This form is equivalent to + +@example + +(define @r{<variable>} + (lambda (@r{<formals>}) @r{<body>}))@r{.} + +@end example + + +@item @t{(define (@r{<variable>} .@: @r{<formal>}) @r{<body>})} + +@r{<Formal>} should be a single +variable. This form is equivalent to + +@example + +(define @r{<variable>} + (lambda @r{<formal>} @r{<body>}))@r{.} + +@end example + + + +@end itemize + + +@node Top level definitions, Internal definitions, Definitions, Definitions +@subsection Top level definitions + + +At the top level of a program, a definition + +@example + +(define @r{<variable>} @r{<expression>}) + +@end example + +has essentially the same effect as the assignment expression + +@example + +(set! @r{<variable>} @r{<expression>}) + +@end example + +if @r{<variable>} is bound. If @r{<variable>} is not bound, +however, then the definition will bind @r{<variable>} to a new +location before performing the assignment, whereas it would be an error +to perform a @samp{set!} on an unbound variable. +@cindex @w{unbound} + + +@example + +(define add3 + (lambda (x) (+ x 3))) +(add3 3) ==> 6 +(define first car) +(first '(1 2)) ==> 1 + +@end example + + +Some implementations of Scheme use an initial environment in +which all possible variables are bound to locations, most of +which contain undefined values. Top level definitions in +such an implementation are truly equivalent to assignments. + +@ignore todo +Rozas: equal time for opposition semantics? +@end ignore + + + +@node Internal definitions, , Top level definitions, Definitions +@subsection Internal definitions + + + +Definitions may occur at the +beginning of a @r{<body>} (that is, the body of a @code{lambda}, +@vindex @w{lambda} +@code{let}, @code{let*}, @code{letrec}, @code{let-syntax}, or @code{letrec-syntax} +@vindex @w{letrec-syntax} +@vindex @w{let-syntax} +@vindex @w{letrec} +@vindex @w{let*} +@vindex @w{let} +expression or that of a definition of an appropriate form). +Such definitions are known as @emph{internal definitions} as opposed to the top level definitions described above. +@cindex @w{internal definition} +The variable defined by an internal definition is local to the +@r{<body>}. That is, @r{<variable>} is bound rather than assigned, +and the region of the binding is the entire @r{<body>}. For example, + + +@example + +(let ((x 5)) + (define foo (lambda (y) (bar x y))) + (define bar (lambda (a b) (+ (* a b) a))) + (foo (+ x 3))) ==> 45 + +@end example + + +A @r{<body>} containing internal definitions can always be converted +into a completely equivalent @samp{letrec} expression. For example, the +@samp{let} expression in the above example is equivalent to + + +@example + +(let ((x 5)) + (letrec ((foo (lambda (y) (bar x y))) + (bar (lambda (a b) (+ (* a b) a)))) + (foo (+ x 3)))) + +@end example + + +Just as for the equivalent @samp{letrec} expression, it must be +possible to evaluate each @r{<expression>} of every internal +definition in a @r{<body>} without assigning or referring to +the value of any @r{<variable>} being defined. + +Wherever an internal definition may occur +@t{(begin @r{<definition1>} @dots{},)} +is equivalent to the sequence of definitions +that form the body of the @code{begin}. +@vindex @w{begin} + +@node Syntax definitions, , Definitions, Program structure +@section Syntax definitions + + +Syntax definitions are valid only at the top level of a @r{<program>}. + +@cindex @w{syntax definition} +They have the following form: +@cindex @w{define-syntax} + +@t{(define-syntax @r{<keyword>} @r{<transformer spec>})} + +@r{<Keyword>} is an identifier, and +the @r{<transformer spec>} should be an instance of @code{syntax-rules}. +@vindex @w{syntax-rules} +The top-level syntactic environment is extended by binding the +@r{<keyword>} to the specified transformer. + +There is no @samp{define-syntax} analogue of internal definitions. + +@c [Rationale flushed because it may or may not be true and isn't the +@c real rationale anyway. -RK] +@c \begin{rationale} +@c As discussed below, the syntax and scope rules for syntax definitions +@c can give rise to syntactic ambiguities when syntactic keywords are +@c shadowed. +@c Further ambiguities would arise if {\cf define-syntax} +@c were permitted at the beginning of a \meta{body}, with scope +@c rules analogous to those for internal definitions. +@c \end{rationale} + +@c It is an error for a program to contain more than one top-level +@c \meta{definition} or \meta{syntax definition} of any identifier. + +@c [I flushed this because it isn't an error for a program to +@c contain more than one top-level definition of an identifier, +@c and I didn't want to introduce any gratuitous incompatibilities +@c with the existing Scheme language. -- Will] + +Although macros may expand into definitions and syntax definitions in +any context that permits them, it is an error for a definition or syntax +definition to shadow a syntactic keyword whose meaning is needed to +determine whether some form in the group of forms that contains the +shadowing definition is in fact a definition, or, for internal definitions, +is needed to determine the boundary between the group and the expressions +that follow the group. For example, the following are errors: + + +@example + +(define define 3) + +(begin (define begin list)) + +(let-syntax + ((foo (syntax-rules () + ((foo (proc args ...) body ...) + (define proc + (lambda (args ...) + body ...)))))) + (let ((x 3)) + (foo (plus x y) (+ x y)) + (define foo x) + (plus foo x))) + +@end example + + + + +@c @include{procs} + +@c Initial environment + +@c \vfill\eject +@node Standard procedures, Formal syntax and semantics, Program structure, top +@chapter Standard procedures + +@menu +* Equivalence predicates:: +* Numbers:: +* Other data types:: +* Control features:: +* Eval:: +* Input and output:: +@end menu + + + + + +@cindex @w{initial environment} + +@cindex @w{top level environment} + +@cindex @w{library procedure} + +This chapter describes Scheme's built-in procedures. The initial (or +``top level'') Scheme environment starts out with a number of variables +bound to locations containing useful values, most of which are primitive +procedures that manipulate data. For example, the variable @samp{abs} is +bound to (a location initially containing) a procedure of one argument +that computes the absolute value of a number, and the variable @samp{+} +is bound to a procedure that computes sums. Built-in procedures that +can easily be written in terms of other built-in procedures are identified as +``library procedures''. + +A program may use a top-level definition to bind any variable. It may +subsequently alter any such binding by an assignment (see @pxref{Assignments}). +These operations do not modify the behavior of Scheme's built-in +procedures. Altering any top-level binding that has not been introduced by a +definition has an unspecified effect on the behavior of the built-in procedures. + +@node Equivalence predicates, Numbers, Standard procedures, Standard procedures +@section Equivalence predicates + + + +A @dfn{predicate} is a procedure that always returns a boolean +@cindex @w{predicate} +value (@t{#t} or @t{#f}). An @dfn{equivalence predicate} is +@cindex @w{equivalence predicate} +the computational analogue of a mathematical equivalence relation (it is +symmetric, reflexive, and transitive). Of the equivalence predicates +described in this section, @samp{eq?} is the finest or most +discriminating, and @samp{equal?} is the coarsest. @samp{Eqv?} is +slightly less discriminating than @samp{eq?}. +@ignore todo +Pitman doesn't like +this paragraph. Lift the discussion from the Maclisp manual. Explain +why there's more than one predicate. +@end ignore + + + + +@deffn {procedure} eqv? obj1 obj2 + +The @samp{eqv?} procedure defines a useful equivalence relation on objects. +Briefly, it returns @t{#t} if @var{obj1} and @var{obj2} should +normally be regarded as the same object. This relation is left slightly +open to interpretation, but the following partial specification of +@samp{eqv?} holds for all implementations of Scheme. + +The @samp{eqv?} procedure returns @t{#t} if: + + + +@itemize @bullet + +@item +@var{obj1} and @var{obj2} are both @t{#t} or both @t{#f}. + +@item +@var{obj1} and @var{obj2} are both symbols and + + +@format +@t{(string=? (symbol->string obj1) + (symbol->string obj2)) + ==> #t +} +@end format + + + +@quotation +@emph{Note:} +This assumes that neither @var{obj1} nor @var{obj2} is an ``uninterned +symbol'' as alluded to in section @ref{Symbols}. This report does +not presume to specify the behavior of @samp{eqv?} on implementation-dependent +extensions. +@end quotation + + +@item +@var{obj1} and @var{obj2} are both numbers, are numerically +equal (see @samp{=}, section @pxref{Numbers}), and are either both +exact or both inexact. + +@item +@var{obj1} and @var{obj2} are both characters and are the same +character according to the @samp{char=?} procedure +(section @pxref{Characters}). + +@item +both @var{obj1} and @var{obj2} are the empty list. + +@item +@var{obj1} and @var{obj2} are pairs, vectors, or strings that denote the +same locations in the store (section @pxref{Storage model}). + +@item +@var{obj1} and @var{obj2} are procedures whose location tags are +equal (section @pxref{Procedures}). + +@end itemize + +@cindex @w{inexact} +@cindex @w{exact} + +The @samp{eqv?} procedure returns @t{#f} if: + + + +@itemize @bullet + +@item +@var{obj1} and @var{obj2} are of different types +(section @pxref{Disjointness of types}). + +@item +one of @var{obj1} and @var{obj2} is @t{#t} but the other is +@t{#f}. + +@item +@var{obj1} and @var{obj2} are symbols but + + +@format +@t{(string=? (symbol->string @var{obj1}) + (symbol->string @var{obj2})) + ==> #f +} +@end format + + +@item +one of @var{obj1} and @var{obj2} is an exact number but the other +is an inexact number. + +@item +@var{obj1} and @var{obj2} are numbers for which the @samp{=} +procedure returns @t{#f}. + +@item +@var{obj1} and @var{obj2} are characters for which the @samp{char=?} +procedure returns @t{#f}. + +@item +one of @var{obj1} and @var{obj2} is the empty list but the other +is not. + +@item +@var{obj1} and @var{obj2} are pairs, vectors, or strings that denote +distinct locations. + +@item +@var{obj1} and @var{obj2} are procedures that would behave differently +(return different value(s) or have different side effects) for some arguments. + + +@end itemize + + + +@format +@t{(eqv? 'a 'a) ==> #t +(eqv? 'a 'b) ==> #f +(eqv? 2 2) ==> #t +(eqv? '() '()) ==> #t +(eqv? 100000000 100000000) ==> #t +(eqv? (cons 1 2) (cons 1 2)) ==> #f +(eqv? (lambda () 1) + (lambda () 2)) ==> #f +(eqv? #f 'nil) ==> #f +(let ((p (lambda (x) x))) + (eqv? p p)) ==> #t +} +@end format + + +The following examples illustrate cases in which the above rules do +not fully specify the behavior of @samp{eqv?}. All that can be said +about such cases is that the value returned by @samp{eqv?} must be a +boolean. + + +@format +@t{(eqv? "" "") ==> @emph{unspecified} +(eqv? '#() '#()) ==> @emph{unspecified} +(eqv? (lambda (x) x) + (lambda (x) x)) ==> @emph{unspecified} +(eqv? (lambda (x) x) + (lambda (y) y)) ==> @emph{unspecified} +} +@end format + + +The next set of examples shows the use of @samp{eqv?} with procedures +that have local state. @samp{Gen-counter} must return a distinct +procedure every time, since each procedure has its own internal counter. +@samp{Gen-loser}, however, returns equivalent procedures each time, since +the local state does not affect the value or side effects of the +procedures. + + +@format +@t{(define gen-counter + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) n)))) +(let ((g (gen-counter))) + (eqv? g g)) ==> #t +(eqv? (gen-counter) (gen-counter)) + ==> #f +(define gen-loser + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) 27)))) +(let ((g (gen-loser))) + (eqv? g g)) ==> #t +(eqv? (gen-loser) (gen-loser)) + ==> @emph{unspecified} + +(letrec ((f (lambda () (if (eqv? f g) 'both 'f))) + (g (lambda () (if (eqv? f g) 'both 'g)))) + (eqv? f g)) + ==> @emph{unspecified} + +(letrec ((f (lambda () (if (eqv? f g) 'f 'both))) + (g (lambda () (if (eqv? f g) 'g 'both)))) + (eqv? f g)) + ==> #f +} +@end format + + +@c Objects of distinct types must never be regarded as the same object, +@c except that \schfalse{} and the empty list\index{empty list} are permitted to +@c be identical. + +@c \begin{scheme} +@c (eqv? '() \schfalse) \ev \unspecified% +@c \end{scheme} + +Since it is an error to modify constant objects (those returned by +literal expressions), implementations are permitted, though not +required, to share structure between constants where appropriate. Thus +the value of @samp{eqv?} on constants is sometimes +implementation-dependent. + + +@format +@t{(eqv? '(a) '(a)) ==> @emph{unspecified} +(eqv? "a" "a") ==> @emph{unspecified} +(eqv? '(b) (cdr '(a b))) ==> @emph{unspecified} +(let ((x '(a))) + (eqv? x x)) ==> #t +} +@end format + + + +@quotation +@emph{Rationale:} +The above definition of @samp{eqv?} allows implementations latitude in +their treatment of procedures and literals: implementations are free +either to detect or to fail to detect that two procedures or two literals +are equivalent to each other, and can decide whether or not to +merge representations of equivalent objects by using the same pointer or +bit pattern to represent both. +@end quotation + + +@end deffn + + + +@deffn {procedure} eq? obj1 obj2 + +@samp{Eq?} is similar to @samp{eqv?} except that in some cases it is +capable of discerning distinctions finer than those detectable by +@samp{eqv?}. + +@samp{Eq?} and @samp{eqv?} are guaranteed to have the same +behavior on symbols, booleans, the empty list, pairs, procedures, +and non-empty +strings and vectors. @samp{Eq?}'s behavior on numbers and characters is +implementation-dependent, but it will always return either true or +false, and will return true only when @samp{eqv?} would also return +true. @samp{Eq?} may also behave differently from @samp{eqv?} on empty +vectors and empty strings. + + +@format +@t{(eq? 'a 'a) ==> #t +(eq? '(a) '(a)) ==> @emph{unspecified} +(eq? (list 'a) (list 'a)) ==> #f +(eq? "a" "a") ==> @emph{unspecified} +(eq? "" "") ==> @emph{unspecified} +(eq? '() '()) ==> #t +(eq? 2 2) ==> @emph{unspecified} +(eq? #\A #\A) ==> @emph{unspecified} +(eq? car car) ==> #t +(let ((n (+ 2 3))) + (eq? n n)) ==> @emph{unspecified} +(let ((x '(a))) + (eq? x x)) ==> #t +(let ((x '#())) + (eq? x x)) ==> #t +(let ((p (lambda (x) x))) + (eq? p p)) ==> #t +} +@end format + + +@ignore todo +Needs to be explained better above. How can this be made to be +not confusing? A table maybe? +@end ignore + + + +@quotation +@emph{Rationale:} It will usually be possible to implement @samp{eq?} much +more efficiently than @samp{eqv?}, for example, as a simple pointer +comparison instead of as some more complicated operation. One reason is +that it may not be possible to compute @samp{eqv?} of two numbers in +constant time, whereas @samp{eq?} implemented as pointer comparison will +always finish in constant time. @samp{Eq?} may be used like @samp{eqv?} +in applications using procedures to implement objects with state since +it obeys the same constraints as @samp{eqv?}. +@end quotation + + +@end deffn + + + +@deffn {library procedure} equal? obj1 obj2 + +@samp{Equal?} recursively compares the contents of pairs, vectors, and +strings, applying @samp{eqv?} on other objects such as numbers and symbols. +A rule of thumb is that objects are generally @samp{equal?} if they print +the same. @samp{Equal?} may fail to terminate if its arguments are +circular data structures. + + +@format +@t{(equal? 'a 'a) ==> #t +(equal? '(a) '(a)) ==> #t +(equal? '(a (b) c) + '(a (b) c)) ==> #t +(equal? "abc" "abc") ==> #t +(equal? 2 2) ==> #t +(equal? (make-vector 5 'a) + (make-vector 5 'a)) ==> #t +(equal? (lambda (x) x) + (lambda (y) y)) ==> @emph{unspecified} +} +@end format + + +@end deffn + + +@node Numbers, Other data types, Equivalence predicates, Standard procedures +@section Numbers + +@menu +* Numerical types:: +* Exactness:: +* Implementation restrictions:: +* Syntax of numerical constants:: +* Numerical operations:: +* Numerical input and output:: +@end menu + + + +@cindex @w{number} + +@c %R4%% The excessive use of the code font in this section was +@c confusing, somewhat obnoxious, and inconsistent with the rest +@c of the report and with parts of the section itself. I added +@c a \tupe no-op, and changed most old uses of \type to \tupe, +@c to make it easier to change the fonts back if people object +@c to the change. + +@c \newcommand{\type}[1]{{\it#1}} +@c \newcommand{\tupe}[1]{{#1}} + +Numerical computation has traditionally been neglected by the Lisp +community. Until Common Lisp there was no carefully thought out +strategy for organizing numerical computation, and with the exception of +the MacLisp system [Pitman83] little effort was made to +execute numerical code efficiently. This report recognizes the excellent work +of the Common Lisp committee and accepts many of their recommendations. +In some ways this report simplifies and generalizes their proposals in a manner +consistent with the purposes of Scheme. + +It is important to distinguish between the mathematical numbers, the +Scheme numbers that attempt to model them, the machine representations +used to implement the Scheme numbers, and notations used to write numbers. +This report uses the types @i{number}, @i{complex}, @i{real}, +@i{rational}, and @i{integer} to refer to both mathematical numbers +and Scheme numbers. Machine representations such as fixed point and +floating point are referred to by names such as @i{fixnum} and +@i{flonum}. + +@c %R4%% I did some reorganizing here to move the discussion of mathematical +@c numbers before the discussion of the Scheme numbers, hoping that this +@c would help to motivate the discussion of representation independence. + +@node Numerical types, Exactness, Numbers, Numbers +@subsection Numerical types + + + +@cindex @w{numerical types} + +@c %R4%% A Scheme system provides data of type \type{number}, which is the most +@c general numerical type supported by that system. +@c \type{Number} is +@c likely to be a complicated union type implemented in terms of +@c \type{fixnum}s, \type{bignum}s, \type{flonum}s, and so forth, but this +@c should not be apparent to a naive user. What the user should see is +@c that the usual operations on numbers produce the mathematically +@c expected results, within the limits of the implementation. + +@c %R4%% I rewrote the following paragraph to make the various levels of +@c the tower into subsets of each other, instead of relating them by +@c injections. I think the injections tended to put people in the frame +@c of mind of thinking about coercions between non-overlapping numeric +@c types in mainstream programming languages. + +Mathematically, numbers may be arranged into a tower of subtypes +@c %R4%% with injections relating adjacent levels of the tower: +in which each level is a subset of the level above it: + +@format + @r{number} + @r{complex} + @r{real} + @r{rational} + @r{integer} +@end format + + +For example, 3 is an integer. Therefore 3 is also a rational, +a real, and a complex. The same is true of the Scheme numbers +that model 3. For Scheme numbers, these types are defined by the +predicates @code{number?}, @code{complex?}, @code{real?}, @code{rational?}, +@vindex @w{rational?} +@vindex @w{real?} +@vindex @w{complex?} +@vindex @w{number?} +and @code{integer?}. +@vindex @w{integer?} + +There is no simple relationship between a number's type and its +representation inside a computer. Although most implementations of +Scheme will offer at least two different representations of 3, these +different representations denote the same integer. + +@c %R4%% I moved "Implementations of Scheme are not required to implement +@c the whole tower..." to the subsection on implementation restrictions. + +Scheme's numerical operations treat numbers as abstract data, as +independent of their representation as possible. Although an implementation +of Scheme may use fixnum, flonum, and perhaps other representations for +numbers, this should not be apparent to a casual programmer writing +simple programs. + +It is necessary, however, to distinguish between numbers that are +represented exactly and those that may not be. For example, indexes +into data structures must be known exactly, as must some polynomial +coefficients in a symbolic algebra system. On the other hand, the +results of measurements are inherently inexact, and irrational numbers +may be approximated by rational and therefore inexact approximations. +In order to catch uses of inexact numbers where exact numbers are +required, Scheme explicitly distinguishes exact from inexact numbers. +This distinction is orthogonal to the dimension of type. + +@node Exactness, Implementation restrictions, Numerical types, Numbers +@subsection Exactness + + +@c %R4%% I tried to direct the following paragraph away from philosophizing +@c about the exactness of mathematical numbers, and toward philosophizing +@c about the exactness of Scheme numbers. + + +@cindex @w{exactness} +Scheme numbers are either @i{exact} or @i{inexact}. A number is +@r{exact} if it was written as an exact constant or was derived from +@r{exact} numbers using only @r{exact} operations. A number is +@r{inexact} if it was written as an inexact constant, +@c %R4%% models a quantity (e.g., a measurement) known only approximately, +if it was +derived using @r{inexact} ingredients, or if it was derived using +@r{inexact} operations. Thus @r{inexact}ness is a contagious +property of a number. +@c %R4%% The rest of this paragraph (from R3RS) has been dropped. + +If two implementations produce @r{exact} results for a +computation that did not involve @r{inexact} intermediate results, +the two ultimate results will be mathematically equivalent. This is +generally not true of computations involving @r{inexact} numbers +since approximate methods such as floating point arithmetic may be used, +but it is the duty of each implementation to make the result as close as +practical to the mathematically ideal result. + +Rational operations such as @samp{+} should always produce +@r{exact} results when given @r{exact} arguments. +@c %R4%%If an implementation is +@c unable to represent an \tupe{exact} result (for example, if it does not +@c support infinite precision integers and rationals) +If the operation is unable to produce an @r{exact} result, +then it may either report the violation of an implementation restriction +or it may silently coerce its +result to an @r{inexact} value. +@c %R4%%Such a coercion may cause an error later. +See section @ref{Implementation restrictions}. + +With the exception of @code{inexact->exact}, the operations described in +@vindex @w{inexact->exact} +this section must generally return inexact results when given any inexact +arguments. An operation may, however, return an @r{exact} result if it can +prove that the value of the result is unaffected by the inexactness of its +arguments. For example, multiplication of any number by an @r{exact} zero +may produce an @r{exact} zero result, even if the other argument is +@r{inexact}. + +@node Implementation restrictions, Syntax of numerical constants, Exactness, Numbers +@subsection Implementation restrictions + + + +@cindex @w{implementation restriction} + +Implementations of Scheme are not required to implement the whole +tower of subtypes given in section @ref{Numerical types}, +but they must implement a coherent subset consistent with both the +purposes of the implementation and the spirit of the Scheme language. +For example, an implementation in which all numbers are @r{real} +may still be quite useful. + +Implementations may also support only a limited range of numbers of +any type, subject to the requirements of this section. The supported +range for @r{exact} numbers of any type may be different from the +supported range for @r{inexact} numbers of that type. For example, +an implementation that uses flonums to represent all its +@r{inexact} @r{real} numbers may +support a practically unbounded range of @r{exact} @r{integer}s +and @r{rational}s +while limiting the range of @r{inexact} @r{real}s (and therefore +the range of @r{inexact} @r{integer}s and @r{rational}s) +to the dynamic range of the flonum format. +Furthermore +the gaps between the representable @r{inexact} @r{integer}s and +@r{rational}s are +likely to be very large in such an implementation as the limits of this +range are approached. + +An implementation of Scheme must support exact integers +throughout the range of numbers that may be used for indexes of +lists, vectors, and strings or that may result from computing the length of a +list, vector, or string. The @code{length}, @code{vector-length}, +@vindex @w{vector-length} +@vindex @w{length} +and @code{string-length} procedures must return an exact +@vindex @w{string-length} +integer, and it is an error to use anything but an exact integer as an +index. Furthermore any integer constant within the index range, if +expressed by an exact integer syntax, will indeed be read as an exact +integer, regardless of any implementation restrictions that may apply +outside this range. Finally, the procedures listed below will always +return an exact integer result provided all their arguments are exact integers +and the mathematically expected result is representable as an exact integer +within the implementation: + + +@example + ++ - * +quotient remainder modulo +max min abs +numerator denominator gcd +lcm floor ceiling +truncate round rationalize +expt + +@end example + + +Implementations are encouraged, but not required, to support +@r{exact} @r{integer}s and @r{exact} @r{rational}s of +practically unlimited size and precision, and to implement the +above procedures and the @samp{/} procedure in +such a way that they always return @r{exact} results when given @r{exact} +arguments. If one of these procedures is unable to deliver an @r{exact} +result when given @r{exact} arguments, then it may either report a +violation of an +implementation restriction or it may silently coerce its result to an +@r{inexact} number. Such a coercion may cause an error later. + +@c %R4%% I moved this stuff here. +@c It seems to me that the only thing that this requires is that +@c implementations that support inexact numbers have to have both +@c exact and inexact representations for the integers 0 through 15. +@c If that's what it's saying, I'd rather say it that way. +@c On the other hand, letting the limit be as small as 15 sounds a +@c tad silly, though I think I understand how that number was arrived at. +@c (Or is 35 the number?) + +@c Implementations are encouraged, but not required, to support \tupe{inexact} +@c numbers. For any implementation that supports \tupe{inexact} numbers, +@c there is a subset of the integers for which there are both \tupe{exact} and +@c \tupe{inexact} representations. This subset must include all non-negative +@c integers up to some limit specified by the implementation. This limit +@c must be 16 or greater. The +@c \ide{exact\coerce{}inexact} and \ide{inexact\coerce{}exact} +@c procedures implement the natural one-to-one correspondence between +@c the \tupe{inexact} and \tupe{exact} integers within this range. + +An implementation may use floating point and other approximate +representation strategies for @r{inexact} numbers. +@c %R4%% The following sentence seemed a bit condescending as well as +@c awkward. It didn't seem to be very enforceable, so I flushed it. + +@c This is not to +@c say that implementors need not use the best known algorithms for +@c \tupe{inexact} computations---only that approximate methods of high +@c quality are allowed. + +This report recommends, but does not require, that the IEEE 32-bit +and 64-bit floating point standards be followed by implementations that use +flonum representations, and that implementations using +other representations should match or exceed the precision achievable +using these floating point standards [IEEE]. + +In particular, implementations that use flonum representations +must follow these rules: A @r{flonum} result +must be represented with at least as much precision as is used to express any of +the inexact arguments to that operation. It is desirable (but not required) for +potentially inexact operations such as @samp{sqrt}, when applied to @r{exact} +arguments, to produce @r{exact} answers whenever possible (for example the +square root of an @r{exact} 4 ought to be an @r{exact} 2). +If, however, an +@r{exact} number is operated upon so as to produce an @r{inexact} result +(as by @samp{sqrt}), and if the result is represented as a @r{flonum}, then +the most precise @r{flonum} format available must be used; but if the result +is represented in some other way then the representation must have at least as +much precision as the most precise @r{flonum} format available. + +Although Scheme allows a variety of written +@c %R4%% representations of +notations for +numbers, any particular implementation may support only some of them. +@c %R4%% +For example, an implementation in which all numbers are @r{real} +need not support the rectangular and polar notations for complex +numbers. If an implementation encounters an @r{exact} numerical constant that +it cannot represent as an @r{exact} number, then it may either report a +violation of an implementation restriction or it may silently represent the +constant by an @r{inexact} number. + + +@node Syntax of numerical constants, Numerical operations, Implementation restrictions, Numbers +@subsection Syntax of numerical constants + + + +@c @@@@LOSE@@@@ + +@c %R4%% I removed the following paragraph in an attempt to tighten up +@c this subsection. Except for its first sentence, which I moved to +@c the subsection on implementation restrictions, I think its content +@c is implied by the rest of the section. + +@c Although Scheme allows a variety of written representations of numbers, +@c any particular implementation may support only some of them. +@c These syntaxes are intended to be purely notational; any kind of number +@c may be written in any form that the user deems convenient. Of course, +@c writing 1/7 as a limited-precision decimal fraction will not express the +@c number exactly, but this approximate form of expression may be just what +@c the user wants to see. + +The syntax of the written representations for numbers is described formally in +section @ref{Lexical structure}. Note that case is not significant in numerical +constants. + +@c %R4%% See section~\ref{numberformats} for many examples. + +A number may be written in binary, octal, decimal, or +hexadecimal by the use of a radix prefix. The radix prefixes are @samp{#b} (binary), @samp{#o} (octal), @samp{#d} (decimal), and @samp{#x} (hexadecimal). With +@vindex #x +@vindex #d +@vindex #o +@vindex #b +no radix prefix, a number is assumed to be expressed in decimal. + +A +@c %R4%% +@c simple +numerical constant may be specified to be either @r{exact} or +@r{inexact} by a prefix. The prefixes are @samp{#e} +@vindex #e +for @r{exact}, and @samp{#i} for @r{inexact}. An exactness +@vindex #i +prefix may appear before or after any radix prefix that is used. If +the written representation of a number has no exactness prefix, the +constant may be either @r{inexact} or @r{exact}. It is +@r{inexact} if it contains a decimal point, an +exponent, or a ``#'' character in the place of a digit, +otherwise it is @r{exact}. +@c %R4%% With our new syntax, the following sentence is redundant: + +@c The written representation of a +@c compound number, such as a ratio or a complex, is exact if and only if +@c all of its constituents are exact. + +In systems with @r{inexact} numbers +of varying precisions it may be useful to specify +the precision of a constant. For this purpose, numerical constants +may be written with an exponent marker that indicates the +desired precision of the @r{inexact} +representation. The letters @samp{s}, @samp{f}, +@samp{d}, and @samp{l} specify the use of @var{short}, @var{single}, +@var{double}, and @var{long} precision, respectively. (When fewer +than four internal +@c %R4%%\tupe{flonum} +@r{inexact} +representations exist, the four size +specifications are mapped onto those available. For example, an +implementation with two internal representations may map short and +single together and long and double together.) In addition, the +exponent marker @samp{e} specifies the default precision for the +implementation. The default precision has at least as much precision +as @var{double}, but +implementations may wish to allow this default to be set by the user. + + +@example + +3.14159265358979F0 + @r{Round to single ---} 3.141593 +0.6L0 + @r{Extend to long ---} .600000000000000 + +@end example + + + +@node Numerical operations, Numerical input and output, Syntax of numerical constants, Numbers +@subsection Numerical operations + + +The reader is referred to section @ref{Entry format} for a summary +of the naming conventions used to specify restrictions on the types of +arguments to numerical routines. +@c %R4%% The following sentence has already been said twice, and the +@c term "exactness-preserving" is no longer defined by the Report. + +@c Remember that +@c an exactness-preserving operation may coerce its result to inexact if the +@c implementation is unable to represent it exactly. +The examples used in this section assume that any numerical constant written +using an @r{exact} notation is indeed represented as an @r{exact} +number. Some examples also assume that certain numerical constants written +using an @r{inexact} notation can be represented without loss of +accuracy; the @r{inexact} constants were chosen so that this is +likely to be true in implementations that use flonums to represent +inexact numbers. + +@ignore todo +Scheme provides the usual set of operations for manipulating +numbers, etc. +@end ignore + + + +@deffn {procedure} number? obj +@deffnx {procedure} complex? obj +@deffnx {procedure} real? obj +@deffnx {procedure} rational? obj +@deffnx {procedure} integer? obj + +These numerical type predicates can be applied to any kind of +argument, including non-numbers. They return @t{#t} if the object is +of the named type, and otherwise they return @t{#f}. +In general, if a type predicate is true of a number then all higher +type predicates are also true of that number. Consequently, if a type +predicate is false of a number, then all lower type predicates are +also false of that number. +@c %R4%% The new section on implementation restrictions subsumes: +@c Not every system +@c supports all of these types; for example, it is entirely possible to have a +@c Scheme system that has only \tupe{integer}s. Nonetheless every implementation +@c of Scheme must have all of these predicates. + +If @var{z} is an inexact complex number, then @samp{(real? @var{z})} is true if +and only if @samp{(zero? (imag-part @var{z}))} is true. If @var{x} is an inexact +real number, then @samp{(integer? @var{x})} is true if and only if +@samp{(= @var{x} (round @var{x}))}. + + +@format +@t{(complex? 3+4i) ==> #t +(complex? 3) ==> #t +(real? 3) ==> #t +(real? -2.5+0.0i) ==> #t +(real? #e1e10) ==> #t +(rational? 6/10) ==> #t +(rational? 6/3) ==> #t +(integer? 3+0i) ==> #t +(integer? 3.0) ==> #t +(integer? 8/4) ==> #t +} +@end format + + + +@quotation +@emph{Note:} +The behavior of these type predicates on @r{inexact} numbers +is unreliable, since any inaccuracy may affect the result. +@end quotation + + + +@quotation +@emph{Note:} +In many implementations the @code{rational?} procedure will be the same +@vindex @w{rational?} +as @code{real?}, and the @code{complex?} procedure will be the same as +@vindex @w{complex?} +@vindex @w{real?} +@code{number?}, but unusual implementations may be able to represent +@vindex @w{number?} +some irrational numbers exactly or may extend the number system to +support some kind of non-complex numbers. +@end quotation + + +@end deffn + + +@deffn {procedure} exact? @var{z} +@deffnx {procedure} inexact? @var{z} + +These numerical predicates provide tests for the exactness of a +quantity. For any Scheme number, precisely one of these predicates +is true. + +@end deffn + + + +@deffn {procedure} = z1 z2 z3 @dots{}, +@deffnx {procedure} < x1 x2 x3 @dots{}, +@deffnx {procedure} > x1 x2 x3 @dots{}, +@deffnx {procedure} <= x1 x2 x3 @dots{}, +@deffnx {procedure} >= x1 x2 x3 @dots{}, + +@c - Some implementations allow these procedures to take many arguments, to +@c - facilitate range checks. +These procedures return @t{#t} if their arguments are (respectively): +equal, monotonically increasing, monotonically decreasing, +monotonically nondecreasing, or monotonically nonincreasing. + +These predicates are required to be transitive. + + +@quotation +@emph{Note:} +The traditional implementations of these predicates in Lisp-like +languages are not transitive. +@end quotation + + + +@quotation +@emph{Note:} +While it is not an error to compare @r{inexact} numbers using these +predicates, the results may be unreliable because a small inaccuracy +may affect the result; this is especially true of @code{=} and @code{zero?}. +@vindex @w{zero?} +@vindex @w{=} +When in doubt, consult a numerical analyst. +@end quotation + + +@end deffn + + +@deffn {library procedure} zero? @var{z} +@deffnx {library procedure} positive? @var{x} +@deffnx {library procedure} negative? @var{x} +@deffnx {library procedure} odd? @var{n} +@deffnx {library procedure} even? @var{n} + +These numerical predicates test a number for a particular property, +returning @t{#t} or @t{#f}. See note above. + +@end deffn + + +@deffn {library procedure} max x1 x2 @dots{}, +@deffnx {library procedure} min x1 x2 @dots{}, + +These procedures return the maximum or minimum of their arguments. + + +@format +@t{(max 3 4) ==> 4 ; exact +(max 3.9 4) ==> 4.0 ; inexact +} +@end format + + + +@quotation +@emph{Note:} +If any argument is inexact, then the result will also be inexact (unless +the procedure can prove that the inaccuracy is not large enough to affect the +result, which is possible only in unusual implementations). If @samp{min} or +@samp{max} is used to compare numbers of mixed exactness, and the numerical +value of the result cannot be represented as an inexact number without loss of +accuracy, then the procedure may report a violation of an implementation +restriction. +@end quotation + + +@end deffn + + + +@deffn {procedure} + z1 @dots{}, +@deffnx {procedure} * z1 @dots{}, + +These procedures return the sum or product of their arguments. +@c - These procedures are exactness preserving. + + +@format +@t{(+ 3 4) ==> 7 +(+ 3) ==> 3 +(+) ==> 0 +(* 4) ==> 4 +(*) ==> 1 +} +@end format + + +@end deffn + + + +@deffn {procedure} - z1 z2 +@deffnx {procedure} - @var{z} +@deffnx {optional procedure} - z1 z2 @dots{}, +@deffnx {procedure} / z1 z2 +@deffnx {procedure} / @var{z} +@deffnx {optional procedure} / z1 z2 @dots{}, + +With two or more arguments, these procedures return the difference or +quotient of their arguments, associating to the left. With one argument, +however, they return the additive or multiplicative inverse of their argument. +@c - These procedures are exactness preserving, except that division may +@c - coerce its result to inexact in implementations that do not support +@c - \tupe{ratnum}s. + + +@format +@t{(- 3 4) ==> -1 +(- 3 4 5) ==> -6 +(- 3) ==> -3 +(/ 3 4 5) ==> 3/20 +(/ 3) ==> 1/3 +} +@end format + + +@end deffn + + + +@deffn {library procedure} abs x + +@samp{Abs} returns the absolute value of its argument. +@c - {\cf Abs} is exactness preserving when its argument is real. + +@format +@t{(abs -7) ==> 7 +} +@end format + +@end deffn + + + +@deffn {procedure} quotient n1 n2 +@deffnx {procedure} remainder n1 n2 +@deffnx {procedure} modulo n1 n2 + +These procedures implement number-theoretic (integer) +division. @var{n2} should be non-zero. All three procedures +return integers. If @var{n1}/@var{n2} is an integer: + +@format +@t{ (quotient @var{n1} @var{n2}) ==> @var{n1}/@var{n2} + (remainder @var{n1} @var{n2}) ==> 0 + (modulo @var{n1} @var{n2}) ==> 0 +} +@end format + +If @var{n1}/@var{n2} is not an integer: + +@format +@t{ (quotient @var{n1} @var{n2}) ==> @var{n_q} + (remainder @var{n1} @var{n2}) ==> @var{n_r} + (modulo @var{n1} @var{n2}) ==> @var{n_m} +} +@end format + +where @var{n_q} is @var{n1}/@var{n2} rounded towards zero, +0 < |@var{n_r}| < |@var{n2}|, 0 < |@var{n_m}| < |@var{n2}|, +@var{n_r} and @var{n_m} differ from @var{n1} by a multiple of @var{n2}, +@var{n_r} has the same sign as @var{n1}, and +@var{n_m} has the same sign as @var{n2}. + +From this we can conclude that for integers @var{n1} and @var{n2} with +@var{n2} not equal to 0, + +@format +@t{ (= @var{n1} (+ (* @var{n2} (quotient @var{n1} @var{n2})) + (remainder @var{n1} @var{n2}))) + ==> #t +} +@end format + +provided all numbers involved in that computation are exact. + + +@format +@t{(modulo 13 4) ==> 1 +(remainder 13 4) ==> 1 + +(modulo -13 4) ==> 3 +(remainder -13 4) ==> -1 + +(modulo 13 -4) ==> -3 +(remainder 13 -4) ==> 1 + +(modulo -13 -4) ==> -1 +(remainder -13 -4) ==> -1 + +(remainder -13 -4.0) ==> -1.0 ; inexact +} +@end format + +@end deffn + + +@deffn {library procedure} gcd n1 @dots{}, +@deffnx {library procedure} lcm n1 @dots{}, + +These procedures return the greatest common divisor or least common +multiple of their arguments. The result is always non-negative. +@c - These procedures are exactness preserving. + +@c %R4%% I added the inexact example. + +@format +@t{(gcd 32 -36) ==> 4 +(gcd) ==> 0 +(lcm 32 -36) ==> 288 +(lcm 32.0 -36) ==> 288.0 ; inexact +(lcm) ==> 1 +} +@end format + + +@end deffn + + + +@deffn {procedure} numerator @var{q} +@deffnx {procedure} denominator @var{q} + +These procedures return the numerator or denominator of their +argument; the result is computed as if the argument was represented as +a fraction in lowest terms. The denominator is always positive. The +denominator of 0 is defined to be 1. +@c - The remarks about denominators are new. +@c - Clearly, they are exactness-preserving procedures. + +@ignore todo +More description and examples needed. +@end ignore + + +@format +@t{(numerator (/ 6 4)) ==> 3 +(denominator (/ 6 4)) ==> 2 +(denominator + (exact->inexact (/ 6 4))) ==> 2.0 +} +@end format + + +@end deffn + + + +@deffn {procedure} floor x +@deffnx {procedure} ceiling x +@deffnx {procedure} truncate x +@deffnx {procedure} round x + + +These procedures return integers. +@samp{Floor} returns the largest integer not larger than @var{x}. +@samp{Ceiling} returns the smallest integer not smaller than @var{x}. +@samp{Truncate} returns the integer closest to @var{x} whose absolute +value is not larger than the absolute value of @var{x}. @samp{Round} returns the +closest integer to @var{x}, rounding to even when @var{x} is halfway between two +integers. + + +@quotation +@emph{Rationale:} +@samp{Round} rounds to even for consistency with the default rounding +mode specified by the IEEE floating point standard. +@end quotation + + + +@quotation +@emph{Note:} +If the argument to one of these procedures is inexact, then the result +will also be inexact. If an exact value is needed, the +result should be passed to the @samp{inexact->exact} procedure. +@end quotation + + + +@format +@t{(floor -4.3) ==> -5.0 +(ceiling -4.3) ==> -4.0 +(truncate -4.3) ==> -4.0 +(round -4.3) ==> -4.0 + +(floor 3.5) ==> 3.0 +(ceiling 3.5) ==> 4.0 +(truncate 3.5) ==> 3.0 +(round 3.5) ==> 4.0 ; inexact + +(round 7/2) ==> 4 ; exact +(round 7) ==> 7 +} +@end format + + +@end deffn + + +@deffn {library procedure} rationalize x y +@c - \proto{rationalize}{ x}{procedure} + + +@samp{Rationalize} returns the @emph{simplest} rational number +differing from @var{x} by no more than @var{y}. A rational number r_1 is +@emph{simpler} than another rational number +@cindex @w{simplest rational} +r_2 if r_1 = p_1/q_1 and r_2 = p_2/q_2 (in lowest terms) and |p_1|<= |p_2| and |q_1| <= |q_2|. Thus 3/5 is simpler than 4/7. +Although not all rationals are comparable in this ordering (consider 2/7 +and 3/5) any interval contains a rational number that is simpler than +every other rational number in that interval (the simpler 2/5 lies +between 2/7 and 3/5). Note that 0 = 0/1 is the simplest rational of +all. + + +@format +@t{(rationalize + (inexact->exact .3) 1/10) ==> 1/3 ; exact +(rationalize .3 1/10) ==> #i1/3 ; inexact +} +@end format + + +@end deffn + + +@deffn {procedure} exp @var{z} +@deffnx {procedure} log @var{z} +@deffnx {procedure} sin @var{z} +@deffnx {procedure} cos @var{z} +@deffnx {procedure} tan @var{z} +@deffnx {procedure} asin @var{z} +@deffnx {procedure} acos @var{z} +@deffnx {procedure} atan @var{z} +@deffnx {procedure} atan @var{y} @var{x} + +These procedures are part of every implementation that supports +@c %R4%% +general +real numbers; they compute the usual transcendental functions. @samp{log} +computes the natural logarithm of @var{z} (not the base ten logarithm). +@samp{asin}, @samp{acos}, and @samp{atan} compute arcsine (sin^-1), +arccosine (cos^-1), and arctangent (tan^-1), respectively. +The two-argument variant of @samp{atan} computes @t{(angle +(make-rectangular @var{x} @var{y}))} (see below), even in implementations +that don't support general complex numbers. + +In general, the mathematical functions log, arcsine, arccosine, and +arctangent are multiply defined. +The value of log z is defined to be the one whose imaginary +part lies in the range from -pi (exclusive) to pi (inclusive). +log 0 is undefined. +With log defined this way, the values of sin^-1 z, cos^-1 z, +and tan^-1 z are according to the following formulae: + + +@center sin^-1 z = -i log (i z + sqrt(1 - z^2)) + + + +@center cos^-1 z = pi / 2 - sin^-1 z + + + +@center tan^-1 z = (log (1 + i z) - log (1 - i z)) / (2 i) + + +The above specification follows [CLtL], which in turn +cites [Penfield81]; refer to these sources for more detailed +discussion of branch cuts, boundary conditions, and implementation of +these functions. When it is possible these procedures produce a real +result from a real argument. + +@c %R4%% + +@ignore todo +The cited references are likely to change their branch cuts +soon to allow for the possibility of distinct positive and negative +zeroes, as in IEEE floating point. We may not want to follow those +changes, since we may want a complex number with zero imaginary part +(whether positive or negative zero) to be treated as a real. I don't +think there are any better standards for complex arithmetic than the +ones cited, so we're really on our own here. +@end ignore + + +@end deffn + + + +@deffn {procedure} sqrt @var{z} + +Returns the principal square root of @var{z}. The result will have +either positive real part, or zero real part and non-negative imaginary +part. +@end deffn + + + +@deffn {procedure} expt z1 z2 + +Returns @var{z1} raised to the power @var{z2}. For z_1 ~= 0 + + +@center z_1^z_2 = e^z_2 log z_1 + +0^z is 1 if z = 0 and 0 otherwise. +@end deffn + +@c - \begin{entry}{%- +@c - \proto{approximate}{ z x}{procedure}} +@c - +@c - Returns an approximation to \vr{z} in a representation whose precision is +@c - the same as that +@c - of the representation of \vr{x}, which must be an inexact number. The +@c - result is always inexact. +@c - +@c - \begin{scheme} +@c - (approximate 3.1415926535 1F10) +@c - \ev 3.14159F0 +@c - (approximate 3.1415926535 \#I65535) +@c - \ev \#I3 +@c - (approximate 3.14F0 1L8) +@c - \ev 3.14L0 +@c - (approximate 3.1415926535F0 1L8) +@c - \ev 3.14159L0 +@c - \end{scheme} +@c - \end{entry} + + + + +@deffn {procedure} make-rectangular x1 x2 +@deffnx {procedure} make-polar x3 x4 +@deffnx {procedure} real-part @var{z} +@deffnx {procedure} imag-part @var{z} +@deffnx {procedure} magnitude @var{z} +@deffnx {procedure} angle @var{z} + +These procedures are part of every implementation that supports +@c %R4%% +general +complex numbers. Suppose @var{x1}, @var{x2}, @var{x3}, and @var{x4} are +real numbers and @var{z} is a complex number such that + + +@center @var{z} = @var{x1} + @var{x2}@w{i} = @var{x3} . e^@w{i} @var{x4} + +Then + +@format +@t{(make-rectangular @var{x1} @var{x2}) ==> @var{z} +(make-polar @var{x3} @var{x4}) ==> @var{z} +(real-part @var{z}) ==> @var{x1} +(imag-part @var{z}) ==> @var{x2} +(magnitude @var{z}) ==> |@var{x3}| +(angle @var{z}) ==> x_angle +} +@end format + +where -pi < x_angle <= pi with x_angle = @var{x4} + 2pi n +for some integer n. + + +@quotation +@emph{Rationale:} +@samp{Magnitude} is the same as @code{abs} for a real argument, +@vindex @w{abs} +but @samp{abs} must be present in all implementations, whereas +@samp{magnitude} need only be present in implementations that support +general complex numbers. +@end quotation + + +@end deffn + + + +@deffn {procedure} exact->inexact @var{z} +@deffnx {procedure} inexact->exact @var{z} + +@samp{Exact->inexact} returns an @r{inexact} representation of @var{z}. +The value returned is the +@r{inexact} number that is numerically closest to the argument. +@c %R4%%For +@c \tupe{exact} arguments which have no reasonably close \tupe{inexact} equivalent, +@c it is permissible to signal an error. +If an @r{exact} argument has no reasonably close @r{inexact} equivalent, +then a violation of an implementation restriction may be reported. + +@samp{Inexact->exact} returns an @r{exact} representation of +@var{z}. The value returned is the @r{exact} number that is numerically +closest to the argument. +@c %R4%% For \tupe{inexact} arguments which have no +@c reasonably close \tupe{exact} equivalent, it is permissible to signal +@c an error. +If an @r{inexact} argument has no reasonably close @r{exact} equivalent, +then a violation of an implementation restriction may be reported. + +@c %R%% I moved this to the section on implementation restrictions. +@c For any implementation that supports \tupe{inexact} quantities, +@c there is a subset of the integers for which there are both \tupe{exact} and +@c \tupe{inexact} representations. This subset must include the non-negative +@c integers up to a limit specified by the implementation. The limit +@c must be big enough to represent all digits in reasonable radices, and +@c may correspond to some natural word size for the implementation. For +@c such integers, these procedures implement the natural one-to-one +@c correspondence between the representations. + +These procedures implement the natural one-to-one correspondence between +@r{exact} and @r{inexact} integers throughout an +implementation-dependent range. See section @ref{Implementation restrictions}. + +@end deffn + +@sp 3 + +@node Numerical input and output, , Numerical operations, Numbers +@subsection Numerical input and output + + + +@deffn {procedure} number->string z +@deffnx {procedure} number->string z radix + +@var{Radix} must be an exact integer, either 2, 8, 10, or 16. If omitted, +@var{radix} defaults to 10. +The procedure @samp{number->string} takes a +number and a radix and returns as a string an external representation of +the given number in the given radix such that + +@format +@t{(let ((number @var{number}) + (radix @var{radix})) + (eqv? number + (string->number (number->string number + radix) + radix))) +} +@end format + +is true. It is an error if no possible result makes this expression true. + +If @var{z} is inexact, the radix is 10, and the above expression +can be satisfied by a result that contains a decimal point, +then the result contains a decimal point and is expressed using the +minimum number of digits (exclusive of exponent and trailing +zeroes) needed to make the above expression +true [howtoprint], [howtoread]; +otherwise the format of the result is unspecified. + +The result returned by @samp{number->string} +never contains an explicit radix prefix. + + +@quotation +@emph{Note:} +The error case can occur only when @var{z} is not a complex number +or is a complex number with a non-rational real or imaginary part. +@end quotation + + + +@quotation +@emph{Rationale:} +If @var{z} is an inexact number represented using flonums, and +the radix is 10, then the above expression is normally satisfied by +a result containing a decimal point. The unspecified case +allows for infinities, NaNs, and non-flonum representations. +@end quotation + + +@end deffn + + + +@deffn {procedure} string->number string +@deffnx {procedure} string->number string radix + +@c %R4%% I didn't include the (string->number string radix exactness) +@c case, since I haven't heard any resolution of the coding to be used +@c for the third argument. + +Returns a number of the maximally precise representation expressed by the +given @var{string}. @var{Radix} must be an exact integer, either 2, 8, 10, +or 16. If supplied, @var{radix} is a default radix that may be overridden +by an explicit radix prefix in @var{string} (e.g. @t{"#o177"}). If @var{radix} +is not supplied, then the default radix is 10. If @var{string} is not +a syntactically valid notation for a number, then @samp{string->number} +returns @t{#f}. + + +@format +@t{(string->number "100") ==> 100 +(string->number "100" 16) ==> 256 +(string->number "1e2") ==> 100.0 +(string->number "15##") ==> 1500.0 +} +@end format + + + +@quotation +@emph{Note:} +The domain of @samp{string->number} may be restricted by implementations +in the following ways. @samp{String->number} is permitted to return +@t{#f} whenever @var{string} contains an explicit radix prefix. +If all numbers supported by an implementation are real, then +@samp{string->number} is permitted to return @t{#f} whenever +@var{string} uses the polar or rectangular notations for complex +numbers. If all numbers are integers, then +@samp{string->number} may return @t{#f} whenever +the fractional notation is used. If all numbers are exact, then +@samp{string->number} may return @t{#f} whenever +an exponent marker or explicit exactness prefix is used, or if +a @t{#} appears in place of a digit. If all inexact +numbers are integers, then +@samp{string->number} may return @t{#f} whenever +a decimal point is used. +@end quotation + + +@end deffn + +@node Other data types, Control features, Numbers, Standard procedures +@section Other data types + +@menu +* Booleans:: +* Pairs and lists:: +* Symbols:: +* Characters:: +* Strings:: +* Vectors:: +@end menu + + +This section describes operations on some of Scheme's non-numeric data types: +booleans, pairs, lists, symbols, characters, strings and vectors. + +@node Booleans, Pairs and lists, Other data types, Other data types +@subsection Booleans + + + +The standard boolean objects for true and false are written as +@t{#t} and @t{#f}. What really +@vindex #f +@vindex #t +matters, though, are the objects that the Scheme conditional expressions +(@samp{if}, @samp{cond}, @samp{and}, @samp{or}, @samp{do}) treat as +true or false. The phrase ``a true value'' +@cindex @w{false} +@cindex @w{true} +(or sometimes just ``true'') means any object treated as true by the +conditional expressions, and the phrase ``a false value'' (or +@cindex @w{false} +``false'') means any object treated as false by the conditional expressions. + +Of all the standard Scheme values, only @t{#f} +@c is guaranteed to count +counts as false in conditional expressions. +@c It is not +@c specified whether the empty list\index{empty list} counts as false +@c or as true in conditional expressions. +Except for @t{#f}, +@c and possibly the empty list, +all standard Scheme values, including @t{#t}, +pairs, the empty list, symbols, numbers, strings, vectors, and procedures, +count as true. + +@c \begin{note} +@c In some implementations the empty list counts as false, contrary +@c to the above. +@c Nonetheless a few examples in this report assume that the +@c empty list counts as true, as in \cite{IEEEScheme}. +@c \end{note} + +@c \begin{rationale} +@c For historical reasons some implementations regard \schfalse{} and the +@c empty list as the same object. These implementations therefore cannot +@c make the empty list count as true in conditional expressions. +@c \end{rationale} + + +@quotation +@emph{Note:} +Programmers accustomed to other dialects of Lisp should be aware that +Scheme distinguishes both @t{#f} and the empty list +@cindex @w{empty list} +from the symbol @code{nil}. +@vindex @w{nil} +@end quotation + + +Boolean constants evaluate to themselves, so they do not need to be quoted +in programs. + + +@example + +#t ==> #t +#f ==> #f +'#f ==> #f + +@end example + + + + +@deffn {library procedure} not obj + +@samp{Not} returns @t{#t} if @var{obj} is false, and returns +@t{#f} otherwise. + + +@format +@t{(not #t) ==> #f +(not 3) ==> #f +(not (list 3)) ==> #f +(not #f) ==> #t +(not '()) ==> #f +(not (list)) ==> #f +(not 'nil) ==> #f +} +@end format + + +@end deffn + + + +@deffn {library procedure} boolean? obj + +@samp{Boolean?} returns @t{#t} if @var{obj} is either @t{#t} or +@t{#f} and returns @t{#f} otherwise. + + +@format +@t{(boolean? #f) ==> #t +(boolean? 0) ==> #f +(boolean? '()) ==> #f +} +@end format + + +@end deffn + + +@node Pairs and lists, Symbols, Booleans, Other data types +@subsection Pairs and lists + + + +A @dfn{pair} (sometimes called a @dfn{dotted pair}) is a +@cindex @w{dotted pair} +@cindex @w{pair} +record structure with two fields called the car and cdr fields (for +historical reasons). Pairs are created by the procedure @samp{cons}. +The car and cdr fields are accessed by the procedures @samp{car} and +@samp{cdr}. The car and cdr fields are assigned by the procedures +@samp{set-car!} and @samp{set-cdr!}. + +Pairs are used primarily to represent lists. A list can +be defined recursively as either the empty list or a pair whose +@cindex @w{empty list} +cdr is a list. More precisely, the set of lists is defined as the smallest +set @var{X} such that + + + +@itemize @bullet + +@item +The empty list is in @var{X}. +@item +If @var{list} is in @var{X}, then any pair whose cdr field contains +@var{list} is also in @var{X}. + +@end itemize + + +The objects in the car fields of successive pairs of a list are the +elements of the list. For example, a two-element list is a pair whose car +is the first element and whose cdr is a pair whose car is the second element +and whose cdr is the empty list. The length of a list is the number of +elements, which is the same as the number of pairs. + +The empty list is a special object of its own type +@cindex @w{empty list} +(it is not a pair); it has no elements and its length is zero. + + +@quotation +@emph{Note:} +The above definitions imply that all lists have finite length and are +terminated by the empty list. +@end quotation + + +The most general notation (external representation) for Scheme pairs is +the ``dotted'' notation @w{@samp{(@var{c1} .@: @var{c2})}} where +@var{c1} is the value of the car field and @var{c2} is the value of the +cdr field. For example @samp{(4 .@: 5)} is a pair whose car is 4 and whose +cdr is 5. Note that @samp{(4 .@: 5)} is the external representation of a +pair, not an expression that evaluates to a pair. + +A more streamlined notation can be used for lists: the elements of the +list are simply enclosed in parentheses and separated by spaces. The +empty list is written @t{()} . For example, +@cindex @w{empty list} + + +@example + +(a b c d e) + +@end example + + +and + + +@example + +(a . (b . (c . (d . (e . ()))))) + +@end example + + +are equivalent notations for a list of symbols. + +A chain of pairs not ending in the empty list is called an +@dfn{improper list}. Note that an improper list is not a list. +@cindex @w{improper list} +The list and dotted notations can be combined to represent +improper lists: + + +@example + +(a b c . d) + +@end example + + +is equivalent to + + +@example + +(a . (b . (c . d))) + +@end example + + +Whether a given pair is a list depends upon what is stored in the cdr +field. When the @code{set-cdr!} procedure is used, an object can be a +@vindex @w{set-cdr!} +list one moment and not the next: + + +@example + +(define x (list 'a 'b 'c)) +(define y x) +y ==> (a b c) +(list? y) ==> #t +(set-cdr! x 4) ==> @emph{unspecified} +x ==> (a . 4) +(eqv? x y) ==> #t +y ==> (a . 4) +(list? y) ==> #f +(set-cdr! x x) ==> @emph{unspecified} +(list? x) ==> #f + +@end example + + +@c It is often convenient to speak of a homogeneous list of objects +@c of some particular data type, as for example \hbox{\cf (1 2 3)} is a list of +@c integers. To be more precise, suppose \var{D} is some data type. (Any +@c predicate defines a data type consisting of those objects of which the +@c predicate is true.) Then + +@c \begin{itemize} +@c \item The empty list is a list of \var{D}. +@c \item If \var{list} is a list of \var{D}, then any pair whose cdr is +@c \var{list} and whose car is an element of the data type \var{D} is also a +@c list of \var{D}. +@c \item There are no other lists of \var{D}. +@c \end{itemize} + +Within literal expressions and representations of objects read by the +@code{read} procedure, the forms @t{'}@r{<datum>}, +@vindex ' +@vindex @w{read} +@t{`}@r{<datum>}, @t{,}@r{<datum>}, and +@vindex , +@t{,@@}@r{<datum>} denote two-ele@-ment lists whose first elements are +the symbols @code{quote}, @code{quasiquote}, @w{@code{unquote}}, and +@vindex @w{unquote} +@vindex @w{quasiquote} +@vindex @w{quote} +@code{unquote-splicing}, respectively. The second element in each case +@vindex @w{unquote-splicing} +is @r{<datum>}. This convention is supported so that arbitrary Scheme +programs may be represented as lists. +@ignore todo +Can or need this be stated +more carefully? +@end ignore + That is, according to Scheme's grammar, every +<expression> is also a <datum> (see section @pxref{External representation}). +Among other things, this permits the use of the @samp{read} procedure to +parse Scheme programs. See section @ref{External representations}. + + + +@deffn {procedure} pair? obj + +@samp{Pair?} returns @t{#t} if @var{obj} is a pair, and otherwise +returns @t{#f}. + + +@format +@t{(pair? '(a . b)) ==> #t +(pair? '(a b c)) ==> #t +(pair? '()) ==> #f +(pair? '#(a b)) ==> #f +} +@end format + +@end deffn + + + +@deffn {procedure} cons obj1 obj2 + +Returns a newly allocated pair whose car is @var{obj1} and whose cdr is +@var{obj2}. The pair is guaranteed to be different (in the sense of +@samp{eqv?}) from every existing object. + + +@format +@t{(cons 'a '()) ==> (a) +(cons '(a) '(b c d)) ==> ((a) b c d) +(cons "a" '(b c)) ==> ("a" b c) +(cons 'a 3) ==> (a . 3) +(cons '(a b) 'c) ==> ((a b) . c) +} +@end format + +@end deffn + + + +@deffn {procedure} car pair + +@ignore nodomain +@var{Pair} must be a pair. +@end ignore + +Returns the contents of the car field of @var{pair}. Note that it is an +error to take the car of the empty list. +@cindex @w{empty list} + + +@format +@t{(car '(a b c)) ==> a +(car '((a) b c d)) ==> (a) +(car '(1 . 2)) ==> 1 +(car '()) ==> @emph{error} +} +@end format + + +@end deffn + + + +@deffn {procedure} cdr pair + +@ignore nodomain +@var{Pair} must be a pair. +@end ignore + +Returns the contents of the cdr field of @var{pair}. +Note that it is an error to take the cdr of the empty list. + + +@format +@t{(cdr '((a) b c d)) ==> (b c d) +(cdr '(1 . 2)) ==> 2 +(cdr '()) ==> @emph{error} +} +@end format + + +@end deffn + + + +@deffn {procedure} set-car! pair obj + +@ignore nodomain +@var{Pair} must be a pair. +@end ignore + +Stores @var{obj} in the car field of @var{pair}. +The value returned by @samp{set-car!} is unspecified. +@c <!> +@c This procedure can be very confusing if used indiscriminately. + + +@format +@t{(define (f) (list 'not-a-constant-list)) +(define (g) '(constant-list)) +(set-car! (f) 3) ==> @emph{unspecified} +(set-car! (g) 3) ==> @emph{error} +} +@end format + + +@end deffn + + + +@deffn {procedure} set-cdr! pair obj + +@ignore nodomain +@var{Pair} must be a pair. +@end ignore + +Stores @var{obj} in the cdr field of @var{pair}. +The value returned by @samp{set-cdr!} is unspecified. +@c <!> +@c This procedure can be very confusing if used indiscriminately. + +@end deffn + + + + + + +@deffn {library procedure} caar pair +@deffnx {library procedure} cadr pair + +@deffnx { @w{ @dots{}}} @w{ @dots{}} + +@deffnx {library procedure} cdddar pair +@deffnx {library procedure} cddddr pair + +These procedures are compositions of @samp{car} and @samp{cdr}, where +for example @samp{caddr} could be defined by + + +@format +@t{(define caddr (lambda (x) (car (cdr (cdr x)))))@r{.} +} +@end format + + +Arbitrary compositions, up to four deep, are provided. There are +twenty-eight of these procedures in all. + +@end deffn + + + +@deffn {library procedure} null? obj + +Returns @t{#t} if @var{obj} is the empty list, +@cindex @w{empty list} +otherwise returns @t{#f}. + +@c \begin{note} +@c In implementations in which the empty +@c list is the same as \schfalse{}, {\cf null?} will return \schtrue{} +@c if \var{obj} is \schfalse{}. +@c \end{note} + +@end deffn + + +@deffn {library procedure} list? obj + +Returns @t{#t} if @var{obj} is a list, otherwise returns @t{#f}. +By definition, all lists have finite length and are terminated by +the empty list. + + +@format +@t{ (list? '(a b c)) ==> #t + (list? '()) ==> #t + (list? '(a . b)) ==> #f + (let ((x (list 'a))) + (set-cdr! x x) + (list? x)) ==> #f +} +@end format + +@end deffn + + + +@deffn {library procedure} list @var{obj} @dots{}, + +Returns a newly allocated list of its arguments. + + +@format +@t{(list 'a (+ 3 4) 'c) ==> (a 7 c) +(list) ==> () +} +@end format + +@end deffn + + + +@deffn {library procedure} length list + +@ignore nodomain +@var{List} must be a list. +@end ignore + +Returns the length of @var{list}. + + +@format +@t{(length '(a b c)) ==> 3 +(length '(a (b) (c d e))) ==> 3 +(length '()) ==> 0 +} +@end format + +@end deffn + + + +@deffn {library procedure} append list @dots{}, + +@ignore nodomain +All @var{list}s should be lists. +@end ignore + +Returns a list consisting of the elements of the first @var{list} +followed by the elements of the other @var{list}s. + + +@format +@t{(append '(x) '(y)) ==> (x y) +(append '(a) '(b c d)) ==> (a b c d) +(append '(a (b)) '((c))) ==> (a (b) (c)) +} +@end format + + +The resulting list is always newly allocated, except that it shares +structure with the last @var{list} argument. The last argument may +actually be any object; an improper list results if the last argument is not a +proper list. +@ignore todo +This is pretty awkward. I should get Bartley to fix this. +@end ignore + + + +@format +@t{(append '(a b) '(c . d)) ==> (a b c . d) +(append '() 'a) ==> a +} +@end format + +@end deffn + + + +@deffn {library procedure} reverse list + +@ignore nodomain +@var{List} must be a list. +@end ignore + +Returns a newly allocated list consisting of the elements of @var{list} +in reverse order. + + +@format +@t{(reverse '(a b c)) ==> (c b a) +(reverse '(a (b c) d (e (f)))) + ==> ((e (f)) d (b c) a) +} +@end format + +@end deffn + + + +@deffn {library procedure} list-tail list @var{k} + +Returns the sublist of @var{list} obtained by omitting the first @var{k} +elements. It is an error if @var{list} has fewer than @var{k} elements. +@samp{List-tail} could be defined by + + +@format +@t{(define list-tail + (lambda (x k) + (if (zero? k) + x + (list-tail (cdr x) (- k 1))))) +} +@end format + +@end deffn + + + +@deffn {library procedure} list-ref list @var{k} + +Returns the @var{k}th element of @var{list}. (This is the same +as the car of @t{(list-tail @var{list} @var{k})}.) +It is an error if @var{list} has fewer than @var{k} elements. + + +@format +@t{(list-ref '(a b c d) 2) ==> c +(list-ref '(a b c d) + (inexact->exact (round 1.8))) + ==> c +} +@end format + +@end deffn + + +@c \begin{entry}{% +@c \proto{last-pair}{ list}{library procedure}} + +@c Returns the last pair in the nonempty, possibly improper, list \var{list}. +@c {\cf Last-pair} could be defined by + +@c \begin{scheme} +@c (define last-pair +@c (lambda (x) +@c (if (pair? (cdr x)) +@c (last-pair (cdr x)) +@c x)))% +@c \end{scheme} + +@c \end{entry} + + + +@deffn {library procedure} memq obj list +@deffnx {library procedure} memv obj list +@deffnx {library procedure} member obj list + +These procedures return the first sublist of @var{list} whose car is +@var{obj}, where the sublists of @var{list} are the non-empty lists +returned by @t{(list-tail @var{list} @var{k})} for @var{k} less +than the length of @var{list}. If +@var{obj} does not occur in @var{list}, then @t{#f} (not the empty list) is +returned. @samp{Memq} uses @samp{eq?} to compare @var{obj} with the elements of +@var{list}, while @samp{memv} uses @samp{eqv?} and @samp{member} uses @samp{equal?}. + + +@format +@t{(memq 'a '(a b c)) ==> (a b c) +(memq 'b '(a b c)) ==> (b c) +(memq 'a '(b c d)) ==> #f +(memq (list 'a) '(b (a) c)) ==> #f +(member (list 'a) + '(b (a) c)) ==> ((a) c) +(memq 101 '(100 101 102)) ==> @emph{unspecified} +(memv 101 '(100 101 102)) ==> (101 102) +} +@end format + + +@end deffn + + + +@deffn {library procedure} assq obj alist +@deffnx {library procedure} assv obj alist +@deffnx {library procedure} assoc obj alist + +@var{Alist} (for ``association list'') must be a list of +pairs. These procedures find the first pair in @var{alist} whose car field is @var{obj}, +and returns that pair. If no pair in @var{alist} has @var{obj} as its +car, then @t{#f} (not the empty list) is returned. @samp{Assq} uses +@samp{eq?} to compare @var{obj} with the car fields of the pairs in @var{alist}, +while @samp{assv} uses @samp{eqv?} and @samp{assoc} uses @samp{equal?}. + + +@format +@t{(define e '((a 1) (b 2) (c 3))) +(assq 'a e) ==> (a 1) +(assq 'b e) ==> (b 2) +(assq 'd e) ==> #f +(assq (list 'a) '(((a)) ((b)) ((c)))) + ==> #f +(assoc (list 'a) '(((a)) ((b)) ((c)))) + ==> ((a)) +(assq 5 '((2 3) (5 7) (11 13))) + ==> @emph{unspecified} +(assv 5 '((2 3) (5 7) (11 13))) + ==> (5 7) +} +@end format + + + + +@quotation +@emph{Rationale:} +Although they are ordinarily used as predicates, +@samp{memq}, @samp{memv}, @samp{member}, @samp{assq}, @samp{assv}, and @samp{assoc} do not +have question marks in their names because they return useful values rather +than just @t{#t} or @t{#f}. +@end quotation + +@end deffn + + +@node Symbols, Characters, Pairs and lists, Other data types +@subsection Symbols + + + +Symbols are objects whose usefulness rests on the fact that two +symbols are identical (in the sense of @samp{eqv?}) if and only if their +names are spelled the same way. This is exactly the property needed to +represent identifiers in programs, and so most +@cindex @w{identifier} +implementations of Scheme use them internally for that purpose. Symbols +are useful for many other applications; for instance, they may be used +the way enumerated values are used in Pascal. + +The rules for writing a symbol are exactly the same as the rules for +writing an identifier; see sections @ref{Identifiers} +and @ref{Lexical structure}. + +It is guaranteed that any symbol that has been returned as part of +a literal expression, or read using the @samp{read} procedure, and +subsequently written out using the @samp{write} procedure, will read back +in as the identical symbol (in the sense of @samp{eqv?}). The +@samp{string->symbol} procedure, however, can create symbols for +which this write/read invariance may not hold because their names +contain special characters or letters in the non-standard case. + + +@quotation +@emph{Note:} +Some implementations of Scheme have a feature known as ``slashification'' +in order to guarantee write/read invariance for all symbols, but +historically the most important use of this feature has been to +compensate for the lack of a string data type. + +Some implementations also have ``uninterned symbols'', which +defeat write/read invariance even in implementations with slashification, +and also generate exceptions to the rule that two symbols are the same +if and only if their names are spelled the same. +@end quotation + + + + +@deffn {procedure} symbol? obj + +Returns @t{#t} if @var{obj} is a symbol, otherwise returns @t{#f}. + + +@format +@t{(symbol? 'foo) ==> #t +(symbol? (car '(a b))) ==> #t +(symbol? "bar") ==> #f +(symbol? 'nil) ==> #t +(symbol? '()) ==> #f +(symbol? #f) ==> #f +} +@end format + +@end deffn + + + +@deffn {procedure} symbol->string symbol + +Returns the name of @var{symbol} as a string. If the symbol was part of +an object returned as the value of a literal expression +(section @pxref{Literal expressions}) or by a call to the @samp{read} procedure, +and its name contains alphabetic characters, then the string returned +will contain characters in the implementation's preferred standard +case---some implementations will prefer upper case, others lower case. +If the symbol was returned by @samp{string->symbol}, the case of +characters in the string returned will be the same as the case in the +string that was passed to @samp{string->symbol}. It is an error +to apply mutation procedures like @code{string-set!} to strings returned +@vindex @w{string-set!} +by this procedure. + +The following examples assume that the implementation's standard case is +lower case: + + +@format +@t{(symbol->string 'flying-fish) + ==> "flying-fish" +(symbol->string 'Martin) ==> "martin" +(symbol->string + (string->symbol "Malvina")) + ==> "Malvina" +} +@end format + +@end deffn + + + +@deffn {procedure} string->symbol string + +Returns the symbol whose name is @var{string}. This procedure can +create symbols with names containing special characters or letters in +the non-standard case, but it is usually a bad idea to create such +symbols because in some implementations of Scheme they cannot be read as +themselves. See @samp{symbol->string}. + +The following examples assume that the implementation's standard case is +lower case: + + +@format +@t{(eq? 'mISSISSIppi 'mississippi) + ==> #t +(string->symbol "mISSISSIppi") + ==> + @r{}the symbol with name "mISSISSIppi" +(eq? 'bitBlt (string->symbol "bitBlt")) + ==> #f +(eq? 'JollyWog + (string->symbol + (symbol->string 'JollyWog))) + ==> #t +(string=? "K. Harper, M.D." + (symbol->string + (string->symbol "K. Harper, M.D."))) + ==> #t +} +@end format + + +@end deffn + + +@node Characters, Strings, Symbols, Other data types +@subsection Characters + + + +Characters are objects that represent printed characters such as +letters and digits. +@c There is no requirement that the data type of +@c characters be disjoint from other data types; implementations are +@c encouraged to have a separate character data type, but may choose to +@c represent characters as integers, strings, or some other type. +Characters are written using the notation #\@r{<character>} +or #\@r{<character name>}. +For example: + + + +@center @c begin-tabular +@quotation +@table @asis +@item @t{#\a} +; lower case letter +@item @t{#\A} +; upper case letter +@item @t{#\(} +; left parenthesis +@item @t{#\ } +; the space character +@item @t{#\space} +; the preferred way to write a space +@item @t{#\newline} +; the newline character +@item +@end table +@end quotation + + + + +Case is significant in #\@r{<character>}, but not in +#\@r{<character name>}. +@c \hyper doesn't + +@c allow a linebreak +If @r{<character>} in +#\@r{<character>} is alphabetic, then the character +following @r{<character>} must be a delimiter character such as a +space or parenthesis. This rule resolves the ambiguous case where, for +example, the sequence of characters ``@t{#\ space}'' +could be taken to be either a representation of the space character or a +representation of the character ``@t{#\ s}'' followed +by a representation of the symbol ``@t{pace}.'' + +@ignore todo +Fix +@end ignore + +Characters written in the #\ notation are self-evaluating. +That is, they do not have to be quoted in programs. +@c The \sharpsign\backwhack{} +@c notation is not an essential part of Scheme, however. Even implementations +@c that support the \sharpsign\backwhack{} notation for input do not have to +@c support it for output. + +Some of the procedures that operate on characters ignore the +difference between upper case and lower case. The procedures that +ignore case have @w{``@t{-ci}''} (for ``case +insensitive'') embedded in their names. + + + +@deffn {procedure} char? obj + +Returns @t{#t} if @var{obj} is a character, otherwise returns @t{#f}. + +@end deffn + + + +@deffn {procedure} char=? char1 char2 +@deffnx {procedure} char<? char1 char2 +@deffnx {procedure} char>? char1 char2 +@deffnx {procedure} char<=? char1 char2 +@deffnx {procedure} char>=? char1 char2 + + +@ignore nodomain +Both @var{char1} and @var{char2} must be characters. +@end ignore + +These procedures impose a total ordering on the set of characters. It +is guaranteed that under this ordering: + + + +@itemize @bullet + +@item +The upper case characters are in order. For example, @samp{(char<? #\A #\B)} returns @t{#t}. +@item +The lower case characters are in order. For example, @samp{(char<? #\a #\b)} returns @t{#t}. +@item +The digits are in order. For example, @samp{(char<? #\0 #\9)} returns @t{#t}. +@item +Either all the digits precede all the upper case letters, or vice versa. +@item +Either all the digits precede all the lower case letters, or vice versa. + +@end itemize + + +Some implementations may generalize these procedures to take more than +two arguments, as with the corresponding numerical predicates. + +@end deffn + + + +@deffn {library procedure} char-ci=? char1 char2 +@deffnx {library procedure} char-ci<? char1 char2 +@deffnx {library procedure} char-ci>? char1 char2 +@deffnx {library procedure} char-ci<=? char1 char2 +@deffnx {library procedure} char-ci>=? char1 char2 + +@ignore nodomain +Both @var{char1} and @var{char2} must be characters. +@end ignore + +These procedures are similar to @samp{char=?} et cetera, but they treat +upper case and lower case letters as the same. For example, @samp{(char-ci=? #\A #\a)} returns @t{#t}. Some +implementations may generalize these procedures to take more than two +arguments, as with the corresponding numerical predicates. + +@end deffn + + + +@deffn {library procedure} char-alphabetic? char +@deffnx {library procedure} char-numeric? char +@deffnx {library procedure} char-whitespace? char +@deffnx {library procedure} char-upper-case? letter +@deffnx {library procedure} char-lower-case? letter + +These procedures return @t{#t} if their arguments are alphabetic, +numeric, whitespace, upper case, or lower case characters, respectively, +otherwise they return @t{#f}. The following remarks, which are specific to +the ASCII character set, are intended only as a guide: The alphabetic characters +are the 52 upper and lower case letters. The numeric characters are the +ten decimal digits. The whitespace characters are space, tab, line +feed, form feed, and carriage return. +@end deffn + + +@c %R4%%\begin{entry}{% +@c \proto{char-upper-case?}{ letter}{procedure} +@c \proto{char-lower-case?}{ letter}{procedure}} + +@c \domain{\var{Letter} must be an alphabetic character.} +@c These procedures return \schtrue{} if their arguments are upper case or +@c lower case characters, respectively, otherwise they return \schfalse. +@c \end{entry} + + + +@deffn {procedure} char->integer char +@deffnx {procedure} integer->char @var{n} + +Given a character, @samp{char->integer} returns an exact integer +representation of the character. Given an exact integer that is the image of +a character under @samp{char->integer}, @samp{integer->char} +returns that character. These procedures implement order-preserving isomorphisms +between the set of characters under the @code{char<=?} ordering and some +@vindex @w{char<=?} +subset of the integers under the @samp{<=} ordering. That is, if + + +@format +@t{(char<=? @var{a} @var{b}) @result{} #t @r{}and (<= @var{x} @var{y}) @result{} #t +} +@end format + + + +@noindent + and @var{x} and @var{y} are in the domain of +@samp{integer->char}, then + + +@format +@t{(<= (char->integer @var{a}) + (char->integer @var{b})) ==> #t + +(char<=? (integer->char @var{x}) + (integer->char @var{y})) ==> #t +} +@end format + + +@end deffn + + + +@deffn {library procedure} char-upcase char +@deffnx {library procedure} char-downcase char + +@ignore nodomain +@var{Char} must be a character. +@end ignore + +These procedures return a character @var{char2} such that @samp{(char-ci=? @var{char} @var{char2})}. In addition, if @var{char} is +alphabetic, then the result of @samp{char-upcase} is upper case and the +result of @samp{char-downcase} is lower case. + +@end deffn + + +@node Strings, Vectors, Characters, Other data types +@subsection Strings + + + +Strings are sequences of characters. +@c In some implementations of Scheme +@c they are immutable; other implementations provide destructive procedures +@c such as {\cf string-set!}\ that alter string objects. +Strings are written as sequences of characters enclosed within doublequotes +(@samp{"}). A doublequote can be written inside a string only by escaping +it with a backslash (\), as in + + +@example + +"The word \"recursion\" has many meanings." + +@end example + + +A backslash can be written inside a string only by escaping it with another +backslash. Scheme does not specify the effect of a backslash within a +string that is not followed by a doublequote or backslash. + +A string constant may continue from one line to the next, but +the exact contents of such a string are unspecified. +@c this is +@c usually a bad idea because +@c the exact effect may vary from one computer +@c system to another. + +The @emph{length} of a string is the number of characters that it +contains. This number is an exact, non-negative integer that is fixed when the +string is created. The @dfn{valid indexes} of a string are the +@cindex @w{valid indexes} +exact non-negative integers less than the length of the string. The first +character of a string has index 0, the second has index 1, and so on. + +In phrases such as ``the characters of @var{string} beginning with +index @var{start} and ending with index @var{end},'' it is understood +that the index @var{start} is inclusive and the index @var{end} is +exclusive. Thus if @var{start} and @var{end} are the same index, a null +substring is referred to, and if @var{start} is zero and @var{end} is +the length of @var{string}, then the entire string is referred to. + +Some of the procedures that operate on strings ignore the +difference between upper and lower case. The versions that ignore case +have @w{``@samp{-ci}''} (for ``case insensitive'') embedded in their +names. + + + +@deffn {procedure} string? obj + +Returns @t{#t} if @var{obj} is a string, otherwise returns @t{#f}. +@end deffn + + + +@deffn {procedure} make-string @var{k} +@deffnx {procedure} make-string @var{k} char + +@c \domain{\vr{k} must be a non-negative integer, and \var{char} must be +@c a character.} +@samp{Make-string} returns a newly allocated string of +length @var{k}. If @var{char} is given, then all elements of the string +are initialized to @var{char}, otherwise the contents of the +@var{string} are unspecified. + +@end deffn + + +@deffn {library procedure} string char @dots{}, + +Returns a newly allocated string composed of the arguments. + +@end deffn + + +@deffn {procedure} string-length string + +Returns the number of characters in the given @var{string}. +@end deffn + + + +@deffn {procedure} string-ref string @var{k} + +@var{k} must be a valid index of @var{string}. +@samp{String-ref} returns character @var{k} of @var{string} using zero-origin indexing. +@end deffn + + + +@deffn {procedure} string-set! string k char + + +@c \var{String} must be a string, +@var{k} must be a valid index of @var{string} +@c , and \var{char} must be a character +. +@samp{String-set!} stores @var{char} in element @var{k} of @var{string} +and returns an unspecified value. +@c <!> + + +@format +@t{(define (f) (make-string 3 #\*)) +(define (g) "***") +(string-set! (f) 0 #\?) ==> @emph{unspecified} +(string-set! (g) 0 #\?) ==> @emph{error} +(string-set! (symbol->string 'immutable) + 0 + #\?) ==> @emph{error} +} +@end format + + +@end deffn + + + +@deffn {library procedure} string=? string1 string2 +@deffnx {library procedure} string-ci=? string1 string2 + +Returns @t{#t} if the two strings are the same length and contain the same +characters in the same positions, otherwise returns @t{#f}. +@samp{String-ci=?} treats +upper and lower case letters as though they were the same character, but +@samp{string=?} treats upper and lower case as distinct characters. + +@end deffn + + + +@deffn {library procedure} string<? string1 string2 +@deffnx {library procedure} string>? string1 string2 +@deffnx {library procedure} string<=? string1 string2 +@deffnx {library procedure} string>=? string1 string2 +@deffnx {library procedure} string-ci<? string1 string2 +@deffnx {library procedure} string-ci>? string1 string2 +@deffnx {library procedure} string-ci<=? string1 string2 +@deffnx {library procedure} string-ci>=? string1 string2 + +These procedures are the lexicographic extensions to strings of the +corresponding orderings on characters. For example, @samp{string<?} is +the lexicographic ordering on strings induced by the ordering +@samp{char<?} on characters. If two strings differ in length but +are the same up to the length of the shorter string, the shorter string +is considered to be lexicographically less than the longer string. + +Implementations may generalize these and the @samp{string=?} and +@samp{string-ci=?} procedures to take more than two arguments, as with +the corresponding numerical predicates. + +@end deffn + + + +@deffn {library procedure} substring string start end + +@var{String} must be a string, and @var{start} and @var{end} +must be exact integers satisfying + + +@center 0 <= @var{start} <= @var{end} <= @w{@t{(string-length @var{string})@r{.}}} + +@samp{Substring} returns a newly allocated string formed from the characters of +@var{string} beginning with index @var{start} (inclusive) and ending with index +@var{end} (exclusive). +@end deffn + + + +@deffn {library procedure} string-append @var{string} @dots{}, + +Returns a newly allocated string whose characters form the concatenation of the +given strings. + +@end deffn + + + +@deffn {library procedure} string->list string +@deffnx {library procedure} list->string list + +@samp{String->list} returns a newly allocated list of the +characters that make up the given string. @samp{List->string} +returns a newly allocated string formed from the characters in the list +@var{list}, which must be a list of characters. @samp{String->list} +and @samp{list->string} are +inverses so far as @samp{equal?} is concerned. +@c Implementations that provide +@c destructive operations on strings should ensure that the result of +@c {\cf list\coerce{}string} is newly allocated. + +@end deffn + + + +@deffn {library procedure} string-copy string + +Returns a newly allocated copy of the given @var{string}. + +@end deffn + + + +@deffn {library procedure} string-fill! string char + +Stores @var{char} in every element of the given @var{string} and returns an +unspecified value. +@c <!> + +@end deffn + + +@node Vectors, , Strings, Other data types +@subsection Vectors + + + +Vectors are heterogeneous structures whose elements are indexed +by integers. A vector typically occupies less space than a list +of the same length, and the average time required to access a randomly +chosen element is typically less for the vector than for the list. + +The @emph{length} of a vector is the number of elements that it +contains. This number is a non-negative integer that is fixed when the +vector is created. The @emph{valid indexes} of a +@cindex @w{valid indexes} +vector are the exact non-negative integers less than the length of the +vector. The first element in a vector is indexed by zero, and the last +element is indexed by one less than the length of the vector. + +Vectors are written using the notation @t{#(@var{obj} @dots{},)}. +For example, a vector of length 3 containing the number zero in element +0, the list @samp{(2 2 2 2)} in element 1, and the string @samp{"Anna"} in +element 2 can be written as following: + + +@example + +#(0 (2 2 2 2) "Anna") + +@end example + + +Note that this is the external representation of a vector, not an +expression evaluating to a vector. Like list constants, vector +constants must be quoted: + + +@example + +'#(0 (2 2 2 2) "Anna") + ==> #(0 (2 2 2 2) "Anna") + +@end example + + +@ignore todo +Pitman sez: The visual similarity to lists is bound to be confusing +to some. Elaborate on the distinction. +@end ignore + + + + +@deffn {procedure} vector? obj + +Returns @t{#t} if @var{obj} is a vector, otherwise returns @t{#f}. +@end deffn + + + +@deffn {procedure} make-vector k +@deffnx {procedure} make-vector k fill + +Returns a newly allocated vector of @var{k} elements. If a second +argument is given, then each element is initialized to @var{fill}. +Otherwise the initial contents of each element is unspecified. + +@end deffn + + + +@deffn {library procedure} vector obj @dots{}, + +Returns a newly allocated vector whose elements contain the given +arguments. Analogous to @samp{list}. + + +@format +@t{(vector 'a 'b 'c) ==> #(a b c) +} +@end format + +@end deffn + + + +@deffn {procedure} vector-length vector + +Returns the number of elements in @var{vector} as an exact integer. +@end deffn + + + +@deffn {procedure} vector-ref vector k + +@var{k} must be a valid index of @var{vector}. +@samp{Vector-ref} returns the contents of element @var{k} of +@var{vector}. + + +@format +@t{(vector-ref '#(1 1 2 3 5 8 13 21) + 5) + ==> 8 +(vector-ref '#(1 1 2 3 5 8 13 21) + (let ((i (round (* 2 (acos -1))))) + (if (inexact? i) + (inexact->exact i) + i))) + ==> 13 +} +@end format + +@end deffn + + + +@deffn {procedure} vector-set! vector k obj + +@var{k} must be a valid index of @var{vector}. +@samp{Vector-set!} stores @var{obj} in element @var{k} of @var{vector}. +The value returned by @samp{vector-set!} is unspecified. +@c <!> + + +@format +@t{(let ((vec (vector 0 '(2 2 2 2) "Anna"))) + (vector-set! vec 1 '("Sue" "Sue")) + vec) + ==> #(0 ("Sue" "Sue") "Anna") + +(vector-set! '#(0 1 2) 1 "doe") + ==> @emph{error} ; constant vector +} +@end format + +@end deffn + + + +@deffn {library procedure} vector->list vector +@deffnx {library procedure} list->vector list + +@samp{Vector->list} returns a newly allocated list of the objects contained +in the elements of @var{vector}. @samp{List->vector} returns a newly +created vector initialized to the elements of the list @var{list}. + + +@format +@t{(vector->list '#(dah dah didah)) + ==> (dah dah didah) +(list->vector '(dididit dah)) + ==> #(dididit dah) +} +@end format + +@end deffn + + + +@deffn {library procedure} vector-fill! vector fill + +Stores @var{fill} in every element of @var{vector}. +The value returned by @samp{vector-fill!} is unspecified. +@c <!> + +@end deffn + + +@node Control features, Eval, Other data types, Standard procedures +@section Control features + + + +@c Intro flushed; not very a propos any more. +@c Procedures should be discussed somewhere, however. + +This chapter describes various primitive procedures which control the +flow of program execution in special ways. +The @samp{procedure?} predicate is also described here. + +@ignore todo +@t{Procedure?} doesn't belong in a section with the name +``control features.'' What to do? +@end ignore + + + +@deffn {procedure} procedure? obj + +Returns @t{#t} if @var{obj} is a procedure, otherwise returns @t{#f}. + + +@format +@t{(procedure? car) ==> #t +(procedure? 'car) ==> #f +(procedure? (lambda (x) (* x x))) + ==> #t +(procedure? '(lambda (x) (* x x))) + ==> #f +(call-with-current-continuation procedure?) + ==> #t +} +@end format + + +@end deffn + + + +@deffn {procedure} apply proc arg1 @dots{} args + +@var{Proc} must be a procedure and @var{args} must be a list. +Calls @var{proc} with the elements of the list +@samp{(append (list @var{arg1} @dots{},) @var{args})} as the actual +arguments. + + +@format +@t{(apply + (list 3 4)) ==> 7 + +(define compose + (lambda (f g) + (lambda args + (f (apply g args))))) + +((compose sqrt *) 12 75) ==> 30 +} +@end format + +@end deffn + + + +@deffn {library procedure} map proc list1 list2 @dots{}, + +The @var{list}s must be lists, and @var{proc} must be a +procedure taking as many arguments as there are @i{list}s +and returning a single value. If more +than one @var{list} is given, then they must all be the same length. +@samp{Map} applies @var{proc} element-wise to the elements of the +@var{list}s and returns a list of the results, in order. +The dynamic order in which @var{proc} is applied to the elements of the +@var{list}s is unspecified. + + +@format +@t{(map cadr '((a b) (d e) (g h))) + ==> (b e h) + +(map (lambda (n) (expt n n)) + '(1 2 3 4 5)) + ==> (1 4 27 256 3125) + +(map + '(1 2 3) '(4 5 6)) ==> (5 7 9) + +(let ((count 0)) + (map (lambda (ignored) + (set! count (+ count 1)) + count) + '(a b))) ==> (1 2) @var{or} (2 1) +} +@end format + + +@end deffn + + + +@deffn {library procedure} for-each proc list1 list2 @dots{}, + +The arguments to @samp{for-each} are like the arguments to @samp{map}, but +@samp{for-each} calls @var{proc} for its side effects rather than for its +values. Unlike @samp{map}, @samp{for-each} is guaranteed to call @var{proc} on +the elements of the @var{list}s in order from the first element(s) to the +last, and the value returned by @samp{for-each} is unspecified. + + +@format +@t{(let ((v (make-vector 5))) + (for-each (lambda (i) + (vector-set! v i (* i i))) + '(0 1 2 3 4)) + v) ==> #(0 1 4 9 16) +} +@end format + + +@end deffn + + + +@deffn {library procedure} force promise + +Forces the value of @var{promise} (see @code{delay}, +@vindex @w{delay} +section @pxref{Delayed evaluation}). If no value has been computed for +@cindex @w{promise} +the promise, then a value is computed and returned. The value of the +promise is cached (or ``memoized'') so that if it is forced a second +time, the previously computed value is returned. +@c without any recomputation. +@c [As pointed out by Marc Feeley, the "without any recomputation" +@c isn't necessarily true. --Will] + + +@format +@t{(force (delay (+ 1 2))) ==> 3 +(let ((p (delay (+ 1 2)))) + (list (force p) (force p))) + ==> (3 3) + +(define a-stream + (letrec ((next + (lambda (n) + (cons n (delay (next (+ n 1))))))) + (next 0))) +(define head car) +(define tail + (lambda (stream) (force (cdr stream)))) + +(head (tail (tail a-stream))) + ==> 2 +} +@end format + + +@samp{Force} and @samp{delay} are mainly intended for programs written in +functional style. The following examples should not be considered to +illustrate good programming style, but they illustrate the property that +only one value is computed for a promise, no matter how many times it is +forced. +@c the value of a promise is computed at most once. +@c [As pointed out by Marc Feeley, it may be computed more than once, +@c but as I observed we can at least insist that only one value be +@c used! -- Will] + + +@format +@t{(define count 0) +(define p + (delay (begin (set! count (+ count 1)) + (if (> count x) + count + (force p))))) +(define x 5) +p ==> @i{}a promise +(force p) ==> 6 +p ==> @i{}a promise, still +(begin (set! x 10) + (force p)) ==> 6 +} +@end format + + +Here is a possible implementation of @samp{delay} and @samp{force}. +Promises are implemented here as procedures of no arguments, +and @samp{force} simply calls its argument: + + +@format +@t{(define force + (lambda (object) + (object))) +} +@end format + + +We define the expression + + +@format +@t{(delay @r{<expression>}) +} +@end format + + +to have the same meaning as the procedure call + + +@format +@t{(make-promise (lambda () @r{<expression>}))@r{} +} +@end format + + +as follows + + +@format +@t{(define-syntax delay + (syntax-rules () + ((delay expression) + (make-promise (lambda () expression))))), +} +@end format + + +where @samp{make-promise} is defined as follows: + +@c \begin{scheme} +@c (define make-promise +@c (lambda (proc) +@c (let ((already-run? \schfalse) (result \schfalse)) +@c (lambda () +@c (cond ((not already-run?) +@c (set! result (proc)) +@c (set! already-run? \schtrue))) +@c result))))% +@c \end{scheme} + + +@format +@t{(define make-promise + (lambda (proc) + (let ((result-ready? #f) + (result #f)) + (lambda () + (if result-ready? + result + (let ((x (proc))) + (if result-ready? + result + (begin (set! result-ready? #t) + (set! result x) + result)))))))) +} +@end format + + + +@quotation +@emph{Rationale:} +A promise may refer to its own value, as in the last example above. +Forcing such a promise may cause the promise to be forced a second time +before the value of the first force has been computed. +This complicates the definition of @samp{make-promise}. +@end quotation + + +Various extensions to this semantics of @samp{delay} and @samp{force} +are supported in some implementations: + + + +@itemize @bullet + +@item +Calling @samp{force} on an object that is not a promise may simply +return the object. + +@item +It may be the case that there is no means by which a promise can be +operationally distinguished from its forced value. That is, expressions +like the following may evaluate to either @t{#t} or to @t{#f}, +depending on the implementation: + + +@format +@t{(eqv? (delay 1) 1) ==> @emph{unspecified} +(pair? (delay (cons 1 2))) ==> @emph{unspecified} +} +@end format + + +@item +Some implementations may implement ``implicit forcing,'' where +the value of a promise is forced by primitive procedures like @samp{cdr} +and @samp{+}: + + +@format +@t{(+ (delay (* 3 7)) 13) ==> 34 +} +@end format + + +@end itemize + +@end deffn + + +@deffn {procedure} call-with-current-continuation proc + + @var{Proc} must be a procedure of one +argument. The procedure @samp{call-with-current-continuation} packages +up the current continuation (see the rationale below) as an ``escape +procedure'' and passes it as an argument to +@cindex @w{escape procedure} +@var{proc}. The escape procedure is a Scheme procedure that, if it is +later called, will abandon whatever continuation is in effect at that later +time and will instead use the continuation that was in effect +when the escape procedure was created. Calling the escape procedure +may cause the invocation of @var{before} and @var{after} thunks installed using +@code{dynamic-wind}. +@vindex @w{dynamic-wind} + +The escape procedure accepts the same number of arguments as the continuation to +the original call to @t{call-with-current-continuation}. +Except for continuations created by the @samp{call-with-values} +procedure, all continuations take exactly one value. The +effect of passing no value or more than one value to continuations +that were not created by @t{call-with-values} is unspecified. + +The escape procedure that is passed to @var{proc} has +unlimited extent just like any other procedure in Scheme. It may be stored +in variables or data structures and may be called as many times as desired. + +The following examples show only the most common ways in which +@samp{call-with-current-continuation} is used. If all real uses were as +simple as these examples, there would be no need for a procedure with +the power of @samp{call-with-current-continuation}. + + +@format +@t{(call-with-current-continuation + (lambda (exit) + (for-each (lambda (x) + (if (negative? x) + (exit x))) + '(54 0 37 -3 245 19)) + #t)) ==> -3 + +(define list-length + (lambda (obj) + (call-with-current-continuation + (lambda (return) + (letrec ((r + (lambda (obj) + (cond ((null? obj) 0) + ((pair? obj) + (+ (r (cdr obj)) 1)) + (else (return #f)))))) + (r obj)))))) + +(list-length '(1 2 3 4)) ==> 4 + +(list-length '(a b . c)) ==> #f +} +@end format + + + +@quotation +@emph{Rationale:} + +A common use of @samp{call-with-current-continuation} is for +structured, non-local exits from loops or procedure bodies, but in fact +@samp{call-with-current-continuation} is extremely useful for implementing a +wide variety of advanced control structures. + +Whenever a Scheme expression is evaluated there is a +@dfn{continuation} wanting the result of the expression. The continuation +@cindex @w{continuation} +represents an entire (default) future for the computation. If the expression is +evaluated at top level, for example, then the continuation might take the +result, print it on the screen, prompt for the next input, evaluate it, and +so on forever. Most of the time the continuation includes actions +specified by user code, as in a continuation that will take the result, +multiply it by the value stored in a local variable, add seven, and give +the answer to the top level continuation to be printed. Normally these +ubiquitous continuations are hidden behind the scenes and programmers do not +think much about them. On rare occasions, however, a programmer may +need to deal with continuations explicitly. +@samp{Call-with-current-continuation} allows Scheme programmers to do +that by creating a procedure that acts just like the current +continuation. + +Most programming languages incorporate one or more special-purpose +escape constructs with names like @t{exit}, @w{@samp{return}}, or +even @t{goto}. In 1965, however, Peter Landin [Landin65] +invented a general purpose escape operator called the J-operator. John +Reynolds [Reynolds72] described a simpler but equally powerful +construct in 1972. The @samp{catch} special form described by Sussman +and Steele in the 1975 report on Scheme is exactly the same as +Reynolds's construct, though its name came from a less general construct +in MacLisp. Several Scheme implementors noticed that the full power of the +@code{catch} construct could be provided by a procedure instead of by a +@vindex @w{catch} +special syntactic construct, and the name +@samp{call-with-current-continuation} was coined in 1982. This name is +descriptive, but opinions differ on the merits of such a long name, and +some people use the name @code{call/cc} instead. +@vindex @w{call/cc} +@end quotation + + +@end deffn + + +@deffn {procedure} values obj @dots{} + +Delivers all of its arguments to its continuation. +Except for continuations created by the @code{call-with-values} +@vindex @w{call-with-values} +procedure, all continuations take exactly one value. +@t{Values} might be defined as follows: + +@format +@t{(define (values . things) + (call-with-current-continuation + (lambda (cont) (apply cont things)))) +} +@end format + + +@end deffn + + +@deffn {procedure} call-with-values producer consumer + +Calls its @var{producer} argument with no values and +a continuation that, when passed some values, calls the +@var{consumer} procedure with those values as arguments. +The continuation for the call to @var{consumer} is the +continuation of the call to @t{call-with-values}. + + +@format +@t{(call-with-values (lambda () (values 4 5)) + (lambda (a b) b)) + ==> 5 + +(call-with-values * -) ==> -1 +} +@end format + + +@end deffn + + +@deffn {procedure} dynamic-wind before thunk after + +Calls @var{thunk} without arguments, returning the result(s) of this call. +@var{Before} and @var{after} are called, also without arguments, as required +by the following rules (note that in the absence of calls to continuations +captured using @code{call-with-current-continuation} the three arguments are +@vindex @w{call-with-current-continuation} +called once each, in order). @var{Before} is called whenever execution +enters the dynamic extent of the call to @var{thunk} and @var{after} is called +whenever it exits that dynamic extent. The dynamic extent of a procedure +call is the period between when the call is initiated and when it +returns. In Scheme, because of @samp{call-with-current-continuation}, the +dynamic extent of a call may not be a single, connected time period. +It is defined as follows: + + +@itemize @bullet + +@item +The dynamic extent is entered when execution of the body of the +called procedure begins. + +@item +The dynamic extent is also entered when execution is not within +the dynamic extent and a continuation is invoked that was captured +(using @samp{call-with-current-continuation}) during the dynamic extent. + +@item +It is exited when the called procedure returns. + +@item +It is also exited when execution is within the dynamic extent and +a continuation is invoked that was captured while not within the +dynamic extent. + +@end itemize + + +If a second call to @samp{dynamic-wind} occurs within the dynamic extent of the +call to @var{thunk} and then a continuation is invoked in such a way that the +@var{after}s from these two invocations of @samp{dynamic-wind} are both to be +called, then the @var{after} associated with the second (inner) call to +@samp{dynamic-wind} is called first. + +If a second call to @samp{dynamic-wind} occurs within the dynamic extent of the +call to @var{thunk} and then a continuation is invoked in such a way that the +@var{before}s from these two invocations of @samp{dynamic-wind} are both to be +called, then the @var{before} associated with the first (outer) call to +@samp{dynamic-wind} is called first. + +If invoking a continuation requires calling the @var{before} from one call +to @samp{dynamic-wind} and the @var{after} from another, then the @var{after} +is called first. + +The effect of using a captured continuation to enter or exit the dynamic +extent of a call to @var{before} or @var{after} is undefined. + + +@format +@t{(let ((path '()) + (c #f)) + (let ((add (lambda (s) + (set! path (cons s path))))) + (dynamic-wind + (lambda () (add 'connect)) + (lambda () + (add (call-with-current-continuation + (lambda (c0) + (set! c c0) + 'talk1)))) + (lambda () (add 'disconnect))) + (if (< (length path) 4) + (c 'talk2) + (reverse path)))) + + ==> (connect talk1 disconnect + connect talk2 disconnect) +} +@end format + +@end deffn + +@node Eval, Input and output, Control features, Standard procedures +@section Eval + + + +@deffn {procedure} eval expression environment-specifier + +Evaluates @var{expression} in the specified environment and returns its value. +@var{Expression} must be a valid Scheme expression represented as data, +and @var{environment-specifier} must be a value returned by one of the +three procedures described below. +Implementations may extend @samp{eval} to allow non-expression programs +(definitions) as the first argument and to allow other +values as environments, with the restriction that @samp{eval} is not +allowed to create new bindings in the environments associated with +@samp{null-environment} or @samp{scheme-report-environment}. + + +@format +@t{(eval '(* 7 3) (scheme-report-environment 5)) + ==> 21 + +(let ((f (eval '(lambda (f x) (f x x)) + (null-environment 5)))) + (f + 10)) + ==> 20 +} +@end format + + +@end deffn + + +@deffn {procedure} scheme-report-environment version +@deffnx {procedure} null-environment version + +@var{Version} must be the exact integer @samp{5}, +corresponding to this revision of the Scheme report (the +Revised^5 Report on Scheme). +@samp{Scheme-report-environment} returns a specifier for an +environment that is empty except for all bindings defined in +this report that are either required or both optional and +supported by the implementation. @samp{Null-environment} returns +a specifier for an environment that is empty except for the +(syntactic) bindings for all syntactic keywords defined in +this report that are either required or both optional and +supported by the implementation. + +Other values of @var{version} can be used to specify environments +matching past revisions of this report, but their support is not +required. An implementation will signal an error if @var{version} +is neither @samp{5} nor another value supported by +the implementation. + +The effect of assigning (through the use of @samp{eval}) a variable +bound in a @samp{scheme-report-environment} +(for example @samp{car}) is unspecified. Thus the environments specified +by @samp{scheme-report-environment} may be immutable. + +@end deffn + + +@deffn {optional procedure} interaction-environment + +This procedure returns a specifier for the environment that +contains imple@-men@-ta@-tion-defined bindings, typically a superset of +those listed in the report. The intent is that this procedure +will return the environment in which the implementation would evaluate +expressions dynamically typed by the user. + +@end deffn + +@node Input and output, , Eval, Standard procedures +@section Input and output + +@menu +* Ports:: +* Input:: +* Output:: +* System interface:: +@end menu + + +@node Ports, Input, Input and output, Input and output +@subsection Ports + + + +Ports represent input and output devices. To Scheme, an input port is a +Scheme object that can deliver characters upon command, while an output port +is a Scheme object that can accept characters. +@cindex @w{port} + +@ignore todo +Haase: Mention that there are alternatives to files? +@end ignore + + + +@deffn {library procedure} call-with-input-file string proc +@deffnx {library procedure} call-with-output-file string proc + +@var{String} should be a string naming a file, and +@var{proc} should be a procedure that accepts one argument. +For @samp{call-with-input-file}, +the file should already exist; for +@samp{call-with-output-file}, +the effect is unspecified if the file +already exists. These procedures call @var{proc} with one argument: the +port obtained by opening the named file for input or output. If the +file cannot be opened, an error is signalled. If @var{proc} returns, +then the port is closed automatically and the value(s) yielded by the +@var{proc} is(are) returned. If @var{proc} does not return, then +the port will not be closed automatically unless it is possible to +prove that the port will never again be used for a read or write +operation. +@c Scheme +@c will not close the port unless it can prove that the port will never +@c again be used for a read or write operation. + + +@quotation +@emph{Rationale:} +Because Scheme's escape procedures have unlimited extent, it is +possible to escape from the current continuation but later to escape back in. +If implementations were permitted to close the port on any escape from the +current continuation, then it would be impossible to write portable code using +both @samp{call-with-current-continuation} and @samp{call-with-input-file} or +@samp{call-with-output-file}. +@ignore todo +Pitman wants more said here; maybe encourage users to call +@var{close-foo-port}; maybe talk about process switches (?). +@end ignore + +@end quotation + +@end deffn + + + +@deffn {procedure} input-port? obj +@deffnx {procedure} output-port? obj + +Returns @t{#t} if @var{obj} is an input port or output port +respectively, otherwise returns @t{#f}. + +@ignore todo +Won't necessarily return true after port is closed. +@end ignore + + +@end deffn + + + +@deffn {procedure} current-input-port +@deffnx {procedure} current-output-port + +Returns the current default input or output port. + +@end deffn + + + +@deffn {optional procedure} with-input-from-file string thunk +@deffnx {optional procedure} with-output-to-file string thunk + +@var{String} should be a string naming a file, and +@var{proc} should be a procedure of no arguments. +For @samp{with-input-from-file}, +the file should already exist; for +@samp{with-output-to-file}, +the effect is unspecified if the file +already exists. +The file is opened for input or output, an input or output port +connected to it is made the default value returned by +@samp{current-input-port} or @samp{current-output-port} +(and is used by @t{(read)}, @t{(write @var{obj})}, and so forth), +and the +@var{thunk} is called with no arguments. When the @var{thunk} returns, +the port is closed and the previous default is restored. +@samp{With-input-from-file} and @samp{with-output-to-file} return(s) the +value(s) yielded by @var{thunk}. +If an escape procedure +is used to escape from the continuation of these procedures, their +behavior is implementation dependent. + +@ignore todo +OK this with authors?? +@end ignore + +@c current continuation changes in such a way +@c as to make it doubtful that the \var{thunk} will ever return. + +@ignore todo +Freeman: +Throughout this section I wanted to see ``the value of @t{(current-input-port)}'' +instead of ``the value returned by @var{current-input-port}''. (Same for +@var{current-output-port}.) +@end ignore + + + +@end deffn + + + +@deffn {procedure} open-input-file filename + +Takes a string naming an existing file and returns an input port capable of +delivering characters from the file. If the file cannot be opened, an error is +signalled. + +@end deffn + + + +@deffn {procedure} open-output-file filename + +Takes a string naming an output file to be created and returns an output +port capable of writing characters to a new file by that name. If the file +cannot be opened, an error is signalled. If a file with the given name +already exists, the effect is unspecified. + +@end deffn + + + +@deffn {procedure} close-input-port port +@deffnx {procedure} close-output-port port + +Closes the file associated with @var{port}, rendering the @var{port} +incapable of delivering or accepting characters. +@ignore todo +But maybe a no-op +on some ports, e.g. terminals or editor buffers. +@end ignore + +These routines have no effect if the file has already been closed. +The value returned is unspecified. + +@ignore todo +Ramsdell: Some note is needed explaining why there are two +different close procedures. +@end ignore + + +@ignore todo +A port isn't necessarily still a port after it has been closed? +@end ignore + + +@end deffn + + +@node Input, Output, Ports, Input and output +@subsection Input + + + + +@noindent + @w{ } +@c ??? +@sp 5 +@ignore todo +The input routines have some things in common, maybe explain here. +@end ignore + + + +@deffn {library procedure} read +@deffnx {library procedure} read port + +@samp{Read} converts external representations of Scheme objects into the +objects themselves. That is, it is a parser for the nonterminal +<datum> (see sections @pxref{External representation} and +@pxref{Pairs and lists}). @samp{Read} returns the next +object parsable from the given input @var{port}, updating @var{port} to point to +the first character past the end of the external representation of the object. + +If an end of file is encountered in the input before any +characters are found that can begin an object, then an end of file +object is returned. +@ignore todo + +@end ignore + The port remains open, and further attempts +to read will also return an end of file object. If an end of file is +encountered after the beginning of an object's external representation, +but the external representation is incomplete and therefore not parsable, +an error is signalled. + +The @var{port} argument may be omitted, in which case it defaults to the +value returned by @samp{current-input-port}. It is an error to read from +a closed port. +@end deffn + + +@deffn {procedure} read-char +@deffnx {procedure} read-char port + +Returns the next character available from the input @var{port}, updating +the @var{port} to point to the following character. If no more characters +are available, an end of file object is returned. @var{Port} may be +omitted, in which case it defaults to the value returned by @samp{current-input-port}. + +@end deffn + + + +@deffn {procedure} peek-char +@deffnx {procedure} peek-char port + +Returns the next character available from the input @var{port}, +@emph{without} updating +the @var{port} to point to the following character. If no more characters +are available, an end of file object is returned. @var{Port} may be +omitted, in which case it defaults to the value returned by @samp{current-input-port}. + + +@quotation +@emph{Note:} +The value returned by a call to @samp{peek-char} is the same as the +value that would have been returned by a call to @samp{read-char} with the +same @var{port}. The only difference is that the very next call to +@samp{read-char} or @samp{peek-char} on that @var{port} will return the +value returned by the preceding call to @samp{peek-char}. In particular, a call +to @samp{peek-char} on an interactive port will hang waiting for input +whenever a call to @samp{read-char} would have hung. +@end quotation + + +@end deffn + + + +@deffn {procedure} eof-object? obj + +Returns @t{#t} if @var{obj} is an end of file object, otherwise returns +@t{#f}. The precise set of end of file objects will vary among +implementations, but in any case no end of file object will ever be an object +that can be read in using @samp{read}. + +@end deffn + + + +@deffn {procedure} char-ready? +@deffnx {procedure} char-ready? port + +Returns @t{#t} if a character is ready on the input @var{port} and +returns @t{#f} otherwise. If @samp{char-ready} returns @t{#t} then +the next @samp{read-char} operation on the given @var{port} is guaranteed +not to hang. If the @var{port} is at end of file then @samp{char-ready?} +returns @t{#t}. @var{Port} may be omitted, in which case it defaults to +the value returned by @samp{current-input-port}. + + +@quotation +@emph{Rationale:} +@samp{Char-ready?} exists to make it possible for a program to +accept characters from interactive ports without getting stuck waiting for +input. Any input editors associated with such ports must ensure that +characters whose existence has been asserted by @samp{char-ready?} cannot +be rubbed out. If @samp{char-ready?} were to return @t{#f} at end of +file, a port at end of file would be indistinguishable from an interactive +port that has no ready characters. +@end quotation + +@end deffn + + +@node Output, System interface, Input, Input and output +@subsection Output + + + +@c We've got to put something here to fix the indentation!! + +@noindent + @w{} +@sp 5 + + +@deffn {library procedure} write obj +@deffnx {library procedure} write obj port + +Writes a written representation of @var{obj} to the given @var{port}. Strings +that appear in the written representation are enclosed in doublequotes, and +within those strings backslash and doublequote characters are +escaped by backslashes. +Character objects are written using the @samp{#\} notation. +@samp{Write} returns an unspecified value. The +@var{port} argument may be omitted, in which case it defaults to the value +returned by @samp{current-output-port}. + +@end deffn + + + +@deffn {library procedure} display obj +@deffnx {library procedure} display obj port + +Writes a representation of @var{obj} to the given @var{port}. Strings +that appear in the written representation are not enclosed in +doublequotes, and no characters are escaped within those strings. Character +objects appear in the representation as if written by @samp{write-char} +instead of by @samp{write}. @samp{Display} returns an unspecified value. +The @var{port} argument may be omitted, in which case it defaults to the +value returned by @samp{current-output-port}. + + +@quotation +@emph{Rationale:} +@samp{Write} is intended +for producing mach@-ine-readable output and @samp{display} is for producing +human-readable output. Implementations that allow ``slashification'' +within symbols will probably want @samp{write} but not @samp{display} to +slashify funny characters in symbols. +@end quotation + +@end deffn + + + +@deffn {library procedure} newline +@deffnx {library procedure} newline port + +Writes an end of line to @var{port}. Exactly how this is done differs +from one operating system to another. Returns an unspecified value. +The @var{port} argument may be omitted, in which case it defaults to the +value returned by @samp{current-output-port}. + +@end deffn + + + +@deffn {procedure} write-char char +@deffnx {procedure} write-char char port + +Writes the character @var{char} (not an external representation of the +character) to the given @var{port} and returns an unspecified value. The +@var{port} argument may be omitted, in which case it defaults to the value +returned by @samp{current-output-port}. + +@end deffn + + +@node System interface, , Output, Input and output +@subsection System interface + + +Questions of system interface generally fall outside of the domain of this +report. However, the following operations are important enough to +deserve description here. + + + +@deffn {optional procedure} load filename + +@ignore todo +Fix +@end ignore + + +@c \domain{\var{Filename} should be a string naming an existing file +@c containing Scheme source code.} The {\cf load} procedure reads +@var{Filename} should be a string naming an existing file +containing Scheme source code. The @samp{load} procedure reads +expressions and definitions from the file and evaluates them +sequentially. It is unspecified whether the results of the expressions +are printed. The @samp{load} procedure does not affect the values +returned by @samp{current-input-port} and @samp{current-output-port}. +@samp{Load} returns an unspecified value. + + +@quotation +@emph{Rationale:} +For portability, @samp{load} must operate on source files. +Its operation on other kinds of files necessarily varies among +implementations. +@end quotation + +@end deffn + + + +@deffn {optional procedure} transcript-on filename +@deffnx {optional procedure} transcript-off + +@var{Filename} must be a string naming an output file to be +created. The effect of @samp{transcript-on} is to open the named file +for output, and to cause a transcript of subsequent interaction between +the user and the Scheme system to be written to the file. The +transcript is ended by a call to @samp{transcript-off}, which closes the +transcript file. Only one transcript may be in progress at any time, +though some implementations may relax this restriction. The values +returned by these procedures are unspecified. + +@c \begin{note} +@c These procedures are redundant in some systems, but +@c systems that need them should provide them. +@c \end{note} +@end deffn + +@page + +@c @include{syn} +@node Formal syntax and semantics, Notes, Standard procedures, top +@chapter Formal syntax and semantics + +@menu +* Formal syntax:: +* Formal semantics:: +* Derived expression type:: +@end menu + + + +This chapter provides formal descriptions of what has already been +described informally in previous chapters of this report. + +@ignore todo +Allow grammar to say that else clause needn't be last? +@end ignore + + + +@node Formal syntax, Formal semantics, Formal syntax and semantics, Formal syntax and semantics +@section Formal syntax + +@menu +* Lexical structure:: +* External representation:: +* Expression:: +* Quasiquotations:: +* Transformers:: +* Programs and definitions:: +@end menu + + + +This section provides a formal syntax for Scheme written in an extended +BNF. + +All spaces in the grammar are for legibility. Case is insignificant; +for example, @samp{#x1A} and @samp{#X1a} are equivalent. <empty> +stands for the empty string. + +The following extensions to BNF are used to make the description more +concise: <thing>* means zero or more occurrences of +<thing>; and <thing>+ means at least one +<thing>. + + +@node Lexical structure, External representation, Formal syntax, Formal syntax +@subsection Lexical structure + + +This section describes how individual tokens (identifiers, +@cindex @w{token} +numbers, etc.) are formed from sequences of characters. The following +sections describe how expressions and programs are formed from sequences +of tokens. + +<Intertoken space> may occur on either side of any token, but not +within a token. + +Tokens which require implicit termination (identifiers, numbers, +characters, and dot) may be terminated by any <delimiter>, but not +necessarily by anything else. + +The following five characters are reserved for future extensions to the +language: @t{[ ] @{ @} |} + + +@format +@t{<token> --> <identifier> | <boolean> | <number> +@cindex @w{identifier} + | <character> | <string> + | ( | ) | #( | @t{'} | @t{`} | , | ,@@ | @b{.} +<delimiter> --> <whitespace> | ( | ) | " | ; +<whitespace> --> <space or newline> +<comment> --> ; <@r{all subsequent characters up to a} + @r{line break>} +@cindex @w{comment} +<atmosphere> --> <whitespace> | <comment> +<intertoken space> --> <atmosphere>*} + +@end format + + + + + + +@c This is a kludge, but \multicolumn doesn't work in tabbing environments. + + + +@format +@t{<identifier> --> <initial> <subsequent>* + | <peculiar identifier> +<initial> --> <letter> | <special initial> +<letter> --> a | b | c | ... | z + +<special initial> --> ! | $ | % | & | * | / | : | < | = + | > | ? | ^ | _ | ~ +<subsequent> --> <initial> | <digit> + | <special subsequent> +<digit> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 +<special subsequent> --> + | - | .@: | @@ +<peculiar identifier> --> + | - | ... +<syntactic keyword> --> <expression keyword> +@cindex @w{syntactic keyword} +@cindex @w{keyword} + | else | => | define + | unquote | unquote-splicing +<expression keyword> --> quote | lambda | if + | set! | begin | cond | and | or | case + | let | let* | letrec | do | delay + | quasiquote + +@w{@samp{<variable> @result{} <}}@r{any <identifier> that isn't} +@cindex @w{variable} + @w{ @r{also a <syntactic keyword>>}} + +<boolean> --> #t | #f +<character> --> #\ <any character> + | #\ <character name> +<character name> --> space | newline + +<string> --> " <string element>* " +<string element> --> <any character other than " or \> + | \" | \\ } + +@end format + + + + + + + +@format +@t{<number> --> <num 2>| <num 8> + | <num 10>| <num 16> +} + +@end format + + + +The following rules for <num R>, <complex R>, <real +R>, <ureal R>, <uinteger R>, and <prefix R> +should be replicated for @w{R = 2, 8, 10,} +and 16. There are no rules for <decimal 2>, <decimal +8>, and <decimal 16>, which means that numbers containing +decimal points or exponents must be in decimal radix. +@ignore todo +Mark Meyer and David Bartley want to fix this. (What? -- Will) +@end ignore + + + +@format +@t{<num R> --> <prefix R> <complex R> +<complex R> --> <real R> | <real R> @@ <real R> + | <real R> + <ureal R> i | <real R> - <ureal R> i + | <real R> + i | <real R> - i + | + <ureal R> i | - <ureal R> i | + i | - i +<real R> --> <sign> <ureal R> +<ureal R> --> <uinteger R> + | <uinteger R> / <uinteger R> + | <decimal R> +<decimal 10> --> <uinteger 10> <suffix> + | . <digit 10>+ #* <suffix> + | <digit 10>+ . <digit 10>* #* <suffix> + | <digit 10>+ #+ . #* <suffix> +<uinteger R> --> <digit R>+ #* +<prefix R> --> <radix R> <exactness> + | <exactness> <radix R> +} + +@end format + + + + +@format +@t{<suffix> --> <empty> + | <exponent marker> <sign> <digit 10>+ +<exponent marker> --> e | s | f | d | l +<sign> --> <empty> | + | - +<exactness> --> <empty> | #i | #e +@vindex #e +@vindex #i +<radix 2> --> #b +@vindex #b +<radix 8> --> #o +@vindex #o +<radix 10> --> <empty> | #d +<radix 16> --> #x +@vindex #x +<digit 2> --> 0 | 1 +<digit 8> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 +<digit 10> --> <digit> +<digit 16> --> <digit 10> | a | b | c | d | e | f } + +@end format + + + +@ignore todo +Mark Meyer of TI sez, shouldn't we allow @t{1e3/2}? +@end ignore + + + +@node External representation, Expression, Lexical structure, Formal syntax +@subsection External representations + + + +<Datum> is what the @code{read} procedure (section @pxref{Input}) +@vindex @w{read} +successfully parses. Note that any string that parses as an +<ex@-pres@-sion> will also parse as a <datum>. + + +@format +@t{<datum> --> <simple datum> | <compound datum> +<simple datum> --> <boolean> | <number> + | <character> | <string> | <symbol> +<symbol> --> <identifier> +<compound datum> --> <list> | <vector> +<list> --> (<datum>*) | (<datum>+ .@: <datum>) + | <abbreviation> +<abbreviation> --> <abbrev prefix> <datum> +<abbrev prefix> --> ' | ` | , | ,@@ +<vector> --> #(<datum>*) } + +@end format + + + + +@node Expression, Quasiquotations, External representation, Formal syntax +@subsection Expressions + + + +@format +@t{<expression> --> <variable> + | <literal> + | <procedure call> + | <lambda expression> + | <conditional> + | <assignment> + | <derived expression> + | <macro use> + | <macro block> + +<literal> --> <quotation> | <self-evaluating> +<self-evaluating> --> <boolean> | <number> + | <character> | <string> +<quotation> --> '<datum> | (quote <datum>) +<procedure call> --> (<operator> <operand>*) +<operator> --> <expression> +<operand> --> <expression> + +<lambda expression> --> (lambda <formals> <body>) +<formals> --> (<variable>*) | <variable> + | (<variable>+ .@: <variable>) +<body> --> <definition>* <sequence> +<sequence> --> <command>* <expression> +<command> --> <expression> + +<conditional> --> (if <test> <consequent> <alternate>) +<test> --> <expression> +<consequent> --> <expression> +<alternate> --> <expression> | <empty> + +<assignment> --> (set! <variable> <expression>) + +<derived expression> --> + (cond <cond clause>+) + | (cond <cond clause>* (else <sequence>)) + | (case <expression> + <case clause>+) + | (case <expression> + <case clause>* + (else <sequence>)) + | (and <test>*) + | (or <test>*) + | (let (<binding spec>*) <body>) + | (let <variable> (<binding spec>*) <body>) + | (let* (<binding spec>*) <body>) + | (letrec (<binding spec>*) <body>) + | (begin <sequence>) + | (do (<iteration spec>*) + (<test> <do result>) + <command>*) + | (delay <expression>) + | <quasiquotation> + +<cond clause> --> (<test> <sequence>) + | (<test>) + | (<test> => <recipient>) +<recipient> --> <expression> +<case clause> --> ((<datum>*) <sequence>) +<binding spec> --> (<variable> <expression>) +<iteration spec> --> (<variable> <init> <step>) + | (<variable> <init>) +<init> --> <expression> +<step> --> <expression> +<do result> --> <sequence> | <empty> + +<macro use> --> (<keyword> <datum>*) +<keyword> --> <identifier> + +<macro block> --> + (let-syntax (<syntax spec>*) <body>) + | (letrec-syntax (<syntax spec>*) <body>) +<syntax spec> --> (<keyword> <transformer spec>) + +} + +@end format + + + +@node Quasiquotations, Transformers, Expression, Formal syntax +@subsection Quasiquotations + + +The following grammar for quasiquote expressions is not context-free. +It is presented as a recipe for generating an infinite number of +production rules. Imagine a copy of the following rules for D = 1, 2,3, @dots{}. D keeps track of the nesting depth. + + +@format +@t{<quasiquotation> --> <quasiquotation 1> +<qq template 0> --> <expression> +<quasiquotation D> --> `<qq template D> + | (quasiquote <qq template D>) +<qq template D> --> <simple datum> + | <list qq template D> + | <vector qq template D> + | <unquotation D> +<list qq template D> --> (<qq template or splice D>*) + | (<qq template or splice D>+ .@: <qq template D>) + | '<qq template D> + | <quasiquotation D+1> +<vector qq template D> --> #(<qq template or splice D>*) +<unquotation D> --> ,<qq template D-1> + | (unquote <qq template D-1>) +<qq template or splice D> --> <qq template D> + | <splicing unquotation D> +<splicing unquotation D> --> ,@@<qq template D-1> + | (unquote-splicing <qq template D-1>) } + +@end format + + + +In <quasiquotation>s, a <list qq template D> can sometimes +be confused with either an <un@-quota@-tion D> or a <splicing +un@-quo@-ta@-tion D>. The interpretation as an +<un@-quo@-ta@-tion> or <splicing +un@-quo@-ta@-tion D> takes precedence. + +@node Transformers, Programs and definitions, Quasiquotations, Formal syntax +@subsection Transformers + + + +@format +@t{<transformer spec> --> + (syntax-rules (<identifier>*) <syntax rule>*) +<syntax rule> --> (<pattern> <template>) +<pattern> --> <pattern identifier> + | (<pattern>*) + | (<pattern>+ . <pattern>) + | (<pattern>* <pattern> <ellipsis>) + | #(<pattern>*) + | #(<pattern>* <pattern> <ellipsis>) + | <pattern datum> +<pattern datum> --> <string> + | <character> + | <boolean> + | <number> +<template> --> <pattern identifier> + | (<template element>*) + | (<template element>+ . <template>) + | #(<template element>*) + | <template datum> +<template element> --> <template> + | <template> <ellipsis> +<template datum> --> <pattern datum> +<pattern identifier> --> <any identifier except @samp{...}> +<ellipsis> --> <the identifier @samp{...}> +} + +@end format + + + +@node Programs and definitions, , Transformers, Formal syntax +@subsection Programs and definitions + + + +@format +@t{<program> --> <command or definition>* +<command or definition> --> <command> + | <definition> + | <syntax definition> + | (begin <command or definition>+) +<definition> --> (define <variable> <expression>) + | (define (<variable> <def formals>) <body>) + | (begin <definition>*) +<def formals> --> <variable>* + | <variable>* .@: <variable> +<syntax definition> --> + (define-syntax <keyword> <transformer spec>) +} + +@end format + + + +@node Formal semantics, Derived expression type, Formal syntax, Formal syntax and semantics +@section Formal semantics + + +This section provides a formal denotational semantics for the primitive +expressions of Scheme and selected built-in procedures. The concepts +and notation used here are described in @sc{[Stoy77]}. + +@quotation +@emph{Note:} The formal semantics section was written in La@TeX{} which +is incompatible with @TeX{}info. See the Formal semantics section of +the original document from which this was derived. +@end quotation + + +@c @include{derive} +@node Derived expression type, , Formal semantics, Formal syntax and semantics +@section Derived expression types + + + +This section gives macro definitions for the derived expression types in +terms of the primitive expression types (literal, variable, call, @samp{lambda}, +@samp{if}, @samp{set!}). See section @ref{Control features} for a possible +definition of @samp{delay}. + + +@example + +(define-syntax cond + (syntax-rules (else =>) + ((cond (else result1 result2 ...)) + (begin result1 result2 ...)) + ((cond (test => result)) + (let ((temp test)) + (if temp (result temp)))) + ((cond (test => result) clause1 clause2 ...) + (let ((temp test)) + (if temp + (result temp) + (cond clause1 clause2 ...)))) + ((cond (test)) test) + ((cond (test) clause1 clause2 ...) + (let ((temp test)) + (if temp + temp + (cond clause1 clause2 ...)))) + ((cond (test result1 result2 ...)) + (if test (begin result1 result2 ...))) + ((cond (test result1 result2 ...) + clause1 clause2 ...) + (if test + (begin result1 result2 ...) + (cond clause1 clause2 ...))))) + +@end example + + + +@example + +(define-syntax case + (syntax-rules (else) + ((case (key ...) + clauses ...) + (let ((atom-key (key ...))) + (case atom-key clauses ...))) + ((case key + (else result1 result2 ...)) + (begin result1 result2 ...)) + ((case key + ((atoms ...) result1 result2 ...)) + (if (memv key '(atoms ...)) + (begin result1 result2 ...))) + ((case key + ((atoms ...) result1 result2 ...) + clause clauses ...) + (if (memv key '(atoms ...)) + (begin result1 result2 ...) + (case key clause clauses ...))))) + +@end example + + + +@example + +(define-syntax and + (syntax-rules () + ((and) #t) + ((and test) test) + ((and test1 test2 ...) + (if test1 (and test2 ...) #f)))) + +@end example + + + +@example + +(define-syntax or + (syntax-rules () + ((or) #f) + ((or test) test) + ((or test1 test2 ...) + (let ((x test1)) + (if x x (or test2 ...)))))) + +@end example + + + +@example + +(define-syntax let + (syntax-rules () + ((let ((name val) ...) body1 body2 ...) + ((lambda (name ...) body1 body2 ...) + val ...)) + ((let tag ((name val) ...) body1 body2 ...) + ((letrec ((tag (lambda (name ...) + body1 body2 ...))) + tag) + val ...)))) + +@end example + + + +@example + +(define-syntax let* + (syntax-rules () + ((let* () body1 body2 ...) + (let () body1 body2 ...)) + ((let* ((name1 val1) (name2 val2) ...) + body1 body2 ...) + (let ((name1 val1)) + (let* ((name2 val2) ...) + body1 body2 ...))))) + +@end example + + +The following @samp{letrec} macro uses the symbol @samp{<undefined>} +in place of an expression which returns something that when stored in +a location makes it an error to try to obtain the value stored in the +location (no such expression is defined in Scheme). +A trick is used to generate the temporary names needed to avoid +specifying the order in which the values are evaluated. +This could also be accomplished by using an auxiliary macro. + + +@example + +(define-syntax letrec + (syntax-rules () + ((letrec ((var1 init1) ...) body ...) + (letrec "generate temp names" + (var1 ...) + () + ((var1 init1) ...) + body ...)) + ((letrec "generate temp names" + () + (temp1 ...) + ((var1 init1) ...) + body ...) + (let ((var1 <undefined>) ...) + (let ((temp1 init1) ...) + (set! var1 temp1) + ... + body ...))) + ((letrec "generate temp names" + (x y ...) + (temp ...) + ((var1 init1) ...) + body ...) + (letrec "generate temp names" + (y ...) + (newtemp temp ...) + ((var1 init1) ...) + body ...)))) + +@end example + + + +@example + +(define-syntax begin + (syntax-rules () + ((begin exp ...) + ((lambda () exp ...))))) + +@end example + + +The following alternative expansion for @samp{begin} does not make use of +the ability to write more than one expression in the body of a lambda +expression. In any case, note that these rules apply only if the body +of the @samp{begin} contains no definitions. + + +@example + +(define-syntax begin + (syntax-rules () + ((begin exp) + exp) + ((begin exp1 exp2 ...) + (let ((x exp1)) + (begin exp2 ...))))) + +@end example + + +The following definition +of @samp{do} uses a trick to expand the variable clauses. +As with @samp{letrec} above, an auxiliary macro would also work. +The expression @samp{(if #f #f)} is used to obtain an unspecific +value. + + +@example + +(define-syntax do + (syntax-rules () + ((do ((var init step ...) ...) + (test expr ...) + command ...) + (letrec + ((loop + (lambda (var ...) + (if test + (begin + (if #f #f) + expr ...) + (begin + command + ... + (loop (do "step" var step ...) + ...)))))) + (loop init ...))) + ((do "step" x) + x) + ((do "step" x y) + y))) + +@end example + + +@c `a = Q_1[a] +@c `(a b c ... . z) = `(a . (b c ...)) +@c `(a . b) = (append Q*_0[a] `b) +@c `(a) = Q*_0[a] +@c Q*_0[a] = (list 'a) +@c Q*_0[,a] = (list a) +@c Q*_0[,@a] = a +@c Q*_0[`a] = (list 'quasiquote Q*_1[a]) +@c `#(a b ...) = (list->vector `(a b ...)) +@c ugh. + +@page + +@c @include{notes} +@node Notes, Additional material, Formal syntax and semantics, top +@unnumbered Notes + +@menu +* Language changes:: +@end menu + + + +@ignore todo +Perhaps this section should be made to disappear. +Can these remarks be moved somewhere else? +@end ignore + + +@node Language changes, , Notes, Notes +@unnumberedsec Language changes + + + +This section enumerates the changes that have been made to Scheme since +the ``Revised^4 report'' [R4RS] was published. + + + +@itemize @bullet + + +@item +The report is now a superset of the IEEE standard for Scheme +[IEEEScheme]: implementations that conform to the report will +also conform to the standard. This required the following changes: + + +@itemize @bullet + + +@item +The empty list is now required to count as true. + +@item +The classification of features as essential or inessential has been +removed. There are now three classes of built-in procedures: primitive, +library, and optional. The optional procedures are @samp{load}, +@samp{with-input-from-file}, @samp{with-output-to-file}, +@samp{transcript-on}, @samp{transcript-off}, and +@samp{interaction-environment}, +and @samp{-} and @samp{/} with more than two arguments. +None of these are in the IEEE standard. + +@item +Programs are allowed to redefine built-in procedures. Doing so +will not change the behavior of other built-in procedures. + +@end itemize + + +@item +@emph{Port} has been added to the list of disjoint types. + +@item +The macro appendix has been removed. High-level macros are now part +of the main body of the report. The rewrite rules for derived expressions +have been replaced with macro definitions. There are no reserved identifiers. + +@item +@samp{Syntax-rules} now allows vector patterns. + +@item +Multiple-value returns, @samp{eval}, and @samp{dynamic-wind} have +been added. + +@item +The calls that are required to be implemented in a properly tail-recursive +fashion are defined explicitly. + +@item +`@samp{@@}' can be used within identifiers. `@samp{|}' is reserved +for possible future extensions. + + +@end itemize + + +@c %R4%% +@c \subsection*{Keywords as variable names} + +@c Some implementations allow arbitrary syntactic +@c keywords \index{keyword}\index{syntactic keyword}to be used as variable +@c names, instead of reserving them, as this report would have +@c it.\index{variable} But this creates ambiguities in the interpretation +@c of expressions: for example, in the following, it's not clear whether +@c the expression {\tt (if 1 2 3)} should be treated as a procedure call or +@c as a conditional. + +@c \begin{scheme} +@c (define if list) +@c (if 1 2 3) \ev 2 {\em{}or} (1 2 3)% +@c \end{scheme} + +@c These ambiguities are usually resolved in some consistent way within any +@c given implementation, but no particular treatment stands out as being +@c clearly superior to any other, so these situations were excluded for the +@c purposes of this report. + +@c %R4%% +@c \subsection*{Macros} + +@c Scheme does not have any standard facility for defining new kinds of +@c expressions.\index{macros} + +@c \vest The ability to alter the syntax of the language creates +@c numerous problems. All current implementations of Scheme have macro +@c facilities that solve those problems to one degree or another, but the +@c solutions are quite different and it isn't clear at this time which +@c solution is best, or indeed whether any of the solutions are truly +@c adequate. Rather than standardize, we are encouraging implementations +@c to continue to experiment with different solutions. + +@c \vest The main problems with traditional macros are: They must be +@c defined to the system before any code using them is loaded; this is a +@c common source of obscure bugs. They are usually global; macros can be +@c made to follow lexical scope rules \todo{flushed: ``as in Common +@c Lisp's {\tt macrolet}''; OK?}, but many people find the resulting scope rules +@c confusing. Unless they are written very carefully, macros are +@c vulnerable to inadvertent capture of free variables; to get around this, +@c for example, macros may have to generate code in which procedure values +@c appear as quoted constants. There is a similar problem with syntactic +@c keywords if the keywords of special forms are not reserved. If keywords +@c are reserved, then either macros introduce new reserved words, +@c invalidating old code, or else special forms defined by the programmer +@c do not have the same status as special forms defined by the system. + +@c \todo{Refer to Pitman's special forms paper.} +@c \todo{Pitman sez: Discuss importance of having a small number of special forms +@c so that programs can inspect each other.} + +@ignore todo +Move cwcc history back here? --- Andy Cromarty is concerned about +confusion over who the audience is. +@end ignore + + +@ignore todo +Cromarty: +23. NOTES, p.35ff.: This material should stay somehow. We need to + make it clear that R^3 Scheme is not being touted as Yet Another + Ultimate Solution To The Programming Language Problem, but rather + as a snapshot of a *process* of good design, for which not all + answers have yet been found. We also ought to use the opportunity + for publicity afforded us by SIGPLAN to advertise some of the thorny + unsolved problems that need further research, and encourage + language designers to work on them. +@end ignore + + +@c @include{repository} +@node Additional material, Example, Notes, top +@unnumbered Additional material + + +The Internet Scheme Repository at + +@center +@center @url{http://www.cs.indiana.edu/scheme-repository/} +@center + +contains an extensive Scheme bibliography, as well as papers, +programs, implementations, and other material related to Scheme. + +@page + +@c @include{example} + +@node Example, Bibliography, Additional material, top +@unnumbered Example + +@c -*- Mode: Lisp; Package: SCHEME; Syntax: Common-lisp -*- + + +@samp{Integrate-system} integrates the system + + +@center y_k^^ = f_k(y_1, y_2, @dots{}, y_n), k = 1, @dots{}, n + +of differential equations with the method of Runge-Kutta. + +The parameter @t{system-derivative} is a function that takes a system +state (a vector of values for the state variables y_1, @dots{}, y_n) +and produces a system derivative (the values y_1^^, @dots{},y_n^^). The parameter @t{initial-state} provides an initial +system state, and @t{h} is an initial guess for the length of the +integration step. + +The value returned by @samp{integrate-system} is an infinite stream of +system states. + + +@example + +(define integrate-system + (lambda (system-derivative initial-state h) + (let ((next (runge-kutta-4 system-derivative h))) + (letrec ((states + (cons initial-state + (delay (map-streams next + states))))) + states)))) + +@end example + + +@samp{Runge-Kutta-4} takes a function, @t{f}, that produces a +system derivative from a system state. @samp{Runge-Kutta-4} +produces a function that takes a system state and +produces a new system state. + + +@example + +(define runge-kutta-4 + (lambda (f h) + (let ((*h (scale-vector h)) + (*2 (scale-vector 2)) + (*1/2 (scale-vector (/ 1 2))) + (*1/6 (scale-vector (/ 1 6)))) + (lambda (y) + ;; y @r{}is a system state + (let* ((k0 (*h (f y))) + (k1 (*h (f (add-vectors y (*1/2 k0))))) + (k2 (*h (f (add-vectors y (*1/2 k1))))) + (k3 (*h (f (add-vectors y k2))))) + (add-vectors y + (*1/6 (add-vectors k0 + (*2 k1) + (*2 k2) + k3)))))))) +@c |--------------------------------------------------| + +(define elementwise + (lambda (f) + (lambda vectors + (generate-vector + (vector-length (car vectors)) + (lambda (i) + (apply f + (map (lambda (v) (vector-ref v i)) + vectors))))))) + +@c |--------------------------------------------------| +(define generate-vector + (lambda (size proc) + (let ((ans (make-vector size))) + (letrec ((loop + (lambda (i) + (cond ((= i size) ans) + (else + (vector-set! ans i (proc i)) + (loop (+ i 1))))))) + (loop 0))))) + +(define add-vectors (elementwise +)) + +(define scale-vector + (lambda (s) + (elementwise (lambda (x) (* x s))))) + +@end example + + +@samp{Map-streams} is analogous to @samp{map}: it applies its first +argument (a procedure) to all the elements of its second argument (a +stream). + + +@example + +(define map-streams + (lambda (f s) + (cons (f (head s)) + (delay (map-streams f (tail s)))))) + +@end example + + +Infinite streams are implemented as pairs whose car holds the first +element of the stream and whose cdr holds a promise to deliver the rest +of the stream. + + +@example + +(define head car) +(define tail + (lambda (stream) (force (cdr stream)))) + +@end example + + +@sp 6 +The following illustrates the use of @samp{integrate-system} in +integrating the system + + +@center C dv_C / dt = -i_L - v_C / R + + + +@center L di_L / dt = v_C + +which models a damped oscillator. + + +@example + +(define damped-oscillator + (lambda (R L C) + (lambda (state) + (let ((Vc (vector-ref state 0)) + (Il (vector-ref state 1))) + (vector (- 0 (+ (/ Vc (* R C)) (/ Il C))) + (/ Vc L)))))) + +(define the-states + (integrate-system + (damped-oscillator 10000 1000 .001) + '#(1 0) + .01)) + +@end example + + +@ignore todo +Show some output? +@end ignore + + +@c (letrec ((loop (lambda (s) +@c (newline) +@c (write (head s)) +@c (loop (tail s))))) +@c (loop the-states)) + +@c #(1 0) +@c #(0.99895054 9.994835e-6) +@c #(0.99780226 1.9978681e-5) +@c #(0.9965554 2.9950552e-5) +@c #(0.9952102 3.990946e-5) +@c #(0.99376684 4.985443e-5) +@c #(0.99222565 5.9784474e-5) +@c #(0.9905868 6.969862e-5) +@c #(0.9888506 7.9595884e-5) +@c #(0.9870173 8.94753e-5) + +@page + +@c \newpage % Put bib on it's own page (it's just one) +@c \twocolumn[\vspace{-.18in}]% Last bib item was on a page by itself. +@c \renewcommand{\bibname}{References} +@c @include{bib} + +@c My reference for proper reference format is: +@c Mary-Claire van Leunen. +@c {\em A Handbook for Scholars.} +@c Knopf, 1978. +@c I think the references list would look better in ``open'' format, +@c i.e. with the three blocks for each entry appearing on separate +@c lines. I used the compressed format for SIGPLAN in the interest of +@c space. In open format, when a block runs over one line, +@c continuation lines should be indented; this could probably be done +@c using some flavor of latex list environment. Maybe the right thing +@c to do in the long run would be to convert to Bibtex, which probably +@c does the right thing, since it was implemented by one of van +@c Leunen's colleagues at DEC SRC. +@c -- Jonathan + +@c I tried to follow Jonathan's format, insofar as I understood it. +@c I tried to order entries lexicographically by authors (with singly +@c authored papers first), then by date. +@c In some cases I replaced a technical report or conference paper +@c by a subsequent journal article, but I think there are several +@c more such replacements that ought to be made. +@c -- Will, 1991. + +@c This is just a personal remark on your question on the RRRS: +@c The language CUCH (Curry-Church) was implemented by 1964 and +@c is a practical version of the lambda-calculus (call-by-name). +@c One reference you may find in Formal Language Description Languages +@c for Computer Programming T.~B.~Steele, 1965 (or so). +@c -- Matthias Felleisen + +@c Rather than try to keep the bibliography up-to-date, which is hopeless +@c given the time between updates, I replaced the bulk of the references +@c with a pointer to the Scheme Repository. Ozan Yigit's bibliography in +@c the repository is a superset of the R4RS one. +@c The bibliography now contains only items referenced within the report. +@c -- Richard, 1996. + +@node Bibliography, Index, Example, top +@unnumbered Bibliography + + +@itemize @bullet +@c 999 + + +@item [SICP] +@pindex SICP +Harold Abelson and Gerald Jay Sussman with Julie Sussman. +@emph{Structure and Interpretation of Computer Programs, second edition.} +MIT Press, Cambridge, 1996. + +@item [Bawden88] +@c new +Alan Bawden and Jonathan Rees. +@pindex Bawden88 +Syntactic closures. +In @emph{Proceedings of the 1988 ACM Symposium on Lisp and + Functional Programming}, pages 86--95. + +@item [howtoprint] +@pindex howtoprint +Robert G. Burger and R. Kent Dybvig. +Printing floating-point numbers quickly and accurately. +In @emph{Proceedings of the ACM SIGPLAN '96 Conference + on Programming Language Design and Implementation}, pages 108--116. + +@item [RRRS] +@pindex RRRS +William Clinger, editor. +The revised revised report on Scheme, or an uncommon Lisp. +MIT Artificial Intelligence Memo 848, August 1985. +Also published as Computer Science Department Technical Report 174, + Indiana University, June 1985. + +@item [howtoread] +@c new +William Clinger. +@pindex howtoread +How to read floating point numbers accurately. +In @emph{Proceedings of the ACM SIGPLAN '90 Conference + on Programming Language Design and Implementation}, pages 92--101. +Proceedings published as @emph{SIGPLAN Notices} 25(6), June 1990. + +@item [R4RS] +@pindex R4RS +William Clinger and Jonathan Rees, editors. +The revised^4 report on the algorithmic language Scheme. +In @emph{ACM Lisp Pointers} 4(3), pages 1--55, 1991. + +@item [macrosthatwork] +@c new +William Clinger and Jonathan Rees. +@pindex macrosthatwork +Macros that work. +In @emph{Proceedings of the 1991 ACM Conference on Principles of + Programming Languages}, pages 155--162. + +@item [propertailrecursion] +@c new +William Clinger. +@pindex propertailrecursion +Proper Tail Recursion and Space Efficiency. +To appear in @emph{Proceedings of the 1998 ACM Conference on Programming + Language Design and Implementation}, June 1998. + +@item [syntacticabstraction] +@pindex syntacticabstraction +R. Kent Dybvig, Robert Hieb, and Carl Bruggeman. +Syntactic abstraction in Scheme. +@emph{Lisp and Symbolic Computation} 5(4):295--326, 1993. + +@item [Scheme311] +@pindex Scheme311 +Carol Fessenden, William Clinger, Daniel P. Friedman, and Christopher Haynes. +Scheme 311 version 4 reference manual. +Indiana University Computer Science Technical Report 137, February 1983. +Superseded by [Scheme84]. + +@item [Scheme84] +@pindex Scheme84 +D. Friedman, C. Haynes, E. Kohlbecker, and M. Wand. +Scheme 84 interim reference manual. +Indiana University Computer Science Technical Report 153, January 1985. + +@item [IEEE] +@pindex IEEE +@emph{IEEE Standard 754-1985. IEEE Standard for Binary Floating-Point +Arithmetic.} IEEE, New York, 1985. + +@item [IEEEScheme] +@pindex IEEEScheme +@emph{IEEE Standard 1178-1990. IEEE Standard for the Scheme + Programming Language.} IEEE, New York, 1991. + +@item [Kohlbecker86] +@pindex Kohlbecker86 +Eugene E. Kohlbecker Jr. +@emph{Syntactic Extensions in the Programming Language Lisp.} +PhD thesis, Indiana University, August 1986. + +@item [hygienic] +@pindex hygienic +Eugene E. Kohlbecker Jr., Daniel P. Friedman, Matthias Felleisen, and Bruce Duba. +Hygienic macro expansion. +In @emph{Proceedings of the 1986 ACM Conference on Lisp + and Functional Programming}, pages 151--161. + +@item [Landin65] +@pindex Landin65 +Peter Landin. +A correspondence between Algol 60 and Church's lambda notation: Part I. +@emph{Communications of the ACM} 8(2):89--101, February 1965. + +@item [MITScheme] +@pindex MITScheme +MIT Department of Electrical Engineering and Computer Science. +Scheme manual, seventh edition. +September 1984. + +@item [Naur63] +@pindex Naur63 +Peter Naur et al. +Revised report on the algorithmic language Algol 60. +@emph{Communications of the ACM} 6(1):1--17, January 1963. + +@item [Penfield81] +@pindex Penfield81 +Paul Penfield, Jr. +Principal values and branch cuts in complex APL. +In @emph{APL '81 Conference Proceedings,} pages 248--256. +ACM SIGAPL, San Francisco, September 1981. +Proceedings published as @emph{APL Quote Quad} 12(1), ACM, September 1981. + +@item [Pitman83] +@pindex Pitman83 +Kent M. Pitman. +The revised MacLisp manual (Saturday evening edition). +MIT Laboratory for Computer Science Technical Report 295, May 1983. + +@item [Rees82] +@pindex Rees82 +Jonathan A. Rees and Norman I. Adams IV. +T: A dialect of Lisp or, lambda: The ultimate software tool. +In @emph{Conference Record of the 1982 ACM Symposium on Lisp and + Functional Programming}, pages 114--122. + +@item [Rees84] +@pindex Rees84 +Jonathan A. Rees, Norman I. Adams IV, and James R. Meehan. +The T manual, fourth edition. +Yale University Computer Science Department, January 1984. + +@item [R3RS] +@pindex R3RS +Jonathan Rees and William Clinger, editors. +The revised^3 report on the algorithmic language Scheme. +In @emph{ACM SIGPLAN Notices} 21(12), pages 37--79, December 1986. + +@item [Reynolds72] +@pindex Reynolds72 +John Reynolds. +Definitional interpreters for higher order programming languages. +In @emph{ACM Conference Proceedings}, pages 717--740. +ACM, +@ignore todo +month? +@end ignore + 1972. + +@item [Scheme78] +@pindex Scheme78 +Guy Lewis Steele Jr. and Gerald Jay Sussman. +The revised report on Scheme, a dialect of Lisp. +MIT Artificial Intelligence Memo 452, January 1978. + +@item [Rabbit] +@pindex Rabbit +Guy Lewis Steele Jr. +Rabbit: a compiler for Scheme. +MIT Artificial Intelligence Laboratory Technical Report 474, May 1978. + +@item [CLtL] +@pindex CLtL +Guy Lewis Steele Jr. +@emph{Common Lisp: The Language, second edition.} +Digital Press, Burlington MA, 1990. + +@item [Scheme75] +@pindex Scheme75 +Gerald Jay Sussman and Guy Lewis Steele Jr. +Scheme: an interpreter for extended lambda calculus. +MIT Artificial Intelligence Memo 349, December 1975. + +@item [Stoy77] +@pindex Stoy77 +Joseph E. Stoy. +@emph{Denotational Semantics: The Scott-Strachey Approach to + Programming Language Theory.} +MIT Press, Cambridge, 1977. + +@item [TImanual85] +@pindex TImanual85 +Texas Instruments, Inc. +TI Scheme Language Reference Manual. +Preliminary version 1.0, November 1985. + +@end itemize + + + + +@page + + +@c Adjustment to avoid having the last index entry on a page by itself. +@c \addtolength{\baselineskip}{-0.1pt} + +@node Index, , Bibliography, top +@unnumbered Alphabetic index of definitions of concepts, keywords, and procedures + + + +The principal entry for each term, procedure, or keyword is listed +first, separated from the other entries by a semicolon. + +@sp 6 + +@unnumberedsec Concepts +@printindex cp +@page +@unnumberedsec Procedures +@printindex fn + +@ifinfo +@unnumberedsec References +@printindex pg +@end ifinfo + + +@contents +@bye diff --git a/doc/recipe-guidelines.txt b/doc/recipe-guidelines.txt new file mode 100644 index 000000000..adf8d5c7d --- /dev/null +++ b/doc/recipe-guidelines.txt @@ -0,0 +1,80 @@ + -*-text-*- + +Guidelines for contributions to the Guile Recipes manual +-------------------------------------------------------- + +1. Licensing + +Contributions must be licensed under the GNU Free Documentation +License (GFDL) or the GNU General Public License (GPL). + +2. Copyright + +Contributors are encouraged, but not required, to assign the copyright +for their contribution to the FSF. `not required' also covers the +case where a contributor has every intention of assigning copyright, +but the process is simply taking a little time. Note that: + +- If you assign your copyright, other people (who have also assigned + copyright) can make non-trivial enhancements to your contribution + without any difficulties arising. If you don't assign copyright for + contribution, it complicates the ownership picture if other people + make non-trivial changes to it; and if the burden of tracking + copyright ownership becomes too great, it will be easier simply to + remove that contribution from the manual. + +- If it transpires that non-assigned copyrights turn out to be a bad + thing (for whatever reason), the maintainers reserve the right to + remove non-assigned contributions from the manual. + +3. Manual organization + +Each contribution has its own chapter and lives in its own Texinfo +file. Chapters in related areas may be grouped together, but maybe +not. Instead, the introduction to the manual will contain references +to chapters, and the introductory text will group those references +appropriately. + +4. Copyright ownership + +Given this organization, ownership for copyright purposes is +straightforward. Each Texinfo file is either owned by its +contributor, or assigned to the FSF. + +Every contribution's chapter should begin with a statement of who +contributed it, who owns the copyright, and its license (GFDL or +GPL). These statements should appear in the printed and online +documentation -- i.e. they are _not_ comments. + +5. Documentation vs. code + +Contributed material should be informative and helpful, and should fit +in with the manual syntax. In general, this means that a +straightforward lump of code is _not_ good enough -- it also needs the +statements mentioned above, introduction, explanation or +documentation, Texinfo markup, etc. + +Note that the maintainers may be able to accept a contribution that +requires substantial extra work if copyright for that contribution has +been assigned to the FSF. Where copyright has not been assigned, the +contribution has to be already finished by its author. + +6. Good indexing + +In practice, the manual index will be a very important tool for +someone looking for an example that is useful to them. So please give +some thought to good indexing in your contribution. + +7. Submissions + +To submit material for inclusion in Guile Recipes, please send your +contribution to the guile-sources mailing list +<guile-sources@gnu.org>. + +As far as past material is concerned, I do have an archive of material +that I will ask people about including individually, but it would make +things easier for me if people resubmitted past material to +guile-sources anyway. + +-- +Neil Jerram <neil@ossau.uklinux.net> April 20th 2001 diff --git a/doc/ref/.gitignore b/doc/ref/.gitignore new file mode 100644 index 000000000..7f5689b1f --- /dev/null +++ b/doc/ref/.gitignore @@ -0,0 +1,3 @@ +autoconf-macros.texi +effective-version.texi +guile.html diff --git a/doc/ref/ChangeLog-2008 b/doc/ref/ChangeLog-2008 new file mode 100644 index 000000000..e4ae0b1ae --- /dev/null +++ b/doc/ref/ChangeLog-2008 @@ -0,0 +1,2801 @@ +2008-07-17 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Evaluating Scheme Code): Document use of + `C-u' prefix with evaluation commands. + +2008-07-05 Ludovic Courtès <ludo@gnu.org> + + * api-data.texi (Symbol Primitives): Add `scm_c_symbol_length ()'. + +2008-06-30 Julian Graham <joolean@gmail.com> + + * srfi-modules.texi (SRFI-18): New section. + (SRFI-19 Time): Mention SRFI-18's `current-time'. + +2008-06-28 Ludovic Courtès <ludo@gnu.org> + + * api-modules.texi (Using Guile Modules): Substitute "syntax + transformer" to "system transformer". Reported by Sebastian + Tennant <sebyte@smolny.plus.com>. + +2008-06-01 Ludovic Courtès <ludo@gnu.org> + + * srfi-modules.texi (SRFI-88): Fix URL. + +2008-05-14 Julian Graham <joolean@gmail.com> + + * api-scheduling.texi (Mutexes and Condition Variables): Add + documentation for new functions "scm_mutex_owner", + "scm_mutex_level", and "scm_mutex_locked_p". Update + documentation for function "scm_lock_mutex_timed" to reflect + addition of optional ownership argument. + +2008-05-07 Ludovic Courtès <ludo@gnu.org> + + * Makefile.am (autoconf-macros.texi): Avoid use of GNU Make + specific `$<' variable. This broke with BSD Make as found on + FreeBSD 6.2. + +2008-05-05 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Using Guile in Emacs): Add concept index + entries `GDS' and `Emacs'. + + * api-debug.texi (Debugging): Add concept index entry `Debugging'. + +2008-05-04 Ludovic Courtès <ludo@gnu.org> + + * guile.texi (Guile Modules): Include `autoconf.texi'. + * autoconf.texi (Autoconf Support): Mention `pkg-config'. + (Autoconf Macros): Document `pkg-config' support. + +2008-04-26 Ludovic Courtès <ludo@gnu.org> + + * srfi-modules.texi (SRFI-88): New section. + * api-data.texi (Keyword Read Syntax): Add reference to + `SRFI-88'. + +2008-04-17 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (File System): New doc for file-exists?. + +2008-04-15 Ludovic Courtès <ludo@gnu.org> + + * api-data.texi (Keywords): Mention postfix syntax. + (Keyword Read Syntax): Document `postfix' read option. + * api-options.texi (Reader options): Update examples. + (Examples of option use): Likewise. + +2008-03-28 Neil Jerram <neil@ossau.uklinux.net> + + * libguile-concepts.texi (Multi-Threading): Fix typo. + +2008-03-24 Neil Jerram <neil@ossau.uklinux.net> + + Applying patch from Julian Graham, containing minor fixes to his + thread enhancements: + + * api-scheduling.texi (Mutexes and Condition Variables): Change + `flag' to `flags' in docstring. + +2008-03-19 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Low Level Trap Calls): Removed (material + duplicated elsewhere); doc for with-traps and debug-object? moved + to section on evaluator trap options. + (High Level Traps): Renamed just `Traps'. Add references to + evaluator trap options and debug options. Make language + appropriate for core Guile (as opposed to previously separate + package). + (Location Traps): Corrected to reflect that location traps now + specify a specific position, not a range of positions. + (Debugging Examples): New (content moved here from + scheme-debugging.texi, and updated to use traps instead of + breakpoints). + + * api-modules.texi (Included Guile Modules): Change `Debugging + Features' reference to `Tracing'. + + * api-options.texi (Evaluator trap options): Doc for with-traps + and debug-object? is now here. + + * guile.texi, scheme-debugging.texi: Move the `Tracing' content of + scheme-debugging.texi to the Modules section. + + * scheme-using.texi (Using Guile in Emacs, GDS Getting Started): + Minor edits. + + * scheme-debugging.texi (Debugging Features, Intro to + Breakpoints): Removed. + (Examples): Moved to api-debug.texi. + (Tracing, Old Tracing): Promoted one level. + (New Tracing, Tracing Compared): Removed. + +2008-03-08 Julian Graham <joolean@gmail.com> + + * api-scheduling.texi (Threads): Add documentation for new + functions "scm_thread_p" and new "scm_join_thread_timed". + (Mutexes and Condition Variables): Add documentation for new + functions "scm_make_mutex_with_flags", "scm_mutex_p", + "scm_lock_mutex_timed", "scm_unlock_mutex_timed", and + "scm_condition_variable_p". + +2008-02-11 Neil Jerram <neil@ossau.uklinux.net> + + * api-data.texi (Random): New text about the default random state, + following suggestions by Stephen Uitti. + +2008-02-01 Neil Jerram <neil@ossau.uklinux.net> + + * api-scheduling.texi (Threads): Add "C Function scm_join_thread" + to doc for join-thread. Thanks to Antoine Mathys for reporting + that scm_join_thread was missing. + +2007-12-09 Stephen Compall <s11@member.fsf.org> + + * srfi-modules.texi (SRFI-69): Avoid use of the first person. + +2007-12-03 Stephen Compall <s11@member.fsf.org> + + * srfi-modules.texi: Describe SRFI-69 in a new subsection. + +2007-10-29 Julian Graham <joolean@gmail.com> + + * api-scheduling.texi (Threads): Document `cancel-thread', + `set-thread-cleanup!' and `thread-cleanup'. + +2007-10-24 Neil Jerram <neil@ossau.uklinux.net> + + * .cvsignore: Add lib-version.texi. + +2007-10-02 Ludovic Courtès <ludo@gnu.org> + + * slib.texi (SLIB installation): Don't recommend using the site + directory for the symlink; instead, suggest either adding a + symlink in `/.../share/guile/1.8' (because slib will look for + its files in the implementation vicinity by default) or defining + `SCHEME_LIBRARY_PATH'. Mention `new-catalog'. + +2007-08-11 Ludovic Courtès <ludo@gnu.org> + + * srfi-modules.texi (SRFI-34): New node. + (SRFI-35): New node. + +2007-07-18 Stephen Compall <s11@member.fsf.org> + + * srfi-modules.texi: Describe SRFI-37 in a new subsection. + +2007-07-10 Ludovic Courtès <ludo@gnu.org> + + * api-data.texi (Arithmetic): Documented `1+' and `1-'. + Suggested by Jon Wilson <j85wilson@fastmail.fm>. + + * api-modules.texi (Module System Reflection): Documented + `save-module-excursion', by Jon Wilson <jsw@wilsonjc.us>. + +2007-06-07 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-control.texi (Dynamic Wind): Fixed typo. Reported by + Norman Hardy. + +2007-05-16 Ludovic Courtès <ludovic.courtes@laas.fr> + + * posix.texi (Network Sockets and Communication): Fixed typo: + `make-socket-object' instead of `make-socket-address'. + +2007-03-08 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Structures): Revise and expand variously, add + make-vtable. + + * api-io.texi: Add various @cindex entries. + + * slib.texi (SLIB): Shorten the bit about core funcs overridden. + Don't want to duplicate the SLIB specs, and the set of modified bits + is likely to change over time and don't want to have to keep up with + that. + +2007-02-22 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Signals): Merge sleep and usleep, note usleep not + actually microsecond accurate, remove warning usleep not always + available (guile has own code for it now, it's not the system call). + Cross reference scm_std_sleep / scm_std_usleep. + + * posix.texi (Signals): Merge getitimer and setitimer, describe what + each timer does, use @defvar to get them indexed, caution may not + actually be microsecond accurate. + +2007-02-20 Neil Jerram <neil@ossau.uklinux.net> + + * Makefile.am (EXTRA_DIST): Add lib-version.texi to the + distribution. + +2007-02-16 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Records): In make-record-type, describe optional + print function argument. + +2007-01-31 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-data.texi (Conversion): Made cross refs point to `Number + Input and Output' rather than `The ice-9 i18n Module'. + (String Comparison): Likewise for `Text Collation'. + * api-i18n.texi (Internationalization): Re-organized the whole + section, documented new i18n features. Added the following + subsections: `i18n Introduction', `Text Collation', `Character + Case Mapping', `Number Input and Output', `Accessing Locale + Information'. Removed `The ice-9 i18n Module'. + * posix.texi (Locales): Updated cross-ref formerly pointing to + `The ice-9 i18n Module'. + * srfi-modules.texi (SRFI-19 String to date): Mention the + internationalization of `string->date'. + +2007-01-25 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Signals): Note signal handlers run via system async and + can hence be delayed quite a while. Struck by William Xu. + +2007-01-19 Han-Wen Nienhuys <hanwen@lilypond.org> + + * api-options.texi (Evaluator trap options): document + memoize-symbol-handler + + * api-evaluation.texi (Evaluator Behaviour): link to the Evaluator + trap options node in trap-enable/trap-set! doco. + +2007-01-16 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Mapping Folding and Unfolding): In string-unfold, + ssay make_final default is nothing extra. The `(lambda (x) )' shown + was not quite right, it would have been `(lambda (x) "")' if anything. + + * api-init.texi (Initialization): Cross reference Runtime Environment + for scm_set_program_arguments. + + * posix.texi (Runtime Environment): Expand program-arguments + description, add set-program-arguments, add scm_set_program_arguments, + note args are per-thread. + +2006-12-14 Kevin Ryde <user42@zip.com.au> + + * api-procedures.texi (let-keywords Reference): Expand variously to + make it clear what's actually taken and done. Shortfalls reported by + Han-Wen Nienhuys. + +2006-12-13 Kevin Ryde <user42@zip.com.au> + + * api-control.texi (Handling Errors): Cross reference "Error + Reporting" for `scm-error', not just "above". + + * posix.texi (Encryption): Cross reference crypt in the glibc manual. + Clarify that key and salt are strings. + + * srfi-modules.texi (SRFI-17): Expand variously. + +2006-11-18 Ludovic Courtès <ludovic.courtes@laas.fr> + + * Makefile.am (BUILT_SOURCES): New variable. + (lib-version.texi): New target. + + * guile.texi: Include `lib-version.texi'. + + * api-data.texi (Conversion): Link to `The ice-9 i18n Module' when + describing `string->number'. + (String Comparison): Likewise. + + * api-i18n.texi (Internationalization)[The ice-9 i18n Module]: New + node. + [Gettext Support]: New node; contains text formerly in + `Internationalization'. + + * posix.texi (Locales): Added a link to the glibc manual + describing the various locale categories. Mention locale objects + and link to `The ice-9 i18n Module' when describing `setlocale'. + +2006-11-17 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi (Reporting Bugs): Note need for subscription to + bug-guile@gnu.org. + +2006-10-10 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Setting and Managing Breakpoints): New text + about what happens when a breakpoint is created. + (Listing and Deleting Breakpoints, Moving and Losing Breakpoints): + New. + +2006-10-08 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Working with GDS in Scheme Buffers): New + subsection, to group (Access to Guile Help and Completion, Setting + and Managing Breakpoints, Evaluating Scheme Code) together. + (GDS Getting Started): Editorial updates. + +2006-10-06 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Using Guile in Emacs): Subnodes reordered, + from (Displaying the Scheme Stack, Continuing Execution, + Evaluating Scheme Code, Setting and Managing Breakpoints, Access + to Guile Help and Completion) to (Access to Guile Help and + Completion, Setting and Managing Breakpoints, Evaluating Scheme + Code, Displaying the Scheme Stack, Continuing Execution). + (Access to Guile Help and Completion): Mention where keys are + defined. + (Setting and Managing Breakpoints): Update text on how to set + breakpoints. + +2006-10-05 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (File Tree Walk): Corrections to BASE parameter + and symlink vs stale-symlink types in nftw. + * misc-modules.texi, guile.texi (Buffered Input): New section, + describing (ice-9 buffered-input). + + * posix.texi (User Information): Clarify getpwent returns #f at end of + file. + + * repl-modules.texi (Readline Functions): New section on how to call + readline from scheme code. + +2006-10-03 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (GDS Getting Started): Editorial updates. + +2006-09-28 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (GDS Introduction, GDS Getting Started): Minor + edits. + + * api-data.texi (Symbol Props): Remove unnecessarily specific + parenthesis about Guile 1.6's use of extra symbol slots. + +2006-09-26 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Using Guile in Emacs, GDS Introduction): + Editorial updates. + (GDS Architecture): Moved earlier in containing section; editorial + updates. + (GDS Getting Started, How to Use GDS): Merged; editorial updates; + subsections reordered. + +2006-09-26 Kevin Ryde <user42@zip.com.au> + + * api-io.texi (Random Access): In truncate-file, tweak wording for + clarity, note cannot always extend file this way. + (Ports): File access uses LFS. + +2006-09-25 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Error Handling, Interactive Debugger): Minor + editorial improvements. + (Leave Debugger): Removed. + (Display Backtrace): Minor updates. + (Frame Selection, Frame Information, Frame Evaluation) : Minor + editorial improvements. + (Stepping and Continuing): Merged from three previous nodes; plus + minor improvements. Removed doc for `trace-finish', which no + longer exists. + +2006-09-22 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Scientific): In sqrt, note it's the positive root + which is returned (as per R5RS). + +2006-09-20 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-data.texi (Standard Character Sets): Documented the + charset recomputation upon successful `setlocale'. + +2006-09-08 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (Formatted Output): Show ":@" rather than "@:", + because ":@" is traditional common lisp, though either way works. + Break a couple of example lines to avoid overflowing DVI page width. + + * scheme-debugging.texi (Debug Last Error): Line break in "Type + (backtrace) to get ..." which overflowed the line in both info and + DVI. Reported by Percy Tiglao. + +2006-09-05 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Network Sockets and Communication): Tweak description, + note not multi-threading. + +2006-09-04 Neil Jerram <neil@ossau.uklinux.net> + + * api-control.texi (Dynamic Wind): Doc for scm_dynwind_free. + + * api-modules.texi (The Guile module system), api-data.texi + (Integers, Numerical Tower), api-compound.texi (Uniform Numeric + Vectors): Fix typos. (Patch sent in by Marco Maggi.) + +2006-08-29 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Debug on Error): Added paragraph on need to use + debugging evaluator. Added text on what the Guile REPL code does. + +2006-08-29 Kevin Ryde <user42@zip.com.au> + + * api-control.texi (Dynamic Wind): Reformat example a bit to avoid + going off the right edge of the paper. Reported by Percy Tiglao. + +2006-08-28 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Examining the Stack): Minor improvements to + display-backtrace doc. + (Debug on Error): More new text on catching the error stack. + +2006-08-27 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Debug on Error): New text on how to catch errors + and the error stack. + +2006-08-23 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Using Guile in Emacs): New text about + available Emacs libraries. + (GDS Introduction): New node, containing GDS-specific introductory + text. + +2006-08-22 Kevin Ryde <user42@zip.com.au> + + * api-i18n.texi (Internationalization): Cross reference gettext manual + on plural forms. + +2006-08-18 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Using Guile in Emacs): Unignore extra GDS + intro text. (I will edit this down later. For now it's + convenient to have it all appearing, so it's visible on paper.) + +2006-08-11 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-using.texi (Run To Frame Exit): Improved doc for finish. + (Continue Execution): Improved doc for continue. + (Using Guile in Emacs): Lots of new docs about the Emacs + interface. + + * api-debug.texi (Low Level Trap Calls): New. + (Using Traps): Removed, material incorporated into Low Level Trap + Calls. + (High Level Traps): New. + (Breakpoints): New. + + * scheme-using.texi (Single Stepping): Improve doc for step and + next. + + * api-debug.texi (Debug on Error): Note need to handling of errors + in C. + + * api-debug.texi (Debugging): New intro text. New subsection + "Evaluation Model". Moved existing subsections "Capturing the + Stack or Innermost Stack Frame", "Examining the Stack", "Examining + Stack Frames", "Source Properties", "Decoding Memoized Source + Expressions" and "Starting a New Stack" under "Evaluation Model". + (Capturing the Stack or Innermost Stack Frame): Some new text, and + correction to doc for last-stack-frame. + (Debug on Error): Renamed from "Interactive Debugging". + +2006-08-01 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Breakpoints): Removed (all wrong). + + * guile.texi (API Reference): Improved summary for "Debugging" + menu item. + + * scheme-debugging.texi (Debug Last Error, Interactive Debugger): + Moved/merged to scheme-using.texi, as REPL features. + (Examples): New. + (Intro to Breakpoints): New introductory text here. Removed all + subnodes except for Breakpoints Overview. + + * scheme-using.texi: New. + + * guile.texi (Programming in Scheme): Include new + scheme-using.texi file. + + * Makefile.am (guile_TEXINFOS): Include new scheme-using.texi + file. + +2006-07-24 Kevin Ryde <user42@zip.com.au> + + * api-evaluation.texi (Fly Evaluation): Add scm_c_eval_string. + (Loading): Add scm_c_primitive_load. + Reported by Jon Wilson. + +2006-06-25 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Time): In tm:gmtoff, give example values, note not the + same as C tm_gmtoff. + +2006-06-16 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-utility.texi (Equality): Mentioned the behavior of `equal?' + for structures (as suggested by Kevin Ryde). + +2006-06-13 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-compound.texi (Structure Concepts): Mentioned the behavior + of `equal?' for structures. + +2006-05-28 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-1 Length Append etc): Add an append-reverse + example. + +2006-05-20 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Pairs): Cross reference SRFI-1 second, third, + fourth. + (List Modification): Cross reference SRFI-1 delete and lset-difference. + (List Searching): Cross reference SRFI-1 member. + (List Mapping): Cross reference SRFI-1 map etc. + (Retrieving Alist Entries): Cross reference SRFI-1 assoc. + + * srfi-modules.texi (SRFI-1 Association Lists): Describe argument + order for "=" procedure. + +2006-05-15 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Processes): Add primitive-_exit. + +2006-05-10 Kevin Ryde <user42@zip.com.au> + + * intro.texi (Linking Guile into Programs): Enhance example program, + change scm_str2string to scm_from_locale_string, since scm_str2string + is "discouraged". And check for NULL from getenv since neither + scm_str2string nor scm_from_locale_string can cope with that. + Reported by Frithjof. + +2006-05-09 Kevin Ryde <user42@zip.com.au> + + * api-control.texi (Multiple Values): In `receive', add an example, + cross ref SRFI-8, tweak wording. + + * api-io.texi (Port Implementation): @defun style for + scm_make_port_type and the various set functions. + + * posix.texi (Ports and File Descriptors): Tweaks to fcntl. + +2006-04-29 Kevin Ryde <user42@zip.com.au> + + * api-scheduling.texi (Threads): In call-with-new-thread, handler arg + is optional (as of 1.8.0). + +2006-04-15 Kevin Ryde <user42@zip.com.au> + + * api-scheduling.texi (System asyncs): "{void *}" in @deffnx to keep + the "*" out of the name in the index. + +2006-04-06 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Ports and File Descriptors): Clarify fcntl a bit, + and correction FD_CLOEXEC goes with FD_SETFD not FD_SETFL. + (Network Sockets and Communication): In accept, cross-reference to + fcntl on O_NONBLOCK. + +2006-03-28 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Vector Accessing from C): Show + SCM_SIMPLE_VECTOR_SET not SCM_SIMPLE_VECTOR_SET_X, the former is + what's in vector.h. + +2006-03-21 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-data.texi (Conversion): Add scm_c_locale_stringn_to_number. + +2006-03-05 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Array Procedures): @pxref for `equal?'. + (Shared Arrays): Correction to make-shared-array stride example, need + `list' on the mapper return value. + +2006-02-13 Marius Vollmer <mvo@zagadka.de> + + * api-utility.texi (Object Properties): Removed confusing + paragraph about 'name' property. + +2006-02-07 Kevin Ryde <user42@zip.com.au> + + * api-modules.texi (Compiled Code Installation): Revise, in particular + @libdir@ needs to go via the makefile. + +2006-02-04 Neil Jerram <neil@ossau.uklinux.net> + + * api-control.texi (Throw Handlers): New node. + (Throw): Moved to after the Lazy Catch node. + (Catch): Enhance to cover the optional pre-unwind handler, and new + APIs scm_c_catch, scm_catch_with_pre_unwind_handler. + (Lazy Catch): Describe relationship to with-throw-handler. + Document that the handler may return, and what happens if it does. + (Throw): Mention that a throw can be handled by a throw handler as + well as by a catch. + +2006-02-04 Kevin Ryde <user42@zip.com.au> + + * api-options.texi (Build Config): pxref libtool on libguileinterface + version info. + * intro.texi (Writing Guile Extensions), libguile-extensions.texi (A + Sample Guile Extension): pxref libtool manual. + + * api-modules.texi (Compiled Code Installation): New section. + + * posix.texi (Network Address Conversion, Network Databases) + (Network Sockets and Communication, Internet Socket Examples): Misc + tweaks. + +2006-01-29 Marius Vollmer <mvo@zagadka.de> + + * api-scheduling.texi: Removed "Futures" node. + + Renamed the "frames" that are related to dynamic-wind to "dynamic + contexts. Renamed all functions from scm_frame_ to scm_dynwind_. + Updated documentation. + +2005-12-19 Ludovic Courtès <ludovic.courtes@laas.fr> + + * api-data.texi (Operations Related to Symbols): + Documented `scm_take_locale_symbol ()'. + +2005-12-15 Kevin Ryde <user42@zip.com.au> + + * api-evaluation.texi (Fly Evaluation): Add scm_call_4, suggested by + Bruce Korb. + + * misc-modules.texi (Streams): In stream->list&length and + stream->reversed-list&length, make the two values clearer. + +2005-12-14 Neil Jerram <neil@ossau.uklinux.net> + + * api-options.texi (Evaluator trap options): Trap calls now always + use a debug object rather than a continuation. + (Debugger options, Examples of option use): Update help text for + 'cheap option (which is now obsolete). + + * api-evaluation.texi (Loading): Document custom reader. + +2005-12-06 Marius Vollmer <mvo@zagadka.de> + + * api-init.texi, api-scheduling.texi, libguile-concepts.texi: + Removed scm_leave_guile, scm_enter_guile and all references to + them since they are no longer in the API. + + From Stephen Compall: + + * api-control.texi (if cond case): Describe SRFI 61 cond. + + * srfi-modules.texi (SRFI-61): New section. + (SRFI Support): Add SRFI-61 to menu. + +2005-11-19 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Retrieving Alist Entries): Revise for clarity and + brevity. + +2005-11-06 Kevin Ryde <user42@zip.com.au> + + From Ludovic Courtès, partial rework by me: + * doc/ref/api-modules.texi (Creating Guile Modules): In define-module, + describe #:re-export, #:export-syntax, #:re-export-syntax, #:replace + and #:duplicates. Add re-export. + +2005-11-01 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Time): In strftime, note systems vary for %Z. + +2005-10-29 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Network Socket Address): Add scm_make_socket_address, + scm_c_make_socket_address, scm_from_sockaddr, scm_to_sockaddr. This + change by Ludovic Courtès and revised a bit by me. + +2005-10-27 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Network Address Conversion): Move INADDR_ANY to here. + (Network Socket Address): New section, move sockaddr bits to here, add + new make-socket-address. + (Network Sockets and Communication): In connect, bind, and sendto, now + take socket address object. In bind, leave INADDR constants for + "Network Address Conversion" node. In those plus accept, getsockname, + getpeername, reword a bit for clarity. + +2005-10-24 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Network Sockets and Communication): Combine and revise + getsockopt and setsockopt. Add OPTNAME constants, including new + IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. + + * posix.texi (Time): Revise strftime for clarity, cross reference man + 3 strftime (suggested by Greg Troxel), note locale character set when + setlocale has been called. + +2005-10-15 Neil Jerram <neil@ossau.uklinux.net> + + * api-debug.texi (Source Properties): Add text describing/advising + limited use of source properties. + + * api-debug.texi (Source Properties): Documentation of source + property procedures moved here from ... + + * api-procedures.texi (Procedure Properties): ... where it didn't + belong. + +2005-10-05 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Regexp Functions): Notes on zero bytes and locale + character set. + + * misc-modules.texi (Formatted Output): Show modifiers like ~:d + instead of in words. + +2005-08-06 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (List Modification): In filter, return may share a + tail with the input, as per docstring. In filter!, fix chopped off + note of modifying input. + + * api-control.texi (Error Reporting): In strerror, note message is in + locale language and charset. + +2005-07-12 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (String Selection): In string-pad, don't say anything + about sharing strings, decided against doing that. + (Miscellaneous String Operations): Ditto in string-filter and + string-delete. + + * api-data.texi (String Selection): Merge descriptions of string-trim, + string-trim-right and string-trim-both for brevity. + +2005-06-24 Kevin Ryde <user42@zip.com.au> + + * api-options.texi (Debugger options): Cross reference new Tail Calls + node rather than R5RS on tail recursion. + +2005-06-23 Kevin Ryde <user42@zip.com.au> + + * guile.texi, libguile-concepts.texi, libguile-extensions.texi, + libguile-linking.texi, libguile-smobs.texi: Spelling errors reported + by hyperdivision. + + * api-compound.texi (Pairs, List Syntax): Cross reference Expression + Syntax for quoting. + * api-control.texi (Lazy Catch): Cross ref for with-fluids. + * libguile-linking.texi (A Sample Guile Main Program): Cross reference + automake manual for aclocal. + * libguile-program.texi (Extending Dia): URL for Dia home page. + (Dia Primitives): Cross ref for scm_c_define_gsubr. + +2005-06-12 Marius Vollmer <mvo@zagadka.de> + + * gh.texi: More stuff about transitioning away from GH. + +2005-06-11 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Miscellaneous String Operations): In string-filter + and string-delete, note result may share with input string (as allowed + by srfi spec). + +2005-06-06 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Array Procedures): In array-in-bounds?, + correction to example result. + + * api-init.texi (Initialization), api-scheduling.texi (Blocking): + {} groups around "void*" C return types. + +2005-05-04 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-1 Selectors): In drop-right, note always a + new list. In take-right, note result shares common tail. Per spec. + +2005-05-03 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (String Constructors): Clarify string, list->string + and reverse-list->string a bit. + +2005-04-30 Kevin Ryde <user42@zip.com.au> + + * api-io.texi (Default Ports): Describe buffering on standard ports. + +2005-04-23 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Regexp Functions): Add list-matches and fold-matches. + + * data-rep.texi (Subrs): Note that subr must not modify its rest list. + +2005-04-19 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Regexp Functions): Clarity flags parameter. + + * misc-modules.texi, guile.texi (Rx Regexps): Remove this section, Rx + is not in the core and we don't want to confuse anyone with it and the + builtin posix regexps. + +2005-04-04 Han-Wen Nienhuys <hanwen@xs4all.nl> + + * srfi-modules.texi (SRFI-1 Set Operations): use @cross iso. @times. + + * guile.texi: add @cross for @tex + +2005-04-02 Kevin Ryde <user42@zip.com.au> + + * guile.texi (@times): New macro. + + * repl-modules.texi (Readline Support): Cross ref readline manual. + (Loading Readline Support): Add GUILE_HISTORY and .inputrc Guile + configurables. + + * srfi-modules.texi (SRFI-1 Association Lists): In alist-cons, clarify + a bit and cross reference core acons. + + * srfi-modules.texi (SRFI-1 Set Operations): Revise and expand. + (SRFI-1 Deleting): In delete, cross reference lset-difference. + + * srfi-modules.texi (SRFI-19): Note Gregorian leap year rules + incorrectly extended back prior to 1582. + +2005-03-29 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-compound.texi: Fixed some typos and added some docs. Talk + about concrete and abstract hash tables. + +2005-03-14 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-55): New section. + (SRFI-60): New section. + +2005-03-01 Kevin Ryde <user42@zip.com.au> + + * api-compound.texi (Shared Arrays): New section. Rewrite + make-shared-array for clarity, adding examples. + + * libguile-concepts.texi (Control Flow): Cross reference Tail Calls. + +2005-02-17 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Reals and Rationals): Use tex for sqrt2 and pi. + (Complex Numbers): Add polar form read syntax. + +2005-02-15 Kevin Ryde <user42@zip.com.au> + + * posix.texi (File System): In tmpnam, clarify security and use of + O_EXCL. In mkstemp!, in fact posix doesn't specify permissions. + + * scheme-ideas.texi (Tail Calls): New section. + +2005-02-12 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (String Selection): In string-pad and + string-pad-right, clarify which end the padding goes on, and merge + descriptions. + + * api-data.texi (Integer Operations): In gcd and lcm, show args. + (Arithmetic): In truncate, add missing arg. + + * srfi-modules.texi (SRFI-1 Fold and Map): Rewrite fold, pair-fold and + reduce for clarity. + +2005-02-05 Kevin Ryde <user42@zip.com.au> + + * posix.texi (File System): In mkstemp!, in fact posix doesn't specify + the permissions mode. Add an example setting 666 less umask. + +2005-02-04 Kevin Ryde <user42@zip.com.au> + + * api-io.texi (File Ports): In port-filename, cannot use after close. + + * posix.texi (Time): In mktime, clarify fields of sbd-time used, and + the handling of tm:isdst. + + * srfi-modules.texi (SRFI-0): Add srfi-4, srfi-13 and srfi-14 now in + the core. + +2005-01-29 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Signals): In sigaction, add SA_NOCLDSTOP, make it + clearer SA_RESTART is a variable. + +2005-01-28 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-1 Predicates): Clarify proper-list?, + circular-list? and dotted-list?, note any object passes exactly one of + those. + + * srfi-modules.texi (SRFI-19 Time/Date conversions): In default + tz-offset, note restrictions on a 32-bit system. + +2005-01-24 Kevin Ryde <user42@zip.com.au> + + * api-i18n.texi (Internationalization): Expand and revise a bit for + clarity. + + * srfi-modules.texi (SRFI-1 Searching): In member, note `=' called arg + order. + (SRFI-1 Set Operations): Remove lset-adjoin!, doesn't exist in the + code or the srfi spec. + +2005-01-20 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Ports and File Descriptors): In flock, for LOCK_NB note + logior for LOCK_NB and EWOULDBLOCK error, and note flock doesn't work + over NFS. + + * srfi-modules.texi (SRFI-1 Searching): In list-index, note 0 based + index and #f for not found. + +2005-01-15 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Bitwise Operations): In logtest and logbit?, describe + operations in words, not just equivalent expressions. In + integer-expt, clarify a bit and note negative k allowed and 0^0==1. + + * api-data.texi (Random): In random:solid-sphere!, there is no return + value. + + * api-evaluation.texi (Loading): In %load-hook, need to use set!, and + describe #f. + +2005-01-14 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-scripts.texi: Describe new 1.4 compatability behavior of + -e option. + +2005-01-14 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Mapping Folding and Unfolding): In + string-for-each-index, make it clear iteration is over indices. + + * posix.texi (User Information): Note cuserid gone from POSIX. + Prompted by Roland Besserer. + + * srfi-modules.texi (SRFI-39): New section. + +2005-01-10 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi: Various index entries. + (SRFI-19 Introduction): Note MJD basis is 2400000.5. + (SRFI-19 Date): In date-second, clarify leap second usage. In + date-year, note negatives for B.C. and no zero. In current-date, + don't let it read like it's just UTC which is returned. + +2005-01-08 Kevin Ryde <user42@zip.com.au> + + * api-modules.texi (Creating Guile Modules): Expand define-modules + #:autoload, clarify that it's a list of symbols. + + * api-modules.texi (Included Guile Modules): Add expect, format, ftw, + getop-long, history, popen, pretty-print, q, readline, receive, regex, + streams, syncase, srfi-16, srfi-19 and srfi-31. Remove ice-9 jacal, + no such module. + + * posix.texi (File System): In mkstemp!, note 0600 creation mode. + +2005-01-06 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-compound.texi: Finished(?) the new array API docs. + +2005-01-02 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Pipes): Expand and clarify a bit. Describe port + inheritance. Caution against waitpid WAIT_ANY. + +2004-12-29 Marius Vollmer <mvo@zagadka.de> + + * api-compound.texi (Arrays): Updated for the new 'typed' approach + at creating arrays. + +2004-12-28 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (String Predicates): For string-any and string-every, + last chars are now tail calls per srfi, and reinstate char_pred can be + character or character set (somehow lost in cut and paste). + + * srfi-modules.texi (SRFI-1 Searching): In any and every, revise for + clarity, note last call in each is a tail call. + +2004-12-27 Marius Vollmer <mvo@zagadka.de> + + * api-compound.texi (Vectors, Bit Vectors, Uniform Numeric + Vectors): Updated for the distinction between read-only and write + access to storage locations. + +2004-12-22 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-compound.texi (Arrays): Reorganized and 'modernized'. + +2004-12-20 Mikael Djurfeldt <djurfeldt@nada.kth.se> + + * expect.texi (Expect): Removed backslash escapes of regexp + operators ( and ) in code example for expect-strings. + +2004-12-14 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Regexp Functions): Revise regex-substitute and + regex-substitute/global for clarity, add some examples. + + * api-procedures.texi (lambda* Reference): Revise for clarity, note + how #:rest works with #:key, note previous bindings available to + default expressions. + +2004-12-05 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-1 Length Append etc): In concatenate, note + equivalence to "apply append". + +2004-11-09 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-compound.texi (Generalized Vectors): New. + (Bit Vectors): More docs. + (Uniform Vectors): Call them Uniform numeric vectors. + +2004-10-29 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-compound.texi (Uniform Vectors): Added c32 and c64 docs. + +2004-10-27 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * srfi-modules.texi, api-compound.texi: Moved SRFI-4 docs into + main part. Moved bit vectors out of array section to make them + more visible. + +2004-10-19 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-smobs.texi (smob mark function): List admissible functions + to call. + +2004-10-04 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-data.texi: Removed primitive keyword section, updated + keyword docs. + + * api-undocumented.texi: Moved keyword dash-symbol docs here. + +2004-09-26 Kevin Ryde <user42@zip.com.au> + + * api-data.texi (Conversion to/from C): Braces {} around char* return. + * api-evaluation.texi (Block Comments): More cindex entries. + + * guile.texi, misc-modules.texi (Streams): New section. + +2004-09-25 Marius Vollmer <mvo@zagadka.de> + + * libguile-smobs.texi, api-smobs.texi: More words abot what a free + function is allowed to do. + +2004-09-24 Marius Vollmer <mvo@zagadka.de> + + * libguile-smobs.texi: Bugfix in example code, use SCM_NEWSMOB + correctly. Use scm_assert_smob_type instead of SCM_ASSERT + baroqueness. + +2004-09-23 Marius Vollmer <mvo@zagadka.de> + + * api-i18n.texi: New file. + * Makefile.am (guile_TEXINFOS): Added it. + * guile.texi: Include it. + +2004-09-16 Kevin Ryde <user42@zip.com.au> + + * api-utility.texi (Equality): Revise for clarity. + +2004-09-08 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-data.texi (integer-expt): Updated from docstring. + + * Makefile.am (CLEANFILES, MAINTAINERCLEANFILES): Moved + autoconf-macros.texi to MAINTAINERCLEANFILES. It is in the + tarball and we shouldn't clean it, then. + +2004-09-07 Kevin Ryde <user42@zip.com.au> + + * api-procedures.texi (let-keywords Reference): Typo, should be + let-keywords* @defunx. + + * api-scheduling.texi (Parallel Forms): In parallel, letpar, par-map, + n-par-map and n-for-each-par-map, describe each form as being in its + own thread, not a new thread, since for instance the calling thread is + used when only one form. Plus typo in n-for-each-par-map example + equivalent for-each + n-par-map. + + * posix.texi (Locales): Use @var for category arg. + + * posix.texi (System Identification): Remove software-type, it doesn't + exist in the guile core. + + * srfi-modules.texi (SRFI-10): Revise and expand. + +2004-09-02 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (Formatted Output): Excess arguments are ignored. + In ~*, correction N parameter cannot be negative. In ~t, note + port-column used. + +2004-08-29 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-2): Note empty body is #t. + +2004-08-25 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-data.texi, srfi-modules.texi: Moved docs for SRFI-14 into + main API chapter. Updated docstrings from libguile/. + +2004-08-25 Marius Vollmer <mvo@zagadka.de> + + * api-data.texi, srfi-modules.texi: Moved docs for SRFI-14 into + main API chapter. Updated docstrings from libguile/. + +2004-08-24 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + Ran a (docstring-process-module "(guile)") and moved entries from + new-docstrings.texi to their appropriate place. + + * api-undocumented.texi: New file. + +2004-08-21 Marius Vollmer <mvo@zagadka.de> + + From Richard Todd, Thanks! + + * scheme-scripts.texi (Invoking Guile): documented new '-L' + switch. + +2004-08-20 Marius Vollmer <mvo@zagadka.de> + + * gh.texi: Updated transition section with new recommended things. + +2004-08-19 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-data.texi (Strings): Document copy-on-write behavior and + mutation-sharing substrings. + (Symbols): Document scm_from_locale_symbol and + scm_from_locale_symboln. + +2004-08-18 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Network Sockets and Communication): Add SOCK_RDM and + SOCK_SEQPACKET. + + * posix.texi (Internet Socket Examples): Correction to socket calls, + should be PF_INET not AF_INET (though generally the two are the same + value). + +2004-08-14 Kevin Ryde <user42@zip.com.au> + + * api-scheduling.texi (Mutexes): New datatype-centric section, adding + fair mutexes and collecting up material from ... + (Low level thread primitives, Higher level thread procedures, C level + thread interface): ... these nodes. + + * srfi-modules.texi (SRFI-13 Predicates): Add string-any and + string-every support for char and charset predicates. + +2004-08-11 Marius Vollmer <mvo@zagadka.de> + + * api-data.texi (scm_c_round, scm_c_truncate): Docs for'em. + +2004-08-10 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-control.texi: Updated example to use scm_to_locale_string + instead of roll-your-own scm_to_string. Also showcase + scm_frame_free. + + * api-data.texi: Docs for scm_is_string, scm_to_locale_string*, + and scm_from_locale_string*. + + * api-memory.texi: Docs for scm_frame_free. + +2004-08-09 Kevin Ryde <user42@zip.com.au> + + * api-io.texi (File Ports): In open-file, describe the "b" binary flag. + + * slib.texi (SLIB): Add notes on delete-file, provided? and open-file + overridden by ice-9 slib module. + +2004-08-05 Kevin Ryde <user42@zip.com.au> + + * api-scheduling.texi (Arbiters): Tweak wording for clarity, note any + thread can unlock not just the one which locked. + + * posix.texi (Conventions): Describe system-error args, use @defun for + system-error-errno instead of just words. + + * srfi-modules.texi (SRFI-13 Predicates): Tweak wording for clarity. + For string-every, note return is #t when no characters. For + string-any and string-every, note last pred call is not currently a + tail call, contrary to SRFI-13 spec. + +2004-08-03 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * api-data.texi: Added scm_is_real, scm_is_rational, + scm_to_double, scm_from_double, numerator, and denominator. Added + scm_is_complex, scm_is_number, scm_c_make_rectangular, + scm_c_make_polar, scm_c_real_part, scm_c_imag_part, + scm_c_magnitude, and scm_c_angle. + +2004-08-02 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * gh.texi: Replaced references to scm_num2* with scm_to_* and + references to scm_*2num with scm_from_*. + + Renamed many file to make the structure of the manual more evident + in the names. Changed all references. + + * scheme-binding.texi: Renamed to api-binding.texi. + * scheme-compound.texi: Renamed to api-compound.texi. + * scheme-control.texi: Renamed to api-control.texi. + * scheme-data.texi: Renamed to api-data.texi. + * scheme-debug.texi: Renamed to api-debug.texi. + * deprecated.texi: Renamed to api-deprecated.texi. + * scheme-evaluation.texi: Renamed to api-evaluation.texi. + * ref-init.texi: Renamed to api-init.texi. + * scheme-io.texi: Renamed to api-io.texi. + * scheme-memory.texi: Renamed to api-memory.texi. + * scheme-modules.texi: Renamed to api-modules.texi. + * scheme-options.texi: Renamed to api-options.texi. + * scm.texi: Renamed to api-overview.texi. + * scheme-procedures.texi: Renamed to api-procedures.texi. + * scheme-scheduling.texi: Renamed to api-scheduling.texi. + * scheme-scm.texi: Renamed to api-scm.texi. + * scheme-smobs.texi: Renamed to api-smobs.texi. + * scheme-snarf.texi: Renamed to api-snarf.texi. + * scheme-translation.texi: Renamed to api-translation.texi. + * scheme-utility.texi: Renamed to api-utility.texi. + * debugging.texi: Renamed to scheme-debugging.texi. + * scripts.texi: Renamed to scheme-scripts.texi. + * program.texi: Renamed to libguile-program.texi. + + * api-deprecated.texi: Removed. + * intro.texi (Discouraged and Deprecated): General information + about deprecation, etc. + +2004-07-30 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * misc-modules.texi (Formatted Output): Changed @w to @w{} in + itemize. The former doesn't work for some reason... + +2004-07-28 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (Formatted Output): Rewrite, describing escapes + and parameters in detail. + * guile.texi (@le, @ge): New macros for ifnottex. + +2004-07-24 Kevin Ryde <user42@zip.com.au> + + * guile.texi (@nicode): Use @alias instead of @macro, for correct + handling of backslashes. + + * scheme-control.texi (Frames): Add @vindex for SCM_F_WIND_EXPLICITLY. + + * scheme-data.texi (String Syntax): Add all backslash forms accepted. + (Regexp Functions): Use @defvar for regexp/icase etc, to emphasise + that they're variables not symbols etc. + + * scheme-smobs.texi (Smobs): In SCM_SMOB_OBJECT_LOC, + SCM_SMOB_OBJECT_2_LOC, SCM_SMOB_OBJECT_3_LOC, use {} to avoid "*" + getting into the index as part of the macro name. + + * srfi-modules.texi (SRFI-0): Revise for clarity, drop BNF in favour + of plain description, emphasise this is just for portable programs. + +2004-07-10 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-data.texi (Integers): Talk more about inexact and exact + integers. + +2004-07-10 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-0): Add srfi-6 to the identifiers provided + by default. + +2004-07-07 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-data.texi (Integers): Added docs for the new scm_is_, + scm_to_ and scm_from_ functions for integers. + + * data-rep.texi (How Guile does it): Mark as being in limbo. All + the real documentation will be in the nodes "Programming in C" and + "API Reference". + (Boolean Data): Just refer to node "Booleans". + + * gh.texi: Replace references to SCM_NFALSEP, etc with + scm_is_true, etc. + + * scheme-data.texi (Booleans): Flag all function-like definitions + as "C Functions". + +2004-07-06 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-data.texi: Remove non-R5RS stuff from the 'rn' index. + + * scheme-utility.texi: Added scm_is_eq, scm_eq_p, scm_eqv_p, and + scm_equal_p. + +2004-07-05 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-data.texi (Booleans): Added reference entries for + scm_is_true, scm_is_false, scm_is_bool, scm_from_bool, and + scm_to_bool. + +2004-06-28 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * Makefile.am: Removed home-grown code for HTML generation. + Automake does it for us now. + + * guile.texi, scheme-scm.texi: Do not use TeXinfo markup in + section or node names. + +2004-06-20 Rob Browning <rlb@defaultvalue.org> + + * srfi-modules.texi (SRFI-31): add documentation for srfi-31. + +2004-05-19 Kevin Ryde <user42@zip.com.au> + + * Makefile.am (CLEANFILES): Remove guile.cps guile.fns guile.rns + guile.tps guile.vrs guile.tmp, cleaned by automake these days. + +2004-05-06 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-smobs.texi: Updated for new SCM_SMOB_* macros. + + * preface.texi: Moved around the sections so that the manual + overview comes first. + + * libguile-smobs.texi: Updated for the new role of scm_t_bits. + +2004-04-21 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * Big reorganization of the whole manual to give it a simpler + structure. + +2004-03-25 Kevin Ryde <user42@zip.com.au> + + * slib.texi (SLIB): Amend `require' cross reference node name, is + called "Require" in slib 3a1. + +2004-03-23 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Reals and Rationals): Typo in `rationalize'. + +2004-03-04 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Processes): Add setgroups. + + * srfi-modules.texi (SRFI-26): New section. + +2004-02-21 Kevin Ryde <user42@zip.com.au> + + * scheme-evaluation.texi (Expression Syntax): Add @findex entries for + quote and quasiquote no longer using @deffn. + +2004-02-20 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-evaluation.texi (Expression Syntax): Turned syntax + description into a table, @deffn is not really up to the task. + +2004-02-18 Marius Vollmer <mvo@zagadka.de> + + * guile.texi: Replaced list of authors with "The Guile + Developers". + + * preface.texi (Contributors to the Manual): New section. + + * scheme-evaluation.texi (Expression Syntax): Use an empty name + for the function call syntax definition. Otherwise, TeX complains + about unbalanced parenthesis. + +2004-02-18 Kevin Ryde <user42@zip.com.au> + + * scheme-evaluation.texi (Expression Syntax): Fill section with + function calling etc, and quote and quasiquote. + + * srfi-modules.texi (SRFI-9): Revise for detail and clarity. Don't + use ":foo" for example type name, since that depends on the keyword + reading option. + +2004-02-15 Mikael Djurfeldt <mdj@chunk.mit.edu> + + * scheme-compound.texi (Hash Table Reference): Wrote a new entry + for hash-for-each-handle. + +2004-02-16 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Sloppy Alist Functions): Amend error messages + shown to match current guile output. + +2004-02-15 Mikael Djurfeldt <mdj@chunk.mit.edu> + + * scheme-compound.texi (Hash Table Reference): Renamed hash-map + --> hash-map->list. + +2004-02-15 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Hash Table Reference): In scm_hash_ref etc, + remove note that dflt must be given, it can be SCM_UNSPECIFIED. + + * scheme-control.texi (while do): Expand and clarify `do', in + particular note iteration binds fresh locations, rather than values + "stored". + + * srfi-modules.texi (SRFI-4): Revise for clarity, give each function + explicitly rather than showing TAG so Emacs info-look can find them, + merge "SRFI-4 - Read Syntax" and "SRFI-4 - Procedures" into just one + node. + +2004-02-12 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Conventional Arrays): Revise for clarity. + In array-equal?, show multiple arguments allowed. + (Uniform Arrays): Remove duplicate array?. + * guile.texi (cross): New macro. + + * scheme-compound.texi (Uniform Arrays): Note 1/3 prototype for + doubles is now an exact fraction. + + * slib.texi (SLIB): Index entry for replacement `system'. + +2004-01-28 Mikael Djurfeldt <mdj@chunk.mit.edu> + + * scheme-compound.texi (Uniform Arrays): Added a FIXME warning + that the 1/3 prototype no longer works. + +2004-01-23 Marius Vollmer <mvo@zagadka.de> + + * Makefile.am (guile_TEXINFOS): Added fdl.texi. + +2004-01-21 Marius Vollmer <mvo@zagadka.de> + + Added copyright notices to all TeXinfo files. + + * fdl.texi: New. + * guile.texi: Include it as an appendix. + * preface.texi: State that the manual is FDL. + +2004-01-20 Kevin Ryde <user42@zip.com.au> + + * preface.texi (Guile License): Note readline is GPL and manual has + its own copying terms. Describe briefly what the licenses mean in + practice. + + * scheme-scheduling.texi (Higher level thread procedures): In monitor, + don't let "newly created" suggest a mutex created on every evaluation. + Note what "monitor" means. + + * slib.texi (SLIB): Note `system' redefined by (ice-9 slib). Tweak + `require' example. + +2004-01-11 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (Queues): New chapter. + * guile.texi (Top): Add it. + +2004-01-09 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Bit Vectors): Revise for clarity, following + report by Rouben Rostamian. Remove #b() example, that syntax is not + accepted. + +2004-01-07 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-control.texi, scheme-io.tex, scheme-scheduling.texi: + Adapt to new 'frame' names. Document scm_c_with_fluid, + scm_c_with_fluids, and scm_frame_fluid. + +2004-01-06 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-control.texi: Document scm_on_unwind_with_scm and + scm_on_rewind_with_scm. + +2004-01-05 Marius Vollmer <mvo@zagadka.de> + + * scheme-scheduling.texi: Document scm_with_[un]blocked_asyncs. + + * scheme-io.texi: Document scm_with_current_<foo>_port. + +2004-01-03 Marius Vollmer <mvo@zagadka.de> + + * scheme-control.texi: Document the frames stuff and other random + changes. + +2004-01-04 Kevin Ryde <user42@zip.com.au> + + * scheme-scheduling.texi (Threads): Note Guile uses POSIX threads, for + concurrency and preemption. + (C level thread interface): Note periodic libguile call required for C + code in threads, add commented out reminders for SCM_TICK and + guile-mode, for when those features are ready. + + * srfi-modules.texi (SRFI-1 Filtering and Partitioning): For partition + and partition!, emphasise the multi-value return, note partition may + share a tail with the given list. + + * srfi-modules.texi (SRFI-1 Searching, SRFI-1 Deleting, SRFI-1 + Association Lists): Note how member, delete, delete! and assoc extend + the corresponding core functions. + +2003-11-25 Kevin Ryde <user42@zip.com.au> + + * tools.texi (Macros guile-snarf recognizes): Correction to GOOPS + cross reference. + +2003-11-19 Marius Vollmer <mvo@zagadka.de> + + * scheme-data.texi: Include exact rationals. + + From Stephen Compall. Thanks! + + * intro.texi (What is Guile?): Add @acronym for POSIX, R5RS, GUI, + and HTTP. Conclude linking libguile. Say what one can find *for*. + + * preface.texi (Manual Conventions): Double-quote some statements + formerly single-quoted. Remove some redundant quotes around code. + Clarify meaning of `iff' further for those that didn't get it the + first time 'round (like me). Make graphical indicators samples, + not code. Put results of evaluation on the same line as @result + symbols. Use @print example as example of total usage, and remind + readers not to forget the difference. + +2003-11-17 Marius Vollmer <mvo@zagadka.de> + + * scheme-modules.texi: Document '@' and '@@'. + + * scripts.texi: Mention that "-e (@ ...)" also works. + +2003-11-15 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Random): Add *random-state* variable, put note at + the top of the node about it being the default, rather than just in + the description of random. + +2003-11-13 Marius Vollmer <mvo@zagadka.de> + + * preface.texi (Manual Layout): Wrap POSIX, API, and SLIB in + @acronym. Change from paragraph format (somewhat clumsy-looking + on paper, at least) to @table format, with headers @strong. Made + example modules complete sentences. From Stephen Compall, thanks! + +2003-11-09 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (Pretty Printing): Add new keyword options, break + example to avoid long line. + + * scheme-data.texi (Random): In random, use @code for *random-state*. + Reported by Stephen Compall. + + * srfi-modules.texi (SRFI-1 Filtering and Partitioning): Move filter + and filter! ... + * scheme-compound.texi (List Modification): ... to here, now that + they're implemented in the core. + +2003-11-03 Kevin Ryde <user42@zip.com.au> + + * misc-modules.texi (File Tree Walk): New chapter. + * guile.texi: Add it. + +2003-10-18 Kevin Ryde <user42@zip.com.au> + + * gh.texi (Calling Scheme procedures from C, scm transition summary): + Refer to scm_list_n, not the old name scm_listify. + (scm transition summary): For gh_apply, recommend scm_apply_0, which + is now documented. + + * gh.texi (Defining new Scheme procedures in C): Don't use + @strong{Note:}, latest makeinfo will complain it looks like a cross + reference. + + * posix.texi (Time): Correction to strftime glibc cross reference + node, now "Formatting Calendar Time". + + * srfi-modules.texi (SRFI-1 Searching): In break, note conflict with + binding established by `while'. + +2003-10-09 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Hash Table Reference): Decribe rehashing, note + no hashx-remove!, describe make-hash-table size parameter. + +2003-10-06 Marius Vollmer <mvo@zagadka.de> + + * scheme-memory.texi: Added a short explanation of the GC and the + conservative stack scanning. + (scm_gc_protect_object, scm_gc_unprotect_object, + scm_permanent_object): New. + + * data-rep.texi, scheme-memory.texi (scm_remember_upto_here_1, + scm_remember_upto_here_2): Moved from data-rep.texi to + scheme-memory.texi. + +2003-10-02 Kevin Ryde <user42@zip.com.au> + + * scheme-io.texi (String Ports): In call-with-output-string, note proc + should not close the port. In get-output-string, note string must be + gotten before closing the port. + +2003-09-21 Kevin Ryde <user42@zip.com.au> + + * posix.texi (File System): In access?, reword a bit, clarify real + versus effective ID handling, cross reference glibc on that, and + recommend against access tests in library functions. + +2003-09-13 Kevin Ryde <user42@zip.com.au> + + * posix.texi (File System): In stat:dev and stat:mode, clarify that + both are numbers. + + * posix.texi (Network Address Conversion): Under IPv4, describe + numeric representation in Guile, add INADDR_LOOPBACK and + INADDR_BROADCAST, add commented-out INADDR_NONE. + + * scheme-compound.texi (Append/Reverse): Merge reverse and reverse!, + describe newtail parameter for reverse!, remove confusing caveat about + head becoming tail for reverse!. + + * scheme-io.texi (Reading): In port-column, port-line, + set-port-column! and set-port-line!, port parameter must be given, + there's no default to current input. + + * scheme-io.texi (Reading): Add scm_c_read. + (Writing): Add scm_c_write. + + * srfi-modules.texi (SRFI-1 Constructors): Add list-copy. + + * srfi-modules.texi (SRFI-19): Rewrite, adding descriptions of all + functions, and a bit of an introduction. + +2003-09-03 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Keyword Primitives): Add examples to + make-keyword-from-dash-symbol and keyword-dash-symbol. Add + scm_c_make_keyword. + + * scheme-data.texi (Symbol Primitives): In gensym, cross reference + uninterned symbols, use @w{} on " g" prefix to avoid any chance of a + line break obscuring it. + +2003-08-30 Kevin Ryde <user42@zip.com.au> + + * data-rep.texi (Remembering During Operations): Note + scm_remember_upto_here_1 applies only to C automatic variables. + + * guile.texi: Move @contents to usual place after title page, and + after first menu since that looks nice in html. + + * posix.texi (Ports and File Descriptors): In pipe PIPE_BUF, use + @defvar, reword a bit for clarity, cross reference glibc. + + * posix.texi (Network Sockets and Communication): In socket, use + @defvar for protocol variables, cross reference for getprotobyname, + note it's usually connect and accept that establishes communication. + + * posix.texi (Network Sockets and Communication): In socketpair, + clarify the return is a pair with ports in car and cdr, note + connection is full duplex, refer to socket for parameters, refer to + PF_UNIX rather than AF_UNIX. + + * scheme-compound.texi (Append/Reverse): Merge append and append!, + shown parameters as lst1 ... lstN, describe list argument for + scm_append and scm_append_x and note that it's unmodified. + + * scheme-compound.texi (Hash Table Reference): Add hashx- case + insensitive string example, add cross references to symbol-hash, + string-hash, string-hash-ci, and char-set-hash. + + * scheme-control.texi (Multiple Values): In values, show args as "arg1 + ... argN". In scm_values, note args is a list and returned object + shares structure with it. + + * scheme-control.texi (Catch): Add scm_internal_catch. + (Lazy Catch): Add scm_internal_lazy_catch. + + * scheme-data.texi (Arithmetic): Use a table for scheme to C libm + equivalences, add C99 trunc. + + * scheme-procedures.texi (Lambda): Note ". rest" list argument is + always newly created. + + * srfi-modules.texi (SRFI-1 Association Lists): In alist-delete and + alist-delete!, note argument order for the equality calls per SRFI-1 + spec. + +2003-08-26 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Scientific): Add two-argument atan. + + * tools.texi (How guile-snarf works): Need @@ for texinfo in example. + +2003-08-17 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (Hash Table Reference): Collect up groups of + functions to avoid duplication. Revise notes on hashx functions and + on vector implementation. In make-hash-table, size is now optional. + Add hash-map and hash-for-each. + +2003-08-14 Kevin Ryde <user42@zip.com.au> + + * scheme-control.texi (while do): Update `while' for code rewrite, in + particular describe break and continue. + +2003-08-09 Kevin Ryde <user42@zip.com.au> + + * scheme-memory.texi (Memory Blocks): Add index entries for deprecated + scm_must_malloc and friends. + +2003-07-29 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (List Constructors): Remove scm_cons_star, + since it's not very helpful. + + * scheme-utility.texi (Property Primitives): In primitive-property-ref, + note parameters to not-found-proc, use hyphens rather than underscores + for that parameter name. + In primitive-property-set!, VAL is the value parameter not CODE. + +2003-07-24 Kevin Ryde <user42@zip.com.au> + + * scheme-control.texi (Dynamic Wind): Untabify. + (Multiple Values): Use @result. + Reported by Stephen Compall <s11@member.fsf.org>. + + * scheme-control.texi (Continuations): Rewrite with more detail. + + * scheme-scheduling.texi (System asyncs): Add index entries for C + functions. + + * scheme-scheduling.texi (Parallel Forms): New section. + +2003-07-18 Kevin Ryde <user42@zip.com.au> + + * scheme-compound.texi (List Constructors): In list, use "elem1 + ... elemN". Add scm_list_1, scm_list_2, scm_list_3, scm_list_4, + scm_list_5, scm_list_n. Remove scm_list, since it's a no-op. + * guile.texi (nicode): New macro. + + * scheme-evaluation.texi (Fly Evaluation): In apply, reword for + clarity, drop the "append" example. Add scm_apply, scm_apply_0, + scm_apply_1, scm_apply_2, scm_apply_3. + Add scm_call_0, scm_call_1, scm_call_2, scm_call_3. + In apply:nconc2last, move down after "apply", reword for clarity, note + correspondence to apply params. + + * srfi-modules.texi (SRFI-0): Add cond-expand index entry. + (SRFI-9): Add define-record-type index entry. + +2003-07-12 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-1 Constructors): In iota, reword a bit for + clarity and add a couple of examples. + +2003-07-10 Kevin Ryde <user42@zip.com.au> + + * deprecated.texi (Deprecated): Add scm_remember. + +2003-06-22 Kevin Ryde <user42@zip.com.au> + + * data-rep.texi (Remembering During Operations): Refer to all "Guile + library functions" as provoking gc. + +2003-06-19 Kevin Ryde <user42@zip.com.au> + + * scheme-io.texi (File Ports): Describe call-with-input-file and + call-with-output-file together. Describe with-input-from-file, + with-output-to-file and with-error-to-file together, and add that they + use dynamic-wind on the current port setting and keep the port open in + support of captured continuations. + (Closing): Describe close-input-port and close-output-port together, + tweak the wording slightly. + +2003-06-14 Kevin Ryde <user42@zip.com.au> + + * data-rep.texi (Vector Data): For SCM_VECTOR_BASE, SCM_STRING_CHARS + and SCM_SYMBOL_CHARS, cross reference "Remembering During Operations". + + * scheme-data.texi (Arithmetic): round is to nearest even. + +2003-06-12 Kevin Ryde <user42@zip.com.au> + + * data-rep.texi (Remembering During Operations): New section. + + * scheme-data.texi (Primitive Numerics): Add atan2, pow, asinh, acosh + and atanh to scheme<->C table. Note asinh, acosh and atanh are C99, + and scm_asinh, scm_acosh and scm_atanh are equivalents. Cross ref + glibc "Mathematics". Reword this end part for clarity. + + * scheme-memory.texi (Memory Blocks): Use {} around types for + @deftypefn, for correct name in indexes. + * scheme-utility.texi (C Hooks): Ditto. + * gh.texi (Scheme to C): Ditto. + + * gh.texi (Scheme to C): In gh_scm2newstr, lenp is size_t* not int*. + This changed in guile 1.6, the docs weren't updated. + +2003-06-09 Marius Vollmer <mvo@zagadka.de> + + From Mike Gran <spikegran@earthlink.net>. Thanks! + + * preface.texi: Minor punctuation mistakes. Hyphens should link + compound adjectives. Commas should be placed after a "therefore" + that begins a sentence. Commas should not be used to separate a + list of only 2 dependent clauses. + +2003-06-07 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Arithmetic): Cross reference glibc floor and ceil. + +2003-06-05 Kevin Ryde <user42@zip.com.au> + + * posix.texi (File System): stat:rdev and stat:blocks can return #f, + stat:blksize returns a sensible size if the field is not available. + + * scheme-compound.texi (Array Mapping): Reword for clarity, and in + particular have the same parameter names in the text and prototypes. + + * scheme-evaluation.texi (Delayed Evaluation): Add delay, reword + promise? and force a bit, describe recursive forcing of a promise by + its own code. + + * scheme-io.texi (Ports): Add notes on garbage collection, and on + explicitly closing file ports. + (File Ports): Cross reference Ports node on explicit closing. + + * posix.texi (Network Sockets and Communication): Cross reference + Ports node on explicit closing. + + * scheme-scheduling.texi (Futures): New section. + + * srfi-modules.texi (SRFI-13 Miscellaneous): In string-replace, note + that start1 and end1 optional is a Guile extension. + +2003-05-30 Kevin Ryde <user42@zip.com.au> + + * deprecated.texi: Add substring-move-left! and substring-move-right!. + + * scheme-io.texi (Default Ports): Remove duplicate descriptions of + set-current-output-port and set-current-error-port. + +2003-05-27 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * scheme-compound.texi: Clarified that vectors need to be quoted. + +2003-05-26 Kevin Ryde <user42@zip.com.au> + + * posix.texi (Locales): Clarify setlocale a bit, list all categories, + cross reference to libc. + +2003-05-24 Kevin Ryde <user42@zip.com.au> + + * scheme-procedures.texi: Add index entries lambda, optargs, syncase. + + * scsh.texi (The Scheme shell (scsh)): Add index entries. + +2003-05-22 Kevin Ryde <user42@zip.com.au> + + * srfi-modules.texi (SRFI-2): Rewrite and-let*, describing plain + expression clauses and improving the examples. + +2003-05-17 Marius Vollmer <mvo@zagadka.de> + + * posix.texi (socket): Use PF_ instead of AF_ prefix. + +2003-05-16 Kevin Ryde <user42@zip.com.au> + + * guile.texi: Use @copying, show copyright and permissions at start of + info and html. + + * srfi-modules.texi (SRFI-1 Deleting): Rewrite delete and + delete-duplicates, adding behaviour details specified by srfi-1. + +2003-05-12 Kevin Ryde <user42@zip.com.au> + + * preface.texi (Guile License): Refer to COPYING.LIB. + + * repl-modules.texi (Loading Readline Support, Readline Options): + Index entries for readline functions. + + * scheme-control.texi (Handling Errors): Fix regexp error key, should + be `regular-expression-syntax'. + + * scheme-data.texi (Complex): Show z argument in prototypes. + +2003-05-10 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Reals and Rationals): Fix typo @result{#f}, and + put @result outside @code. + + * scheme-data.texi (Bitwise Operations): Note negatives are treated as + infinite precision twos complement. Revise `ash' to emphasise this + for right shifts of negatives. Describe integer-length behaviour on + negatives. Add `...' to logand, logior, logxor since they take + multiple parameters. + * guile.texi (m): New macro. + + * scheme-control.texi (Handling Errors): Revise C support section to + get index entries, and clarify parameters. Remove scm_regex_error, no + longer exists and wasn't available to applications. + + * scheme-control.texi (Handling Errors): Index entries for error keys. + +2003-05-08 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Bitwise Operations): Fix lognot to ones-complement. + + * slib.texi (JACAL): Fix @ref title. + Add index entries, use @file and @code variously. + +2003-05-06 Kevin Ryde <user42@zip.com.au> + + * scheme-scheduling.texi (C level thread interface): Use @deftypefn + not @deftypefun, to get function names (not types) indexed. + + * scheme-options.texi (Build Config): Add index entries for + %guile-build-info keys. + +2003-05-04 Kevin Ryde <user42@zip.com.au> + + * scheme-data.texi (Integer Operations): Describe how quotient, + remainder and modulo round their results. + + * scheme-io.texi (Reading): In read-char and peek-char, fix typos "?" + in @rnindex. In port-column, use @: after i.e. + (Writing): In get-print-state, two spaces after full stop. Add write, + revise display. + + * srfi-modules.texi (SRFI-1 Length Append etc): Add count. + (SRFI-1 Fold and Map): In reduce, fix typo "... variant of fold", add + "f" to fold call shown. In reduce-right, use @code on "reduce". + + * data-rep.texi, gh.texi: Add spaces after some @defun names. + * posix.texi (Processes): Fix typo "hhhh". + +2003-05-01 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi: Add index entries for many variables and functions, + either using @defvar/@deffn or @vindex/@pindex. (Patch supplied + by Kevin Ryde.) + +2003-04-30 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * posix.texi (scm_c_port_for_each): Added. + +2003-04-26 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Symbol Primitives): Document scm_str2symbol + and scm_mem2symbol. + + * data-rep.texi (Describing a New Type): Clarify that + scm_make_smob_type_mfpe is deprecated. (Thanks to + tomas@fabula.de.) + + * scheme-control.texi (Handling Errors): Remove scm_sysmissing, + long since gone from libguile. (Thanks to Kevin Ryde.) + +2003-04-23 Rob Browning <rlb@defaultvalue.org> + + * posix.texi (Processes): add documentation for system*. + +2003-04-05 Marius Vollmer <mvo@zagadka.de> + + * preface.texi: Reflect change to LGPL. + +2003-03-27 Rob Browning <rlb@defaultvalue.org> + + * scheme-io.texi (Reading): clarify character ordering in port for + unread-string. + +2003-03-07 Rob Browning <rlb@defaultvalue.org> + + * guile.texi: change MANUAL_EDITION to MANUAL-EDITION so we don't + choke TeX (thanks to Dale P. Smith). + + * preface.texi: change MANUAL_EDITION to MANUAL-EDITION so we + don't choke TeX (thanks to Dale P. Smith). + +2003-01-02 Mikael Djurfeldt <djurfeldt@nada.kth.se> + + * scheme-scheduling.texi (Low level thread primitives): Fixed typo + in broadcast-condition-variable. + +2002-12-08 Rob Browning <rlb@defaultvalue.org> + + * scheme-options.texi (Build Config): add effective-version docs. + +2002-11-17 Neil Jerram <neil@ossau.uklinux.net> + + Applied patches from Stephen Compall as follows. (Thanks!) + + 2002-11-06 Stephen Compall <rushing@sigecom.net> + + * posix.texi: Changed quotes to match Texinfo expectations. + + Added references to the glibc manual. + + Used proper Texinfo text marking for many keywords, such as @code, + @samp, @env, @var. + + Fixed argument metasyntactic variable references in + file-manipulation section so the usage in the descriptions matches + the usage in the declarations. + + 2002-10-26 Stephen Compall <rushing@sigecom.net> + + * scheme-data.texi: Addition and change of many Texinfo tags, + particularly usage of @var and @samp, as well as reformatting of + some lists into tables and usage of @result. + + Notes about some things I didn't understand, as well as a + missing section on non-control characters. + +2002-10-27 Gary Houston <ghouston@arglist.com> + + * scheme-modules.texi (Environments): only available when + (ice-9 r5rs) is used. + * scsh.texi (The Scheme shell (scsh)): current url is www.scsh.net. + +2002-10-27 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-scheduling.texi: Updated mutex and condition varable + functions. + +2002-10-27 Neil Jerram <neil@ossau.uklinux.net> + + * debugging.texi (Debugging Features): Rewritten. + +2002-10-19 Neil Jerram <neil@ossau.uklinux.net> + + * new-docstrings.texi, scheme-binding.texi, scheme-io.texi, + scheme-scheduling.texi, posix.texi: Automatic docstring updates. + +2002-10-14 Marius Vollmer <mvo@zagadka.ping.de> + + * intro.texi (Whirlwind Tour): Added pointer to examples + directory. + +2002-10-10 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-scheduling.texi (System Asyncs): Updated. + +2002-10-07 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-scheduling.texi (Asyncs): Updated. + * posix.texi (sigaction): Updated. + +2002-10-03 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Processes), scheme-options.texi (Common Feature + Symbols): Refer to provided? rather than deprecated feature?. + +2002-10-03 Marius Vollmer <mvo@zagadka.ping.de> + + * tools.texi (How guile-snarf works): Updated. + (Writing your own snarfing macros): New. + +2002-09-25 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-debug.texi (Debugging): Make sections into nodes. + (Debugging Options): Node removed. + + * scheme-options.texi (Feature Tracking): Brought forward before + sections on options. + (Runtime Options): New section, to group options-related nodes. + +2002-09-24 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-options.texi (Options and Config): Chapter name changed, + and intro text improved. + (Install Config): Brought forward, and renamed Build + Configuration. + + The following doc updates are from Ian Sheldon - thanks! + + * scheme-data.texi (Appending Strings, Regexp Functions, Match + Structures): Add examples. + (Regular Expressions): Add instruction to use (ice-9 regex) + module. + + * slib.texi (SLIB): Remove duplicate `the'. + +2002-09-22 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-options.texi (General option interface): Mention + eval-options-interface and debug-options-interface. + + * scheme-debug.texi (Debugging): New node describing source + properties. + +2002-09-19 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-utility.texi (Hook Reference): Improvements to hook docs. + Thanks to Thien-Thi Nguyen for the patches. + +2002-09-16 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-data.texi (Symbol Props): It's "set-symbol-property!", + not "set-symbol-property". Thanks to Pieter Pareit! + +2002-09-15 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-data.texi: Tell them to use 'provided?' instead of + '*feaures*'. + +2002-09-09 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-ideas.texi (Creating a Procedure): Fixed typo. Thanks to + Pieter Pareit! + + * intro.texi: Updated GNu ftp server name. Use "-lguile" instead + of "libguile.a". Some small fixes/improvements. + + * scheme-reading.texi: Added www.schemers.org. Removed foldoc, + it's too generic. Updated 'teach yourself ...' URL. + +2002-08-27 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-modules.texi: Markup fixes and removal of gh_ references. + Thanks to Dale Smith! + +2002-08-14 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-evaluation.texi (eval-string): Updated. + + * scheme-scheduling.texi (Fluids): Touched up a bit, added + with-fluids. + +2002-08-13 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-modules.texi (More Modules Procedures): Removed. + (Accessing Modules from C): New. + +2002-08-10 Gary Houston <ghouston@arglist.com> + + * scheme-procedures.texi: new section Primitive Procedures, + documentation for scm_c_make_gsubr and scm_c_define_gsubr. + * scheme-modules.texi (Compiled Code Modules): replace + gh_new_procedure with scm_c_define_gsubr. + +2002-08-08 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (Data types and constants defined by gh): Avoid + generating index entry for SCM. + + * posix.texi (Runtime Environment): Remove duplicate doc for + setenv. + + * data-rep.texi, scheme-memory.texi, scheme-modules.texi: Merge + recent updates from stable branch. + + * posix.texi (File System, Time, Pipes, Network Databases, + Internet Socket Examples): Add examples provided by Ian Sheldon. + +2002-08-08 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-binding.texi: Don't talk about 'bound?' which is gone. + Thanks to Christopher Cramer. + +2002-08-06 Han-Wen Nienhuys <hanwen@cs.uu.nl> + + * scheme-memory.texi (Memory Blocks): add scm_calloc, scm_gc_calloc. + correct typos. + +2002-08-05 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * intro.texi, srfi-modules.texi: Added (use-modules (ice-9 + rdelim)) to an example that uses read-line. Thanks to Ralf + Mattes! + + * scheme-memory.texi: Added an introductory blurb about GC that I + had lying around. + +2002-08-02 Gary Houston <ghouston@arglist.com> + + * scheme-modules.texi: split "Scheme and modules" into + "provide and require" and "Environments". Mention R5RS + environments. + +2002-07-16 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-options.texi (Debugger options): New subsection + describing stack overflow and what to do about it. + +2002-07-10 Gary Houston <ghouston@arglist.com> + + * scheme-modules.texi (Compiled Code Modules): Removed description + of scm_register_module_xxx, which no longer exists. A description + of current techniques is needed. + +2002-05-09 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-data.texi (Numbers): Added description of the new values + +inf.0, -inf.0 and +nan.0. + + * posix.texi (Runtime Environment): Added entries for 'setenv' and + 'unsetenv'. + +2002-04-28 Marius Vollmer <mvo@zagadka.ping.de> + + * gh.texi, data-rep.texi: Moved `@deftyp {Data type} SCM' line + from gh.texi to data-rep.texi. Both files already had similar + descriptions for SCM. Given that gh.texi is deprecated, looking + up `SCM' in the index should take one to the primary location + rather than deprecated section. Hence this change. Added + `@deftp' for scm_t_bits data type so that a proper index entry is + added for this. Thanks to Richard Y. Kim! + + * data-rep.texi (Subrs): Changed scm_make_gsubr to + scm_c_define_gsubr. Thanks to Richard Y. Kim! + +2002-04-24 Marius Vollmer <mvo@zagadka.ping.de> + + * srfi-modules.texi (SRFI-13 Miscellaneous): Updated docs of + string-tokenize. + +2002-04-20 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-intro.texi (Scheme Layout), scm.texi (Reference Layout): + Node moved from a to b. + + * guile.texi (Scheme Intro, Basic Ideas, Guile Scripting, Command + Line Handling, Debugging Features, Autoconf Support, Miscellaneous + Tools, Further Reading): Moved to new Part II. + + * preface.texi (Manual Layout): Part numbers updated accordingly. + + * guile.texi (Top): Move API Overview node to beginning of Guile + API Reference part. + (Part II: Writing and Running Guile Scheme): New part; will + contain content from `Programming with Guile' that pertains to + writing and using Guile on the Scheme level. + + * scm.texi (API Overview): Renamed from `Guile API'. + + * guile.texi (Top), scheme-modules.texi (Included Guile Modules): + Debugger User Interface node renamed Debugging Features. + + * debugging.texi (Stacks and Frames): Node deleted; non-duplicated + material moved to scheme-debug.texi. + (Debugging Features): Renamed from `Debugger User Interface'. + + * scheme-debug.texi (Debugging): Rename chapter `Debugging + Infrastructure' and reorganize its contents. + + * scheme-debug.texi (Debugging), scheme-control.texi (Handling + Errors): Move display-error to error-focussed section. + + * scheme-debug.texi (Debugging), debugging.texi (Backtrace): Move + backtrace to user-level debugging chapter. + + * scheme-debug.texi (Debugging), scheme-procedures.texi (Procedure + Properties): Move procedure-name, procedure-source and + procedure-environment to procedures chapter. + + * scheme-debug.texi (Debugging), scheme-memory.texi (Memory + Blocks): Move malloc-stats to memory management chapter. + + * scheme-procedures.texi (Syntax Rules): Remove mention of + use-modules for loading syncase; only use-syntax really works. + Thanks to Panagiotis Vossos for spotting this. + + * program.texi (Scheme vs C): New node, with existing material + taken from chapter intro. + (Programming Overview): New intro para to introduce example of + Guile integration: + (Extending Dia): New node. + +2002-04-17 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (CLEANFILES): Added guile.cps, guile.fns, guile.rns, + guile.tps, guile.vrs, guile.tmp. + +2002-04-01 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-intro.texi (Scheme Layout): Remove reference to defunct + Guile Extensions index. + + * guile.texi: Removed Guile Extensions index. + + * scheme-indices.texi (Guile Extensions Index): Removed. + + * guile.texi: Remove vgone, vdeprecated, vchanged and vnote + macros; they're not actually useful after all. Update copyright + years. + + * scheme-compound.texi (Vectors): Make subsections into nodes. + (Vectors): Review, slightly reorg and clarify docs in this + section. + + * scheme-data.texi (Symbols): Reorganized node substructure and + added lots of explanatory text around the @deffn's. + +2002-03-29 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-modules.texi (Variables): Mention obarrays. + + * scheme-data.texi (Symbol Tables, Symbol Props): Remove vgone + markers for deprecated symbol items. + (Symbol Props): Remove doc for obsolete 2 arg version of + symbol-interned?. + (String Miscellanea): Removed, since it only contained duplicate + doc for string-ci->symbol. + (Symbol Tables): Move doc for gensym to Symbol Primitives; rest of + section removed. + + * posix.texi (Ports and File Descriptors), scheme-evaluation.texi + (Fly Evaluation): Remove vgone markers for close-all-ports-except, + eval2 and read-and-eval!. + + * data-rep.texi (Describing a New Type), scheme-compound.texi + (Append/Reverse), scheme-procedures.texi (Internal Macros): + Trivial updates to sync with stable branch. + +2002-03-27 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-compound.texi (List Searching): Remove docs for + `scm_sloppy_mem*', which no longer exist. + +2002-03-24 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi (Top), intro.texi (What is Guile?, The Basic Guile + Package): Use @ifnottex instead of @ifinfo, so that HTML + generation works correctly. + +2002-03-24 Marius Vollmer <mvo@zagadka.ping.de> + + * tools.texi: Updated to reflect changes to the guile-snarf tool. + +2002-03-16 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-utility.texi (Hooks): Further updates. New material on + GC hooks. + + * scheme-evaluation.texi (Fly Evaluation): Note disappearance of + eval2 and read-and-eval!. + + * deprecated.texi (Deprecated): Remove docs about previously + deprecated items that have now been removed. + +2002-03-15 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * tools.texi (guile-1.4 guile-snarf): Remove this node. + (How guile-snarf works): Update usage and description to + no longer mention "--compat=1.4" and instead "-d" and "-D". + (Macros guile-snarf recognizes): Add list of deprecated macros + and blurb. Add cindex for deprecated macros. + +2002-03-15 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-utility.texi (Hooks): Reviewed and updated. + + * scheme-options.texi (Feature Tracking): New section. + + * scheme-data.texi (Arithmetic, Primitive Numerics): Add + description of corresponding C functions. + + * scheme-utility.texi (Object Properties): Revamp documentation on + object properties. + + * scheme-memory.texi (Weak References): Update reference to Object + Properties node. + + * guile.texi: Add macros for describing version information. + + * scheme-data.texi, scheme-debug.texi, scheme-io.texi, + scheme-procedures.texi: Automatic updates from snarfed libguile + docstrings. + +2002-03-13 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am (guile_toc.html): Look for guile.texi in $(srcdir). + + * tools.texi (How guile-snarf works): Mention "--compat=1.4", and + new processing steps. Update usage example, makefile frag. + + (guile-1.4 guile-snarf): New subsubsection under + "Init Snarfing with guile-snarf". + +2002-03-12 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-compound.texi, scheme-data.texi, new-docstrings.texi: + Automatic updates from snarfed libguile docstrings. + + * data-rep.texi, guile.texi, scheme-evaluation.texi, + scheme-options.texi, scheme-translation.texi: Various minor + enhancements ported from the stable CVS branch. + +2002-03-08 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * tools.texi (Miscellaneous Tools): New node/chapter. + (Snarfing, Init Snarfing with guile-snarf, How guile-snarf works, + Macros guile-snarf recognizes, Doc Snarfing): New nodes/(sub)sections. + (Executable Modules): Now a section under "Miscellaneous Tools". + + * guile.texi (Miscellaneous Tools): Add under "Part II". + Implement by including tools.texi. + + * Makefile.am (guile_TEXINFOS): Add tools.texi. + +2002-03-07 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * tools.texi: New file. + +2002-03-03 Neil Jerram <neil@ossau.uklinux.net> + + * autoconf.texi (Autoconf Background): Insert missing `of'. + +2002-03-01 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * api.txt, data-rep.texi: Renamed the struct scm_cell to + scm_t_cell. + + * data-rep.texi: Renamed scm_alloc_cell to scm_cell and + scm_alloc_double_cell to scm_double_cell. + +2002-03-01 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-memory.texi (Upgrading from scm_must_malloc et al): New + section. + +2002-02-28 Marius Vollmer <mvo@zagadka.ping.de> + + * data-rep.texi: Use scm_gc_malloc and scm_gc_free instead of + scm_must_malloc and free in example code. Updated text for the + new memory management functions. + + * scheme-debug.texi (malloc-stats): Refer to scm_gc_malloc instead + of to scm_must_malloc. + +2002-02-27 Stefan Jahn <stefan@lkcc.org> + + * gh.texi (scm transition summary): Documented some more + gh equivalents and removed appropriate FIXME's. + +2002-02-26 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am: Update path to pre-inst-guile automake frag. + +2002-02-24 Rob Browning <rlb@defaultvalue.org> + + * .cvsignore: add autoconf-macros.texi. + + * Makefile.am (CLEANFILES): add autoconf-macros.texi. + +2002-02-19 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-memory.texi (Memory Blocks): New section. + +2002-02-05 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am: Include $(top_srcdir)/pre-inst-guile.am. + + (GUILE): Delete var. + (autoconf-macros.texi): Use $(preinstguiletool). + +2002-02-04 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * autoconf.texi (Autofrisk, Using Autofrisk): New sections. + (Autoconf Support): Add new sections to menu. + +2002-02-04 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * scheme-data.texi (Symbol Uninterned): Added node. + +2002-01-29 Stefan Jahn <stefan@lkcc.org> + + * gh.texi (scm transition summary): Documented gh equivalents + `scm_c_string2str', `scm_c_substring2str' and `scm_c_symbol2str' + and removed the appropriate FIXME's. + +2002-01-14 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * Makefile.am (autoconf-macros.texi): Also set GUILE_LOAD_PATH + when invoking the uninstalled guile executable. + +2002-01-09 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * Makefile.am (autoconf-macros.texi): Fix build bug: + Write this file to srcdir. Thanks to I. N. Golubev. + +2002-01-08 Gary Houston <ghouston@arglist.com> + + * Makefile.am: attempt to use guile from $(top_builddir)/libguile + when building autoconf-macros.texi. There are still problems with + modules and running makeinfo when builddir != srcdir. + +2002-01-08 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * data-rep.texi, gh.texi, guile.texi, intro.texi, + misc-modules.texi, new-docstrings.texi, posix.texi, program.texi, + repl-modules.texi, scheme-binding.texi, scheme-compound.texi, + scheme-control.texi, scheme-data.texi, scheme-debug.texi, + scheme-ideas.texi, scheme-io.texi, scheme-memory.texi, + scheme-modules.texi, scheme-procedures.texi, + scheme-translation.texi, scheme-utility.texi, scm.texi, slib.texi, + srfi-modules.texi: Spell check. Thanks to Fabrice Bauzac. + +2002-01-07 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi (Linking Programs With Guile): Fix typo (superfluous + `do'). Thanks to Fabrice Bauzac. + +2002-01-05 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * intro.texi: Spell check. Thanks to Fabrice Bauzac. + +2002-01-02 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * guile.texi (Part II): Add "Autoconf Support"; include + autoconf.texi. + + * Makefile.am (guile_TEXINFOS): Add autoconf.texi and + autoconf-macros.texi. + (autoconf.texi, autoconf-macros.texi): New rules. + + * autoconf.texi: New file. + +2001-12-22 Marius Vollmer <mvo@zagadka.ping.de> + + * scheme-compound.texi (Alist Example): Changed "Bismarck" to + "Pierre". Thanks to Ron Peterson! + +2001-12-22 Neil Jerram <neil@ossau.uklinux.net> + + * program.texi (Programming Overview): Chapter renamed from + `Programming Options'; some new material added. + +2001-12-07 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (Guile API): Renamed from `Scheme Primitives' and + broadened so that this chapter discusses the Guile API as a whole. + + * program.texi (Available Functionality): Revise so that text + reads better. + + * guile.texi (Programming Intro): New introductory text. + + * scheme-ideas.texi (Definition): Reorder reference bullets in + ascending page number order. + +2001-12-04 Martin Grabmueller <mg@glug.org> + + * scheme-procedures.texi (Optional Arguments): Typo fix: wither -> + either. + +2001-12-01 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Hooks): Moved into scheme-utility.texi. + + * Makefile.am (guile_TEXINFOS): Added scheme-compound.texi. + + * scheme-data.texi (Variables): Node moved to modules chapter. + (Symbol Read Syntax): New node, with syntax-related material taken + from old Symbols node. + (Symbol Primitives): Renamed from `Symbols'. + (Symbols and Variables): Renamed to `Symbols'. + (Symbol Props): Renamed from `Symbol Tables'. + (Symbols): General review, improvements and additional material + throughout this section. + (Other Data Types): New material: links to object types documented + elsewhere. Also renamed node to `Other Types'. + (Data Types): Split into two: `Simple Data Types' and `Compound + Data Types'. Introductory blurbs rewritten accordingly. + + * guile.texi: Updated Notes comment. + + * scheme-data.texi (Rx Interface): Node moved to Guile Modules + part, as the Rx interface is not core Guile. + +2001-11-30 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (String Miscellanea): Removed, moving doc for + string-ci->symbol into the node on Symbols. + + * Makefile.am (ETAGS_ARGS): Added. + + * scheme-data.texi (Symbol Tables): Removed doc for gentemp, + intern-symbol, string->obarray-symbol, symbol-binding, + symbol-bound?, symbol-set!, unintern-symbol, symbol-interned?; all + of which no longer exist. + +2001-11-25 Thien-Thi Nguyen <ttn@glug.org> + + * posix.texi: Fix spelling. Thanks to Chris Cramer. + Reword `getpass' intro blurb. + +2001-11-23 Neil Jerram <neil@ossau.uklinux.net> + + * program.texi (Program Control): Remove spurious placeholder + text. + +2001-11-20 Thien-Thi Nguyen <ttn@glug.org> + + * scheme-options.texi (Install Config): + Tweak `%load-path' verb to not imply it's a proc. + Add documentation for `%guile-build-info'. + +2001-11-19 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Symbol Tables), new-docstrings.texi: Removed + doc for builtin-bindings (no longer exists). + (Variables): Expanded existing description of variables. Removed + doc for builtin-variable (no longer exists). + + * scheme-binding.texi (Top Level): New docs for define, scm_define + and scm_c_define. Also clarified point about interchangeability + of define and set!. + +2001-11-18 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Vectors): Autoupdate docs for + vector-move-left! and vector-move-right!. + +2001-11-16 Neil Jerram <neil@ossau.uklinux.net> + + * debugging.texi, deprecated.texi, intro.texi, misc-modules.texi, + new-docstrings.texi, posix.texi, scheme-binding.texi, + scheme-control.texi, scheme-data.texi, scheme-debug.texi, + scheme-evaluation.texi, scheme-io.texi, scheme-memory.texi, + scheme-modules.texi, scheme-options.texi, scheme-procedures.texi, + scheme-scheduling.texi, scheme-translation.texi, + scheme-utility.texi, script-getopt.texi, srfi-modules.texi: Change + category for "primitive" and "procedure" @deffn's to {Scheme + Procedure}; add @deffnx lines for {C Function}s; automatic updates + from libguile docstring changes. + + * scheme-memory.texi (Garbage Collection): Removed doc for removed + `unhash-name'. + +2001-11-14 Thien-Thi Nguyen <ttn@glug.org> + + * scheme-procedures.texi: Spell "library" correctly. + +2001-11-13 Neil Jerram <neil@ossau.uklinux.net> + + * new-docstrings.texi, scheme-data.texi: Merge recent doc + improvements from stable branch. + + * scheme-options.texi: Automatic updates from docstring changes in + libguile's C source code. + +2001-11-12 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Vtables, Structure Basics): Automatic doc + updates for struct? and struct-vtable?. + (String Searching): Add missing "for". Thanks to Scott Lenser. + +2001-11-08 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi (Top): Added new chapter `Programming Options'. + + * program.texi: New file. + + * Makefile.am (guile_TEXINFOS): Added program.texi. + +2001-11-07 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-memory.texi, scheme-io.texi, scheme-debug.texi, + scheme-data.texi, scheme-binding.texi, posix.texi, + new-docstrings.texi: Automatic updates from improved libguile + docstrings. + +2001-11-04 Neil Jerram <neil@ossau.uklinux.net> + + * preface.texi: Use MANUAL_EDITION variable. + (Manual Layout): Updated to reflect reorg. + + * guile.texi (MANUAL_EDITION): New variable, with value + incremented from 1.0 to 1.1 to reflect the reorg described here. + (Top): Use MANUAL_EDITION variable. + + * scheme-indices.texi (R5RS Index, Guile Extensions Index): Use + @unnumbered rather than @chapter for these indices. + + * guile.texi (Top): A little top-level reshuffling, with the aims + that: (1) the `Guile Scheme' (reference) part of the manual + becomes the `Guile API Reference', and covers both Scheme and C + interfaces; (2) non-API-reference material such as the `Basic + Ideas in Scheme' chapter is collected together to form a new part + `Programming with Guile'. This new part will contain general + documentation on using and programming Guile in both Scheme and C, + including - for example - awareness of GC when C programming, how + to use the snarf macros, how to debug ... + (Top): Move inclusion of scheme-indices.texi so that all indices + appear together in the printed manual. + + * Makefile.am (guile_TEXINFOS): Removed appendices.texi, added + debugging.texi. + + * appendices.texi: Removed. + + * debugging.texi (Debugger User Interface): New file, same as the + material that used to be in appendices.texi, but now a chapter in + Part II rather than an appendix. + + * appendices.texi (Obtaining and Installing Guile): Moved to + become a chapter in ... + * intro.texi: ... Part I: Introduction to Guile. + + * scm.texi (I/O Extensions): Moved to become a section of ... + * scheme-io.texi (Input and Output): ... this chapter. + + * scm.texi (Handling Errors): Moved to become a section of ... + * scheme-control.texi (Control Mechanisms): ... this chapter. + +2001-11-06 Thien-Thi Nguyen <ttn@glug.org> + + * srfi-modules.texi (SRFI-19, SRFI-19 Constants, SRFI-19 Current + time and clock resolution, SRFI-19 Time object and accessors, + SRFI-19 Time comparison procedures, SRFI-19 Time arithmetic + procedures, SRFI-19 Date object and accessors, SRFI-19 + Time/Date/Julian Day/Modified Julian Day converters, SRFI-19 Date + to string/string to date converters): New nodes. + (SRFI Support): Add "SRFI-19" to menu. + +2001-11-06 Marius Vollmer <mvo@zagadka.ping.de> + + * scripts.texi: Document `--debug' and `--no-debug'. + +2001-10-27 Gary Houston <ghouston@arglist.com> + + * guile.texi, scsh.texi: removed obsolete guile-scsh material + and updated links (I don't know if it should remain in the + main menu. It's like slib I think.) + + * minor updates to the slib installation notes. + +2001-10-05 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-evaluation.texi (Fly Evaluation): Removed documentation + for `read-and-eval!' and `eval2'. (Thanks to Alex Schroeder for + noticing that they'd disappeared!) + +2001-10-05 Thien-Thi Nguyen <ttn@glug.org> + + * scheme-io.texi (Writing): Add entry for `display'. + Include in R5RS Index. Thanks to Alex Schroeder for suggestion. + +2001-09-26 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * srfi-modules.texi (SRFI-13): Tyop fix. + (SRFI-13): Changed paragraph about bindings both in the code and + in SRFI-13. + + * misc-modules.texi (Formatted Output): Tyop fix. + (Formatted Output): Document ~g properly. + + Thanks to Alex Schroeder for pointing out the typos and sending + suggestions. + +2001-09-25 Thien-Thi Nguyen <ttn@glug.org> + + * scheme-procedures.texi (Syntax Rules): Add `cindex' directive. + Thanks to suggestion by Alex Schroeder. + +2001-08-30 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi (Top): Group all index nodes together so that + `Info-index' works more effectively in Info. Thanks to Eric + Hanchrow for the report and fix. + + * scheme-data.texi (Random, String Syntax, String Modification, + Regular Expressions), scheme-ideas.texi (Definition), + scheme-modules.texi (Dynamic Linking and Compiled Code Modules), + scm.texi (Transforming Scheme name to C name, Port + Implementation): Various typo fixes and clarifications merged from + the stable CVS branch. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi: Merged wording fixes from stable CVS branch. + + * Makefile.am (guile_TEXINFOS): Remove ../AUTHORS. + + * guile.texi: Incorporate text previously in separate AUTHORS + file. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + The change log for files in this directory continues backwards + from 2001-08-27 in ../ChangeLog, as all the Guile documentation + prior to this date was contained in a single directory. + + +;; Local Variables: +;; coding: utf-8 +;; End: diff --git a/doc/ref/ChangeLog-goops-2008 b/doc/ref/ChangeLog-goops-2008 new file mode 100644 index 000000000..a5a637d7b --- /dev/null +++ b/doc/ref/ChangeLog-goops-2008 @@ -0,0 +1,76 @@ +2008-02-06 Neil Jerram <neil@ossau.uklinux.net> + + * goops-tutorial.texi (Next-method): Minor improvements to the + text. + +2006-09-28 Neil Jerram <neil@ossau.uklinux.net> + + * goops.texi (Slot Options): Added example from Ludovic Courtès + about difference between init-value, -form and -thunk. + +2006-04-21 Kevin Ryde <user42@zip.com.au> + + * hierarchy.pdf: New file, converted from hierarchy.eps using + epstopdf, to let "make pdf" work. + * Makefile.am: (goops_TEXINFOS): Add it. + +2006-03-08 Ludovic Courtès <ludovic.courtes@laas.fr> + + * goops.texi (Slot Options): Note init-value is shared. + +2006-02-06 Marius Vollmer <mvo@zagadka.de> + + * goops.texi (Basic Generic Function Creation): Added blurb about + merge-generics duplicates handler from NEWS. + +2004-06-28 Marius Vollmer <marius.vollmer@uni-dortmund.de> + + * Makefile.am: Removed home-grown code for HTML generation. + Automake does it for us now. + (goops_TEXINFOS): Added hierarchy.png + + * hierarchy.png: New file. + +2004-05-19 Kevin Ryde <user42@zip.com.au> + + * Makefile.am (CLEANFILES): Remove, goops.tmp goops.cps cleaned by + automake these days. + +2003-04-17 Mikael Djurfeldt <djurfeldt@nada.kth.se> + + * goops.texi (Object Comparisons): Removed object-eqv? and + object-equal? and added eqv?, equal? and =. + +2003-01-10 Mikael Djurfeldt <djurfeldt@nada.kth.se> + + * goops.texi (Class Redefinition): Clarifications; Removed + mentioning of change-object-class. + +2002-11-07 Neil Jerram <neil@ossau.uklinux.net> + + * goops.texi (Top): Say "Indices" before index nodes in main menu. + (Index): Removed (it was empty). Generally remove unnecessary + padding text that looks bad in HTML. + +2002-04-17 Marius Vollmer <mvo@zagadka.ping.de> + + * Makefile.am (CLEANFILES): Added goops.tmp, goops.cps. + +2001-12-03 Thien-Thi Nguyen <ttn@giblet.glug.org> + + * goops.texi: Grammar fix. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + * Makefile.am (goops_TEXINFOS): Remove ../AUTHORS. + (TEXINFO_TEX): Added; avoids shipping multiple copies of + texinfo.tex in a single distribution. + + * goops.texi: Incorporate text previously in separate AUTHORS + file. + +2001-08-27 Neil Jerram <neil@ossau.uklinux.net> + + The change log for files in this directory continues backwards + from 2001-08-27 in ../ChangeLog, as all the Guile documentation + prior to this date was contained in a single directory. diff --git a/doc/ref/ChangeLog-guile-doc-ref b/doc/ref/ChangeLog-guile-doc-ref new file mode 100644 index 000000000..3d2cc4e09 --- /dev/null +++ b/doc/ref/ChangeLog-guile-doc-ref @@ -0,0 +1,890 @@ +2001-03-09 Neil Jerram <neil@ossau.uklinux.net> + + Moving texinfo files from guile-doc/ref into guile-core/doc: + + * env.texi, indices.texi, mbapi.texi, mltext.texi, scripts.texi, + scsh.texi, tcltk.texi, hierarchy.txt, scheme-indices.texi, + slib.texi, deprecated.texi, scheme-binding.texi, appendices.texi, + scheme-intro.texi, goops.texi, extend.texi, gh.texi, intro.texi, + preface.texi, scm.texi, goops-tutorial.texi, hierarchy.eps, + r4rs.texi, r5rs.texi, texinfo.tex, scheme-reading.texi, + data-rep.texi, scheme-utility.texi, posix.texi, + scheme-control.texi, scheme-debug.texi, scheme-evaluation.texi, + scheme-io.texi, scheme-memory.texi, scheme-modules.texi, + scheme-options.texi, scheme-procedures.texi, + scheme-scheduling.texi, scheme-translation.texi, guile.texi, + scheme-data.texi, scheme-ideas.texi, expect.texi: Removed. + +2001-02-28 Gary Houston <ghouston@arglist.com> + + * expect.texi (Expect): add missing eof? argument in example code. + +2001-02-27 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi, scheme-data.texi, scheme-ideas.texi: Remove the code + that set paragraph indent to zero, then add @noindent to several + places that need not to be indented. + +2001-02-24 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (File System, Time), scheme-control.texi + (Exceptions), scheme-data.texi (Complex, Primitive Numerics, + Random, String Fun, Symbols and Variables, Lists, Bit Vectors, + Hooks), scheme-debug.texi (Debugging), scheme-evaluation.texi + (Reader Extensions, Scheme Read, Fly Evaluation, Loading, + Evaluator Options), scheme-io.texi (Reading, Writing, Default + Ports, File Ports), scheme-memory.texi (Garbage Collection, + Guardians, Objects), scheme-modules.texi (The Guile module + system), scheme-options.texi (Install Config), + scheme-procedures.texi (Procedure Properties, Procedures with + Setters), scheme-scheduling.texi (Arbiters, Asyncs), + scheme-translation.texi (Emacs Lisp Support): Automatic docstring + updates. + + * scheme-io.texi (Binary IO): New node. + + * scheme-control.texi (Multiple Values): New node. + +2001-02-23 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-utility.texi (Sorting), scheme-procedures.texi (Procedure + Properties), scheme-memory.texi (Guardians), scheme-io.texi + (Line/Delimited), scheme-data.texi (String Fun, Symbols and + Variables, Vtables), posix.texi (Ports and File Descriptors, File + System, Network Sockets and Communication): Automatic docstring + updates. + +2001-02-15 Neil Jerram <neil@ossau.uklinux.net> + + * data-rep.texi: Preserve, in comments beginning `@c essay', + material from the standalone version of this essay which is very + soon to be retired from its current location at + guile-core/doc/data-rep.texi. + + * data-rep.texi: Incorporate recent changes to smob example + documentation from the standalone version of this essay. + +2001-02-02 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-reading.texi (Further Reading): Add reference to online + version of SICP. + +2001-01-27 Neil Jerram <neil@ossau.uklinux.net> + + Further changes to get everything to build to dvi with the latest + texinfo.tex. + + * texinfo.tex: Replaced by latest version from ftp.gnu.org. + + * r5rs.texi (Binding constructs): Remove @c inside @t{...} at + lines 2207-2209. + (Lexical structure): Remove @c inside @t{...} at line 7517. + + * r4rs.texi (Example): Remove @c inside @t{...} at lines 6557 and + 6569. + +2001-01-26 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (Handling Errors): Improved markup. + (snarfing): Deleted. + + * data-rep.texi: File copied here from sources directory and + integrated into the reference manual structure. + + * extend.texi (Libguile Intro): New file, new node, to introduce + new Part. + + * guile.texi: Merged Parts V and VI into a single Part: "Extending + Applications Using Guile". Improved some top level node names and + descriptions. Include extend.texi and data-rep.texi. + + * preface.texi (Manual Layout): Updated according to merge of + Parts V and VI. + + * gh.texi: Restructured into a single chapter. + + * scm.texi (C Port Interface, Port Implementation): Moved here + from scheme-io.texi. + + * scheme-io.texi (Default Ports): Renamed from `Port + Environment'. + (Port Internals): Contents moved to scm.texi. + + * r5rs.texi: Changes to allow building of r5rs.dvi from r5rs.texi. + Aubrey Jaffer's view - which I agree with - is that, given that + people have the option of building r5rs.dvi from the original + LaTeX distribution for R5RS, it is not worth fixing his master + copy of r5rs.texi and the tool which autogenerates it. On the + other hand, it is a marginal convenience for people to be able to + build hardcopy from r5rs.texi, even if the results are less good + than with the original LaTeX. Hence the following fixes. + (lines 714, 725, 728, 1614, 2258): Remove invalid parentheses from + @deffn statements. + (line 2316): Change @deffnx to @deffn, and insert `@end deffn' to + terminate preceding @deffn. + (line 7320): Insert `@c ' at beginning of lines that are intended + to be @ignore'd. + + * guile.texi, r4rs.texi, r5rs.texi: Align @direntry descriptions + to start in column 32. + +2001-01-24 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi: Licensing and Layout material moved to + preface.texi. + (Whirlwind Tour): New chapter as top level for preexisting + sections. + + * guile.texi: Various minor changes to improve the structure at + the beginning of the reference manual. + + * preface.texi: New file, to split out "prefatory material". + Initially with Licensing and Layout material taken from + intro.texi. + + * Makefile.am (dist_texis): Add preface.texi. + +2001-01-19 Neil Jerram <neil@ossau.uklinux.net> + + * intro.texi: Change R4RS everywhere to R5RS. + (What is Guile?): Change "compiling" to "translating". + +2001-01-07 Neil Jerram <neil@ossau.uklinux.net> + + * appendices.texi (Internals): Content merged into Symbols and + Variables node of scheme-data.texi. + (Reporting Bugs): Moved to manual Part I. + + * guile.texi: Inserted new Part for `Guile Modules' as distinct + from core Guile Scheme language/features. Other parts renumbered + correspondingly. Module chapters moved into new part. + + * intro.texi (Reporting Bugs): Node moved here from + appendices.texi. + + * posix.texi (POSIX): Node name changed from `POSIX System Calls + and Networking'. + + * scheme-data.texi (Symbols and Variables): Added texinfo markup + to docstrings that didn't have it. Expanded snarfed argument + names like `o' and `s' to `obarray' and `string'. + + * scheme-debug.texi (Debugging): Node name changed from `Internal + Debugging Interface'. + + * scheme-evaluation.texi (Fly Evaluation): Moved doc for + `interaction-environment' here (previously under module doc). + + * scheme-memory.texi: Structure reorganization. + + * scheme-modules.texi: Structure reorganization. Removed empty + subsections `First-class Variables' and `First-class Modules'. + + * scheme-options.texi (Options and Config): Node name changed from + `Options'. + (Install Config) Node name changed from `Configuration Data'. + + * scheme-scheduling.texi (Scheduling): Node name changed from + `Threads and Dynamic Roots'. + + * scheme-translation.texi (Translation): New top level node for + translation documentation. + +2001-01-05 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-exceptions.texi: Removed. + + * Makefile.am (dist_texis): Removed scheme-exceptions.texi. + + * guile.texi (Top): Renamed/redescribed some top level nodes. No + longer include scheme-exceptions.texi. + + * scheme-control.texi: Merge material that was previously in + scheme-exceptions.texi. + + * posix.texi: Updated close-port reference. + + * scheme-binding.texi, scheme-control.texi, + scheme-evaluation.texi, scheme-intro.texi, scheme-io.texi, + scheme-procedures.texi, scheme-utility.texi: Massaged into desired + structure. + + * scheme-data.texi (Generic Data Types): Changed to "Data Types". + (Numbers) Introduction streamlined. + (Complex Numbers) New material. + +2001-01-05 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi, scheme-io.texi, scheme-memory.texi, + scheme-options.texi: Where a single docstring documents more than + one primitive, add a docstring comment for each additionally + documented primitive. + + * scheme-modules.texi: Update docstring for dynamic-func. + + * scheme-data.texi (Numbers, Numerical Tower, Integers, Reals and + Rationals, Number Syntax): New material. + + * deprecated.texi (Deprecated): Remove obsolete MD5 comment line. + +2000-12-12 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Numbers): Documentation added for scientific + functions. + + * Makefile.am (dist_texis): Updated following split of scheme.texi + into per-chapter files. + +2000-12-07 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Booleans): Written. + (Numbers): Introduction written, primitives organized into + subsections. + +2000-12-06 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi (Generic Data Types): Added chapter + introduction. + (Bitwise Operations, Random): Moved underneath Numbers. + (Other Data Types): New placeholder section for data types that + are documented elsewhere. + + * scheme-indices.texi, scheme-reading.texi: Added Local Variables + block. + +2000-12-06 Neil Jerram <neil@ossau.uklinux.net> + + This change replaces scheme.texi, which is unmanageably large, by + a set of smaller one-per-chapter files. The set and ordering of + the new files reflects the intended top level structure of the + Guile Scheme part of the reference manual. This structure is not + yet all reflected in the combined Texinfo/Info, though, because I + haven't yet fixed the @node levels appropriately. + + * scheme.texi: Removed, after dividing content into new files. + + * scheme-procedures.texi, scheme-utility.texi, + scheme-binding.texi, scheme-control.texi, scheme-io.texi, + scheme-evaluation.texi, scheme-exceptions.texi, + scheme-memory.texi, scheme-modules.texi, scheme-scheduling.texi, + scheme-options.texi, scheme-translation.texi, scheme-debug.texi, + slib.texi: New files. + + * guile.texi: @include new files instead of scheme.texi. Reorder + existing top level nodes. + +2000-12-01 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-data.texi: Remove @page breaks (following demotion). + + * guile.texi (Top), scheme-ideas.texi: Demote everything one level + so that previous chapters About Data, About Procedures, About + Expressions and About Closure are now combined into a single + Scheme Ideas chapter. Add overall chapter introduction. Fix up + top level nodes accordingly. + + * guile.texi (Top), scheme.texi, scheme-data.texi: Gather material + for Generic Data Types chapter into a new file + (scheme-data.texi). @include new file in guile.texi. Fix up top + level nodes accordingly. (This changes demotes all the affected + material by one level, except for that which was already grouped + together under the Data Structures node.) + + * guile.texi (Top): @include new files. + + * scheme-intro.texi, scheme-ideas.texi: New files. + + * scheme.texi (Guile and R5RS Scheme): Moved introductory chapter + to its own file (scheme-intro.texi). + (About Closure) Chapter completed. + (About Data, About Procedures, About Expressions, About Closure): + Ideas chapters moved to their own file (scheme-ideas.texi); + scheme.texi was just getting too large! + +2000-11-09 Gary Houston <ghouston@arglist.com> + + * posix.texi (Ports and File Descriptors): updated + close-all-ports-except. + +2000-11-07 Gary Houston <ghouston@arglist.com> + + * posix.texi (Ports and File Descriptors): added dup2, close-fdes + and port-for-each. + (Pipes): synchronise open-input-pipe, open-output-pipe with + popen.scm. + +2000-11-04 Gary Houston <ghouston@arglist.com> + + * scheme.texi (Generic Port Operations): "port?" added. + +2000-11-03 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi (About Expressions): New material about evaluation + and program execution. + + * scheme.texi (About Procedures): Minor textual improvements. + +2000-10-29 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi (About Expressions, About Closure): Placeholder + structure for remaining introductory Scheme material. + + * guile.texi (Top): Shorten some menu item lines to fit on a + single console line. + +2000-10-28 Neil Jerram <neil@ossau.uklinux.net> + + * scheme-indices.texi (R5RS Index, Guile Extensions Index): Print + new indices. + + * guile.texi: Define new R5RS and Guile extension indices. + +2000-10-27 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi (Guile and R5RS Scheme): Filled in examples of Guile + extensions. + (About Procedures): New introductory material. + + * scheme-reading.texi: New file. + + * scheme-indices.texi: New file. + + * intro.texi (Scripting Examples): Added @* to fix TeX overfull + hboxes (twice). + (end of file): Added Local Variables block for TeX-master + variable. + + * scheme.texi (R4RS Scheme): Node changed to "Guile and R5RS + Scheme". Content changed to indicate that we plan to document + both standard Scheme and Guile extensions. + (About Data, About Procedures, About Expressions): New Scheme + introductory material chapters. + (Options): Moved material on Options into its own chapter. + (Coding With Keywords): New subsection; extends material on use of + keywords to include examples of and references to (ice-9 optargs). + (passim): Change many uses of @example to @lisp, since the + formatting seems to come out better in TeX. + (Optional Arguments): New placeholder chapter (empty). + (end of file): Added Local Variables block for TeX-master + variable. + + * guile.texi (Top): "R4RS Scheme" node changed to "Guile and R5RS + Scheme". Added Scheme introductory chapters: About Data, About + Procedures and About Expressions. New Options chapter for options + material. New Optional Arguments chapter as placeholder for + (ice-9 optargs) material. New chapter for "Further Reading". New + chapters for indices showing what is standard Scheme and what is + Guile extension. + +2000-10-25 Mikael Djurfeldt <mdj@linnaeus.mit.edu> + + * Makefile.am: Added goops.texi and new files to dist_texis. + + * goops.texi, goops-tutorial.texi, hierarchy.eps, hierarchy.txt: + New files. + +2000-10-15 Neil Jerram <neil@ossau.uklinux.net> + + * gh.texi (Starting and controlling the interpreter): Removed + obsolete note about boot-9.scm not being loaded by gh_enter. + (Thanks to Chris Cramer for pointing this out.) + +2000-10-06 Neil Jerram <neil@ossau.uklinux.net> + + * guile.texi, scheme.texi, posix.texi: Simplified docstring + comments: (i) they new refer to the Texinfo-format file that is + generated by snarfing when libguile is built, rather than to + individual C files in the libguile source; (ii) there is no longer + a need to keep MD5 digest values for the corresponding source + docstring, since I'm now using a different mechanism for keeping + track of source material changes. + + * scheme.texi (Lists): Use "@example" in docstring for append. + + * guile.texi, scheme.texi (Primitive Properties): New chapter, + documenting new primitive property primitives. + +2000-09-22 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (I/O internals): Add full stops (periods) after + standalone uses of @xref. + + * scheme.texi (Structure Layout): Doc for make-struct-layout + changed to remove reference to "read-only" strings, which no + longer exist. + (Structure Basics): Use @pxref rather than @xref for parenthetical + reference. + (Dynamic Roots): Use @code rather than @var for code, in doc for + call-with-dynamic-root. + (Low level thread primitives): Ditto call-with-new-thread. + (Higher level thread procedures): Ditto call-with-new-thread. + (Symbols and Variables): Docs for gensym and symbol-hash updated + according to libguile changes. + + * posix.texi (Generic Port Operations): Synchronized docstring + for unread-string. + + * gh.texi (Defining new Scheme procedures in C): Avoid texinfo + warning by using @code rather than @var for code. + + * scheme.texi: Lots more docstring comments added, and docs + synchronized with libguile source. + (interaction-environment, make-struct, make-vtable-vtable): Newer, + better doc taken from source file. + (cons-source): New docstring written. + (Vectors): New section added. + (Random, Symbols and Variables): New chapters. + + * posix.texi: Lots more docstring comments added. + (pipe, tzset) Newer, better documentation taken from source file. + + * deprecated.texi: New file, for documenting features that are + deprecated and so planned to disappear. + + * guile.texi (Procedures, Reading and Writing, Random, Sorting, + Symbols and Variables, Deprecated): New chapters in the Scheme + part of the reference manual, to hold docstrings that don't + currently fit anywhere else. + +2000-08-28 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Pipes): open-pipe and close-pipe are procedures (in + ice-9/popen.scm), not primitives. + + * scheme.texi (Generic Port Operations): Remove doc for + port-revealed and set-port-revealed!, since these are covered in + posix.texi. + + * posix.texi: Inserted docstring synchronization comments and + synchronized docstrings for all primitives defined in posix.c, + simpos.c, scmsigs.c, stime.c. + (Ports and File Descriptors) Similarly synchronized port-revealed + and set-port-revealed!. + +2000-08-25 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi: Lots more docstrings added. + + * guile.texi (Top): More new chapters: Pairs, Objects, Guardians, + Emacs Lisp Support. + + * scheme.texi (Numbers): New chapter containing docs (many still + empty right now) for numerical primitives. + + * guile.texi (Top): Add chapter for numerical primitives. + +2000-08-18 Neil Jerram <neil@ossau.uklinux.net> + + * posix.texi (Ports and File Descriptors): Docstring for select + substantially changed by update from libguile source. + + * scheme.texi, posix.texi: Lots more primitive docstrings added. + + * guile.texi (Top): Removed empty Reflection chapter, added new + Hooks chapter. + + * scheme.texi: Added docstrings for all Guile primitives from + libguile files from arbiters.c to error.c. + (Reflection): Empty chapter removed. + + * guile.texi (Top): New chapters "Booleans" and "Equality" + (temporary - until we improve the overall organization). + + * scheme.texi (Uniform Arrays): Fix "indentical" typo. + +2000-08-12 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi: Removed superfluous "@c docstring end" markers - + docstring.el now uses "@end deffn" to find the end of the + docstring. + Added a lot more docstring comments, and synced up docstrings with + libguile - all libguile primitives documented in scheme.texi now + have docstring comments and are up to date. + (Evaluation): Updated docstring for eval and eval-string (now + R5RS-compliant). + + * intro.texi (Guile Scripts): Added a couple of blank lines. + +2000-08-11 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi: Add docstring comments and sync up existing + docstrings with libguile source - complete as far as Association + Lists. + (Keywords): Fill out and improve documentation about + keywords. + + * guile.texi: Set paragraph indent to zero. + +2000-08-07 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (libguile error handling): Add note (text supplied by + Gary Houston) giving a pointer on how to do C exception handling + since scm_error_callback was removed. + +2000-08-01 Dirk Herrmann <D.Herrmann@tu-bs.de> + + * scm.texi (libguile error handling): Removed reference to + scm_error_callback, which is not available any more since + guile-1.3. Thanks to Juli-Manel Merino Vidal and to Gary Houston + for pointing this out. + +2000-07-31 Neil Jerram <neil@ossau.uklinux.net> + + * scm.texi (Relationship between Scheme and C functions): + Expand. (Contributed by Thien-Thi Nguyen <ttn@gnu.org>.) + +2000-07-30 Neil Jerram <neil@ossau.uklinux.net> + + * scheme.texi (Association Lists): New, more complete + documentation. + * guile.texi: New top-level manual file based on guile-ref.texi + but modified to reflect the better organization suggested in + sources/jimb-org.texi. + * expect.texi: New file to separate out Expect doc. + * indices.texi: New file to separate indices from appendices. + * intro.texi: Invoking Guile and Meta Switch nodes moved to Guile + Scripting part (scripts.texi). Manual layout node moved to end of + introduction. + * posix.texi: All nodes downgraded one level. Expect, SCSH and + Tcl/Tk nodes moved to dedicated files. + * scheme.texi: Stuff moved around in accordance with + sources/jimb-org.texi reorganization (cvs diff totally confused, + I'm afraid). + * scsh.texi: New file to separate out SCSH doc. + * scripts.texi: New file to separate out Guile scripting doc. + * tcltk.texi: New file to separate out Tcl/Tk interface doc. + * Makefile.am: Changed guile-ref to guile; more distribution + texis. + * Makefile.in: Changed guile-ref to guile; more distribution + texis. + + +2000-05-14 Marius Vollmer <mvo@zagadka.ping.de> + + * posix.texi (Conventions): Added example on how to retrieve errno + value from a system-exception. Thanks to Eric Hanchrow! + +2000-05-04 Marius Vollmer <mvo@zagadka.ping.de> + + * intro.texi: Added chapter about Guile's license. + * guile-ref.texi: Updated menu. + +1999-12-15 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi (SLIB installation): new node. + +1999-12-06 Gary Houston <ghouston@freewire.co.uk> + + * r4rs.texi: tweaked the dircategory/direntry for compatibility + with the r5 version. + guile-ref.texi: tweaked the dircategory. + * Makefile.am (info_TEXINFOS): add r5rs.texi. + * r5rs.texi: new file, lifted from Aubrey Jaffer's site. + +1999-12-04 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi (Generic Port Operations): add "port-closed?". + +1999-11-22 Jim Blandy <jimb@savonarola.red-bean.com> + + * mbapi.texi: Don't promise any behavior on ill-formed text. + +1999-11-19 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi: rewrote the intros in the array nodes. + +1999-11-18 Gary Houston <ghouston@freewire.co.uk> + + * posix.texi (Network Sockets and Communication): add htons etc. + (Ports and File Descriptors, Network Sockets and Communication): + suggest setvbuf instead of duplicate-port for converting + unbuffered ports to buffered. + + * scheme.texi (Uniform Array): add missing array types to the + table. + +1999-11-17 Gary Houston <ghouston@freewire.co.uk> + + * posix.texi (Network Databases): updated. + +1999-10-24 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi (String Ports): add with-output-to-string and + with-input-from-string. + (Port Implementation): update for ptob seek. + +1999-10-18 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi (C Port Interface): update the description of + the rw_random port flag. + +1999-09-22 Gary Houston <ghouston@freewire.co.uk> + + * scheme.texi: added a bit of documentation for port internals. + +1999-09-12 Gary Houston <ghouston@easynet.co.uk> + + * posix.texi (File System): make that "directory-stream?". + +1999-09-11 Gary Houston <ghouston@easynet.co.uk> + + * posix.texi (File System): added "directory?". + +1999-09-06 James Blandy <jimb@mule.m17n.org> + + * mbapi.texi, mltext.texi: New files, describing interfaces for + dealing with multilingual code. + +1999-07-25 Gary Houston <ghouston@easynet.co.uk> + + * scheme.texi, posix.texi: updated for changes in the I/O system + and expect macros. + +1999-01-25 Mark Galassi <rosalia@cygnus.com> + + * scheme.texi (General option interface): applied a typo fix. + Thanks to Eric Hanchrow (offby1@blarg.net). + +1998-11-01 Mark Galassi <rosalia@cygnus.com> + + * scheme.texi (Weak References): incorporated David Lutterkort's + chapter on Weak References, which is based on Mikael's email + message exchange with with Michael Livshin. + +1998-10-29 Jim Blandy <jimb@zwingli.cygnus.com> + + * scheme.texi: Corrected shell commands in example. (Thanks to + Chris Bitmead.) + +1998-10-25 Mikael Djurfeldt <mdj@barbara.nada.kth.se> + + * gh.texi (C to Scheme, Scheme to C): Completed entries about + vector conversions. + +1998-08-26 Mark Galassi <rosalia@cygnus.com> + + * gh.texi (Starting and controlling the interpreter): modified the + gh_enter() docs in response to some good comments from Dirk + Herrmann: now they address the issue of loading ice-9/boot-9.scm, + and include Dirk's hackaround for the problem until we fix it + properly. + +1998-04-29 Mark Galassi <rosalia@cygnus.com> + + * scheme.texi (Dynamic Linking from Marius): added Marius's new + chapter on dynamic linking; there is still a section in dynamic + linking (written by Tim maybe?), and I have to examine how to + resolve that. + +1998-03-30 Mikael Djurfeldt <mdj@nada.kth.se> + + * scheme.texi (Port Operations): Changed entry for port-column and + port-line. (Thanks to Per Bothner.) + +1998-02-02 Mikael Djurfeldt <mdj@mdj.nada.kth.se> + + * scheme.texi (Exceptions): Adjusted documentation to reflect the + removal of the (catch #f ...) mechanism. + +1998-01-28 Mark Galassi <rosalia@nis.lanl.gov> + + * guile-ref.texi: changed @dircategory to "Scheme Programming". + It seems to be the consensus. + +1998-01-20 Mikael Djurfeldt <mdj@mdj.nada.kth.se> + + * gh.texi (C to Scheme): Added documentation for gh_doubles2scm + and gh_doubles2dvect. + (Scheme to C): Added documentation for gh_scm2doubles. + +1998-01-15 Mark Galassi <rosalia@nis.lanl.gov> + + * gh.texi (Calling Scheme procedures from C): removed + gh_make_subr() since Mikael pointed out that it is gone from + Guile. I don't remember its history any more, but I don't think + anyone is missing it. + +1998-01-03 Tim Pierce <twp@skepsis.com> + + * scheme.texi (Evaluation): Several corrections supplied by MDJ. + +Sat Dec 27 19:02:36 1997 Tim Pierce <twp@skepsis.com> + + * appendices.texi (Internals, Symbols): New nodes. + * scheme.texi (Configuration Data): New node. + +1997-12-27 Tim Pierce <twp@skepsis.com> + + * guile-ref.texi (Bitwise Operations): New description. + +1997-12-24 Tim Pierce <twp@skepsis.com> + + * scheme.texi (Port Operations, Evaluation): New nodes. + +1997-12-13 Tim Pierce <twp@skepsis.com> + + * scheme.texi, posix.texi: Documented each procedure as `procedure', + `primitive' or `syntax' as appropriate. + (Records): Change record-type-field-names to record-type-fields. + (Low level thread primitives): Change with-new-thread to + call-with-new-thread. + +Sun Dec 7 22:47:22 1997 Gary Houston <ghouston@actrix.gen.nz> + + * posix.texi (Processes): add "system" procedure. + +1997-11-23 Mark Galassi <rosalia@cygnus.com> + + * gh.texi (Starting and controlling the interpreter): added + documentation for gh_repl() -- gh_repl() has changed since I saw + the scm_shell() routine. + +1997-11-19 Tim Pierce <twp@twp.tezcat.com> + + * scheme.texi (String Fun): New node. + (Hash Tables): Added `get-handle' and `create-handle!' docs. + + * posix.texi (Networking Databases): Add docs for gethost, getnet, + getserv, getproto. Expanded on miscellaneous docs. + +1997-11-18 Tim Pierce <twp@twp.tezcat.com> + + * posix.texi: New file; moved docs for POSIX interface here. + * Makefile.am: Add posix.texi. + * Makefile.in: Regenerated. + * guile-ref.texi: Reorganize top-level menu. @include posix.texi. + * scheme.texi: Moved many nodes around, some restructuring + (e.g. new "Data Structures" node for records, structures, arrays, + hash tables, and so on). + +1997-10-19 Mark Galassi <rosalia@cygnus.com> + + * gh.texi (Calling Scheme procedures from C): added many routines + as I go through R4RS and try to complete the gh_ interface. + +Wed Oct 8 04:51:54 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (Dynamic Roots): added batch mode procedures. + +1997-10-03 Mikael Djurfeldt <mdj@nada.kth.se> + + * scheme.texi (Vtables): Changed 0 --> @code{vtable-index-layout}; + Changed @code{struct-vtable-offset} --> @code{vtable-offset-user}; + Added short note about the print call-back initializer. (This + section is in need of review. However, we shoudn't spend much + time on it since the structs will be replaced by something + equivalent, but with a different interface.} + +Sun Sep 28 00:02:35 1997 Mark Galassi <rosalia@nis.lanl.gov> + + * scheme.texi (Keywords): very small re-organization to take + advantage of the fact that read-options is now documented in + another chapter. + +Thu Sep 25 23:37:02 1997 Mark Galassi <rosalia@nis.lanl.gov> + + * scheme.texi (Guile options interface): renamed the symbol case + section to "Guile options interface". "Reader options" is now a + subsection of that. I've finally figured a lot of how options + work, thanks to discovering Mikael's comments in options.c and an + old note from Mikael to Jim describing it. + (Guile options interface): reorganized the individual option + groups. This section (on options) of the manual is now reasonably + complete, unless I am completely missing something. + +Wed Sep 24 15:25:03 1997 Mark Galassi <rosalia@nis.lanl.gov> + + * scheme.texi (The Guile module system): Added a bit more to this + chapter, mostly the more user-friendly (use-modules (ice-9 + module-name)) approach. + (Symbol case): tried to write something about this, but it will + need to be reviewed by someone who understands the big picture of + read options. I also think the section name should be changed to + something like "Read options". + +Sun Sep 21 18:45:57 1997 Mark Galassi <rosalia@nis.lanl.gov> + + * scheme.texi (SLIB): some little details, including splitting off + what does in the installation chapter. Also added a section on + Jacal, which has some open issues. + + * appendices.texi (Packages not shipped with Guile): added this + section to describe getting resources on SCSH, SLIB and Jacal (and + who knows what else in the future). + +Sat Aug 30 19:31:22 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (Uniform Array): mention start and end arguments + for uniform-array-read! and uniform-array-write. + +Sat Aug 23 19:05:08 1997 Gary Houston <ghouston@actrix.gen.nz> + + * guile-ref.texi (Top): corresponding changes. + * scheme.texi (Exception Handling): add scm-error, strerror. + (Exceptions): renamed from Exception Handling. + (Exceptions): deleted empty section. + +Mon Aug 18 16:11:43 1997 Jim Blandy <jimb@totoro.red-bean.com> + + * texinfo.tex: Installed from texinfo release 3.11. + +Fri Aug 15 08:14:32 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (file system): added truncate-file. + chown, fcntl, fseek, ftell updated. + (ports vs file descriptors): added fsync, open, open-fdes. + (time): added times. + +Sun Aug 10 07:39:55 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (processes): added execle. + +Tue Jul 29 02:01:21 1997 Gary Houston <ghouston@actrix.gen.nz> + + * setvbuf added. primitive-dup[2] removed. + +Sat Jul 26 04:25:40 1997 Gary Houston <ghouston@actrix.gen.nz> + + * various close and dup procedures added, plus setenv. + +Sat Jul 19 04:04:50 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (signals): new section. + (processes): primitive-exit. + (ports vs. file descriptors): force-output, flush-all-ports. + fcntl from NEWS. + +Fri Jul 18 07:58:52 1997 Gary Houston <ghouston@actrix.gen.nz> + + * scheme.texi (SLIB): update initialization details. + (expect): likewise. + (The Scheme shell (scsh)): likewise. + +Fri Jun 27 00:31:25 1997 Tim Pierce <twp@twp.tezcat.com> + + * scheme.texi (Regexp Functions): Add docs for make-regexp flags + regexp/icase, regexp/newline, regexp/basic, regexp/extended. + +Mon Jun 23 12:35:57 1997 Tim Pierce <twpierce@bio-5.bsd.uchicago.edu> + + * appendices.texi (debugger user interface): new text. + (Single-Step, Trace, Backtrace): new nodes. + + * scheme.texi: Many revised nodes, some new ones. + + (Binary Numeric Operations, Input/Output Ports, File Ports, Soft + Ports, String Ports): Imported documentation from SCM and SLIB manuals. + + (Association Lists and Hash Tables, Dictionary Types, Association + Lists, Hash Tables): New nodes. + (Dictionaries in general): Removed. + + (Regular Expressions): Replaced. + (Rx Interface): New node, renamed from old `Regular Expressions'. + (Regexp Functions, Match Functions, Backslash Escapes): new nodes. + + (Property Lists): new node with documentation for both object and + procedure properties. + (Object Properties): removed. + * guile-ref.texi: change `Object Properties' to `Property Lists'. + diff --git a/doc/ref/Makefile.am b/doc/ref/Makefile.am new file mode 100644 index 000000000..05393cd96 --- /dev/null +++ b/doc/ref/Makefile.am @@ -0,0 +1,139 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 1998, 2004, 2006, 2008, 2009, 2010, +## 2011, 2013, 2014 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE is free software; you can redistribute it and/or modify it +## under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 3, or +## (at your option) any later version. +## +## GUILE is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with GUILE; see the file COPYING.LESSER. If not, +## write to the Free Software Foundation, Inc., 51 Franklin Street, +## Fifth Floor, Boston, MA 02110-1301 USA + +AUTOMAKE_OPTIONS = gnu + +info_TEXINFOS = guile.texi + +guile_TEXINFOS = preface.texi \ + intro.texi \ + tour.texi \ + libguile-parallel.texi \ + libguile-program.texi \ + scheme-intro.texi \ + api-scm.texi \ + api-snarf.texi \ + api-smobs.texi \ + api-foreign-objects.texi \ + scheme-ideas.texi \ + api-data.texi \ + api-procedures.texi \ + api-macros.texi \ + api-utility.texi \ + api-binding.texi \ + api-control.texi \ + api-io.texi \ + api-foreign.texi \ + api-regex.texi \ + api-lalr.texi \ + api-peg.texi \ + api-languages.texi \ + api-evaluation.texi \ + api-memory.texi \ + api-modules.texi \ + api-scheduling.texi \ + api-options.texi \ + api-i18n.texi \ + api-debug.texi \ + api-coverage.texi \ + scheme-reading.texi \ + scheme-indices.texi \ + slib.texi \ + posix.texi \ + web.texi \ + expect.texi \ + scsh.texi \ + curried.texi \ + sxml-match.texi \ + scheme-scripts.texi \ + api-overview.texi \ + api-deprecated.texi \ + scheme-using.texi \ + indices.texi \ + data-rep.texi \ + repl-modules.texi \ + srfi-modules.texi \ + r6rs.texi \ + match.texi \ + misc-modules.texi \ + libguile-autoconf.texi \ + autoconf-macros.texi \ + tools.texi \ + history.texi \ + vm.texi \ + compiler.texi \ + fdl.texi \ + libguile-concepts.texi \ + libguile-foreign-objects.texi \ + libguile-snarf.texi \ + libguile-linking.texi \ + libguile-extensions.texi \ + api-init.texi \ + mod-getopt-long.texi \ + statprof.texi \ + sxml.texi \ + texinfo.texi \ + goops.texi \ + goops-tutorial.texi \ + guile-invoke.texi \ + effective-version.texi + +ETAGS_ARGS = $(info_TEXINFOS) $(guile_TEXINFOS) + +PICTURES = hierarchy.eps \ + hierarchy.pdf \ + hierarchy.png \ + hierarchy.txt \ + gds.eps \ + gds.pdf \ + gds.txt \ + scheme.eps \ + scheme.pdf \ + scheme.txt \ + mop.text + +noinst_DATA = $(PICTURES) + +EXTRA_DIST = ChangeLog-2008 $(PICTURES) + +# Automated snarfing + +libguile-autoconf.texi: autoconf-macros.texi +autoconf-macros.texi: $(top_srcdir)/meta/guile.m4 + GUILE_AUTO_COMPILE=0 $(top_builddir)/meta/build-env guild \ + snarf-guile-m4-docs $(top_srcdir)/meta/guile.m4 \ + > $(srcdir)/$@ + +# Build that file from here rather than at the user's site to avoid +# triggering a rebuild of `guile.info'. Note that `GUILE-VERSION' is +# among $(CONFIG_STATUS_DEPENDENCIES); thus, when it's updated, this +# Makefile is rebuilt, and $(GUILE_EFFECTIVE_VERSION) is up-to-date. +$(srcdir)/effective-version.texi: $(top_srcdir)/GUILE-VERSION + echo "@set EFFECTIVE-VERSION $(GUILE_EFFECTIVE_VERSION)" > $@ + +MAINTAINERCLEANFILES = autoconf-macros.texi + +www-commit: html + cd guile.html; \ + cvs -d :ext:cvs.sv.gnu.org:/web/guile \ + import -m 'make www-commit in doc/ref' guile/docs/master/guile.html gnu \ + $(shell date "+D%Y%m%d%H%M%S") diff --git a/doc/ref/api-binding.texi b/doc/ref/api-binding.texi new file mode 100644 index 000000000..c3ee01b8c --- /dev/null +++ b/doc/ref/api-binding.texi @@ -0,0 +1,349 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011, +@c 2014 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Binding Constructs +@section Definitions and Variable Bindings + +Scheme supports the definition of variables in different contexts. +Variables can be defined at the top level, so that they are visible in +the entire program, and variables can be defined locally to procedures +and expressions. This is important for modularity and data abstraction. + +@menu +* Top Level:: Top level variable definitions. +* Local Bindings:: Local variable bindings. +* Internal Definitions:: Internal definitions. +* Binding Reflection:: Querying variable bindings. +* Binding Multiple Values:: Binding multiple return values. +@end menu + + +@node Top Level +@subsection Top Level Variable Definitions + +@cindex variable definition + +At the top level of a program (i.e., not nested within any other +expression), a definition of the form + +@lisp +(define a @var{value}) +@end lisp + +@noindent +defines a variable called @code{a} and sets it to the value @var{value}. + +If the variable already exists in the current module, because it has +already been created by a previous @code{define} expression with the +same name, its value is simply changed to the new @var{value}. In this +case, then, the above form is completely equivalent to + +@lisp +(set! a @var{value}) +@end lisp + +@noindent +This equivalence means that @code{define} can be used interchangeably +with @code{set!} to change the value of variables at the top level of +the REPL or a Scheme source file. It is useful during interactive +development when reloading a Scheme file that you have modified, because +it allows the @code{define} expressions in that file to work as expected +both the first time that the file is loaded and on subsequent occasions. + +Note, though, that @code{define} and @code{set!} are not always +equivalent. For example, a @code{set!} is not allowed if the named +variable does not already exist, and the two expressions can behave +differently in the case where there are imported variables visible from +another module. + +@deffn {Scheme Syntax} define name value +Create a top level variable named @var{name} with value @var{value}. +If the named variable already exists, just change its value. The return +value of a @code{define} expression is unspecified. +@end deffn + +The C API equivalents of @code{define} are @code{scm_define} and +@code{scm_c_define}, which differ from each other in whether the +variable name is specified as a @code{SCM} symbol or as a +null-terminated C string. + +@deffn {C Function} scm_define (sym, value) +@deffnx {C Function} scm_c_define (const char *name, value) +C equivalents of @code{define}, with variable name specified either by +@var{sym}, a symbol, or by @var{name}, a null-terminated C string. Both +variants return the new or preexisting variable object. +@end deffn + +@code{define} (when it occurs at top level), @code{scm_define} and +@code{scm_c_define} all create or set the value of a variable in the top +level environment of the current module. If there was not already a +variable with the specified name belonging to the current module, but a +similarly named variable from another module was visible through having +been imported, the newly created variable in the current module will +shadow the imported variable, such that the imported variable is no +longer visible. + +Attention: Scheme definitions inside local binding constructs +(@pxref{Local Bindings}) act differently (@pxref{Internal Definitions}). + +Many people end up in a development style of adding and changing +definitions at runtime, building out their program without restarting +it. (You can do this using @code{reload-module}, the @code{reload} REPL +command, the @code{load} procedure, or even just pasting code into a +REPL.) If you are one of these people, you will find that sometimes +there are some variables that you @emph{don't} want to redefine all the +time. For these, use @code{define-once}. + +@fnindex defvar +@deffn {Scheme Syntax} define-once name value +Create a top level variable named @var{name} with value @var{value}, but +only if @var{name} is not already bound in the current module. +@end deffn + +Old Lispers probably know @code{define-once} under its Lisp name, +@code{defvar}. + + +@node Local Bindings +@subsection Local Variable Bindings + +@cindex local bindings +@cindex local variables + +As opposed to definitions at the top level, which creates bindings that +are visible to all code in a module, it is also possible to define +variables which are only visible in a well-defined part of the program. +Normally, this part of a program will be a procedure or a subexpression +of a procedure. + +With the constructs for local binding (@code{let}, @code{let*}, +@code{letrec}, and @code{letrec*}), the Scheme language has a block +structure like most other programming languages since the days of +@sc{Algol 60}. Readers familiar to languages like C or Java should +already be used to this concept, but the family of @code{let} +expressions has a few properties which are well worth knowing. + +The most basic local binding construct is @code{let}. + +@deffn syntax let bindings body +@var{bindings} has the form + +@lisp +((@var{variable1} @var{init1}) @dots{}) +@end lisp + +that is zero or more two-element lists of a variable and an arbitrary +expression each. All @var{variable} names must be distinct. + +A @code{let} expression is evaluated as follows. + +@itemize @bullet +@item +All @var{init} expressions are evaluated. + +@item +New storage is allocated for the @var{variables}. + +@item +The values of the @var{init} expressions are stored into the variables. + +@item +The expressions in @var{body} are evaluated in order, and the value of +the last expression is returned as the value of the @code{let} +expression. +@end itemize + +The @var{init} expressions are not allowed to refer to any of the +@var{variables}. +@end deffn + +The other binding constructs are variations on the same theme: making new +values, binding them to variables, and executing a body in that new, +extended lexical context. + +@deffn syntax let* bindings body +Similar to @code{let}, but the variable bindings are performed +sequentially, that means that all @var{init} expression are allowed to +use the variables defined on their left in the binding list. + +A @code{let*} expression can always be expressed with nested @code{let} +expressions. + +@lisp +(let* ((a 1) (b a)) + b) +@equiv{} +(let ((a 1)) + (let ((b a)) + b)) +@end lisp +@end deffn + +@deffn syntax letrec bindings body +Similar to @code{let}, but it is possible to refer to the @var{variable} +from lambda expression created in any of the @var{inits}. That is, +procedures created in the @var{init} expression can recursively refer to +the defined variables. + +@lisp +(letrec ((even? (lambda (n) + (if (zero? n) + #t + (odd? (- n 1))))) + (odd? (lambda (n) + (if (zero? n) + #f + (even? (- n 1)))))) + (even? 88)) +@result{} +#t +@end lisp + +Note that while the @var{init} expressions may refer to the new +variables, they may not access their values. For example, making the +@code{even?} function above creates a closure (@pxref{About Closure}) +referencing the @code{odd?} variable. But @code{odd?} can't be called +until after execution has entered the body. +@end deffn + +@deffn syntax letrec* bindings body +Similar to @code{letrec}, except the @var{init} expressions are bound to +their variables in order. + +@code{letrec*} thus relaxes the letrec restriction, in that later +@var{init} expressions may refer to the values of previously bound +variables. + +@lisp +(letrec ((a 42) + (b (+ a 10))) ;; Illegal access + (* a b)) +;; The behavior of the expression above is unspecified + +(letrec* ((a 42) + (b (+ a 10))) + (* a b)) +@result{} 2184 +@end lisp +@end deffn + +There is also an alternative form of the @code{let} form, which is used +for expressing iteration. Because of the use as a looping construct, +this form (the @dfn{named let}) is documented in the section about +iteration (@pxref{while do, Iteration}) + +@node Internal Definitions +@subsection Internal definitions + +@c FIXME::martin: Review me! + +A @code{define} form which appears inside the body of a @code{lambda}, +@code{let}, @code{let*}, @code{letrec}, @code{letrec*} or equivalent +expression is called an @dfn{internal definition}. An internal +definition differs from a top level definition (@pxref{Top Level}), +because the definition is only visible inside the complete body of the +enclosing form. Let us examine the following example. + +@lisp +(let ((frumble "froz")) + (define banana (lambda () (apple 'peach))) + (define apple (lambda (x) x)) + (banana)) +@result{} +peach +@end lisp + +Here the enclosing form is a @code{let}, so the @code{define}s in the +@code{let}-body are internal definitions. Because the scope of the +internal definitions is the @strong{complete} body of the +@code{let}-expression, the @code{lambda}-expression which gets bound to +the variable @code{banana} may refer to the variable @code{apple}, even +though its definition appears lexically @emph{after} the definition of +@code{banana}. This is because a sequence of internal definition acts +as if it were a @code{letrec*} expression. + +@lisp +(let () + (define a 1) + (define b 2) + (+ a b)) +@end lisp + +@noindent +is equivalent to + +@lisp +(let () + (letrec* ((a 1) (b 2)) + (+ a b))) +@end lisp + +Internal definitions are only allowed at the beginning of the body of an +enclosing expression. They may not be mixed with other expressions. + +Another noteworthy difference to top level definitions is that within +one group of internal definitions all variable names must be distinct. +That means where on the top level a second define for a given variable +acts like a @code{set!}, an exception is thrown for internal definitions +with duplicate bindings. + +As a historical note, it used to be that internal bindings were expanded +in terms of @code{letrec}, not @code{letrec*}. This was the situation +for the R5RS report and before. However with the R6RS, it was recognized +that sequential definition was a more intuitive expansion, as in the +following case: + +@lisp +(let () + (define a 1) + (define b (+ a a)) + (+ a b)) +@end lisp + +@noindent +Guile decided to follow the R6RS in this regard, and now expands +internal definitions using @code{letrec*}. + + +@node Binding Reflection +@subsection Querying variable bindings + +Guile provides a procedure for checking whether a symbol is bound in the +top level environment. + +@deffn {Scheme Procedure} defined? sym [module] +@deffnx {C Function} scm_defined_p (sym, module) +Return @code{#t} if @var{sym} is defined in the module @var{module} or +the current module when @var{module} is not specified; otherwise return +@code{#f}. +@end deffn + + +@node Binding Multiple Values +@subsection Binding multiple return values + +@deffn {Syntax} define-values formals expression +The @var{expression} is evaluated, and the @var{formals} are bound to +the return values in the same way that the formals in a @code{lambda} +expression are matched to the arguments in a procedure call. +@end deffn + +@example +(define-values (q r) (floor/ 10 3)) +(list q r) @result{} (3 1) + +(define-values (x . y) (values 1 2 3)) +x @result{} 1 +y @result{} (2 3) + +(define-values x (values 1 2 3)) +x @result{} (1 2 3) +@end example + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi new file mode 100644 index 000000000..2d696ea89 --- /dev/null +++ b/doc/ref/api-control.texi @@ -0,0 +1,2237 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, +@c 2011, 2012, 2013, 2014 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Control Mechanisms +@section Controlling the Flow of Program Execution + +See @ref{Control Flow} for a discussion of how the more general control +flow of Scheme affects C code. + +@menu +* begin:: Sequencing and splicing. +* Conditionals:: If, when, unless, case, and cond. +* and or:: Conditional evaluation of a sequence. +* while do:: Iteration mechanisms. +* Prompts:: Composable, delimited continuations. +* Continuations:: Non-composable continuations. +* Multiple Values:: Returning and accepting multiple values. +* Exceptions:: Throwing and catching exceptions. +* Error Reporting:: Procedures for signaling errors. +* Dynamic Wind:: Dealing with non-local entrance/exit. +* Fluids and Dynamic States:: Dynamic scope building blocks. +* Parameters:: A dynamic scope facility. +* Handling Errors:: How to handle errors in C code. +* Continuation Barriers:: Protection from non-local control flow. +@end menu + +@node begin +@subsection Sequencing and Splicing + +@cindex begin +@cindex sequencing +@cindex expression sequencing + +As an expression, the @code{begin} syntax is used to evaluate a sequence +of sub-expressions in order. Consider the conditional expression below: + +@lisp +(if (> x 0) + (begin (display "greater") (newline))) +@end lisp + +If the test is true, we want to display ``greater'' to the current +output port, then display a newline. We use @code{begin} to form a +compound expression out of this sequence of sub-expressions. + +@deffn syntax begin expr @dots{} +The expression(s) are evaluated in left-to-right order and the value of +the last expression is returned as the value of the +@code{begin}-expression. This expression type is used when the +expressions before the last one are evaluated for their side effects. +@end deffn + +@cindex splicing +@cindex definition splicing + +The @code{begin} syntax has another role in definition context +(@pxref{Internal Definitions}). A @code{begin} form in a definition +context @dfn{splices} its subforms into its place. For example, +consider the following procedure: + +@lisp +(define (make-seal) + (define-sealant seal open) + (values seal open)) +@end lisp + +Let us assume the existence of a @code{define-sealant} macro that +expands out to some definitions wrapped in a @code{begin}, like so: + +@lisp +(define (make-seal) + (begin + (define seal-tag + (list 'seal)) + (define (seal x) + (cons seal-tag x)) + (define (sealed? x) + (and (pair? x) (eq? (car x) seal-tag))) + (define (open x) + (if (sealed? x) + (cdr x) + (error "Expected a sealed value:" x)))) + (values seal open)) +@end lisp + +Here, because the @code{begin} is in definition context, its subforms +are @dfn{spliced} into the place of the @code{begin}. This allows the +definitions created by the macro to be visible to the following +expression, the @code{values} form. + +It is a fine point, but splicing and sequencing are different. It can +make sense to splice zero forms, because it can make sense to have zero +internal definitions before the expressions in a procedure or lexical +binding form. However it does not make sense to have a sequence of zero +expressions, because in that case it would not be clear what the value +of the sequence would be, because in a sequence of zero expressions, +there can be no last value. Sequencing zero expressions is an error. + +It would be more elegant in some ways to eliminate splicing from the +Scheme language, and without macros (@pxref{Macros}), that would be a +good idea. But it is useful to be able to write macros that expand out +to multiple definitions, as in @code{define-sealant} above, so Scheme +abuses the @code{begin} form for these two tasks. + +@node Conditionals +@subsection Simple Conditional Evaluation + +@cindex conditional evaluation +@cindex if +@cindex when +@cindex unless +@cindex case +@cindex cond + +Guile provides three syntactic constructs for conditional evaluation. +@code{if} is the normal if-then-else expression (with an optional else +branch), @code{cond} is a conditional expression with multiple branches +and @code{case} branches if an expression has one of a set of constant +values. + +@deffn syntax if test consequent [alternate] +All arguments may be arbitrary expressions. First, @var{test} is +evaluated. If it returns a true value, the expression @var{consequent} +is evaluated and @var{alternate} is ignored. If @var{test} evaluates to +@code{#f}, @var{alternate} is evaluated instead. The values of the +evaluated branch (@var{consequent} or @var{alternate}) are returned as +the values of the @code{if} expression. + +When @var{alternate} is omitted and the @var{test} evaluates to +@code{#f}, the value of the expression is not specified. +@end deffn + +When you go to write an @code{if} without an alternate (a @dfn{one-armed +@code{if}}), part of what you are expressing is that you don't care +about the return value (or values) of the expression. As such, you are +more interested in the @emph{effect} of evaluating the consequent +expression. (By convention, we use the word @dfn{statement} to refer to +an expression that is evaluated for effect, not for value). + +In such a case, it is considered more clear to express these intentions +with these special forms, @code{when} and @code{unless}. As an added +bonus, these forms accept multiple statements to evaluate, which are +implicitly wrapped in a @code{begin}. + +@deffn {Scheme Syntax} when test statement1 statement2 ... +@deffnx {Scheme Syntax} unless test statement1 statement2 ... +The actual definitions of these forms are in many ways their most clear +documentation: + +@example +(define-syntax-rule (when test stmt stmt* ...) + (if test (begin stmt stmt* ...))) + +(define-syntax-rule (unless condition stmt stmt* ...) + (if (not test) (begin stmt stmt* ...))) +@end example + +That is to say, @code{when} evaluates its consequent statements in order +if @var{test} is true. @code{unless} is the opposite: it evaluates the +statements if @var{test} is false. +@end deffn + +@deffn syntax cond clause1 clause2 @dots{} +Each @code{cond}-clause must look like this: + +@lisp +(@var{test} @var{expression} @dots{}) +@end lisp + +where @var{test} and @var{expression} are arbitrary expressions, or like +this + +@lisp +(@var{test} => @var{expression}) +@end lisp + +where @var{expression} must evaluate to a procedure. + +The @var{test}s of the clauses are evaluated in order and as soon as one +of them evaluates to a true value, the corresponding @var{expression}s +are evaluated in order and the last value is returned as the value of +the @code{cond}-expression. For the @code{=>} clause type, +@var{expression} is evaluated and the resulting procedure is applied to +the value of @var{test}. The result of this procedure application is +then the result of the @code{cond}-expression. + +@cindex SRFI-61 +@cindex general cond clause +@cindex multiple values and cond +One additional @code{cond}-clause is available as an extension to +standard Scheme: + +@lisp +(@var{test} @var{guard} => @var{expression}) +@end lisp + +where @var{guard} and @var{expression} must evaluate to procedures. +For this clause type, @var{test} may return multiple values, and +@code{cond} ignores its boolean state; instead, @code{cond} evaluates +@var{guard} and applies the resulting procedure to the value(s) of +@var{test}, as if @var{guard} were the @var{consumer} argument of +@code{call-with-values}. If the result of that procedure call is a +true value, it evaluates @var{expression} and applies the resulting +procedure to the value(s) of @var{test}, in the same manner as the +@var{guard} was called. + +The @var{test} of the last @var{clause} may be the symbol @code{else}. +Then, if none of the preceding @var{test}s is true, the +@var{expression}s following the @code{else} are evaluated to produce the +result of the @code{cond}-expression. +@end deffn + +@deffn syntax case key clause1 clause2 @dots{} +@var{key} may be any expression, and the @var{clause}s must have the form + +@lisp +((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{}) +@end lisp + +or + +@lisp +((@var{datum1} @dots{}) => @var{expression}) +@end lisp + +and the last @var{clause} may have the form + +@lisp +(else @var{expr1} @var{expr2} @dots{}) +@end lisp + +or + +@lisp +(else => @var{expression}) +@end lisp + +All @var{datum}s must be distinct. First, @var{key} is evaluated. The +result of this evaluation is compared against all @var{datum} values using +@code{eqv?}. When this comparison succeeds, the expression(s) following +the @var{datum} are evaluated from left to right, returning the value of +the last expression as the result of the @code{case} expression. + +If the @var{key} matches no @var{datum} and there is an +@code{else}-clause, the expressions following the @code{else} are +evaluated. If there is no such clause, the result of the expression is +unspecified. + +For the @code{=>} clause types, @var{expression} is evaluated and the +resulting procedure is applied to the value of @var{key}. The result of +this procedure application is then the result of the +@code{case}-expression. +@end deffn + + +@node and or +@subsection Conditional Evaluation of a Sequence of Expressions + +@code{and} and @code{or} evaluate all their arguments in order, similar +to @code{begin}, but evaluation stops as soon as one of the expressions +evaluates to false or true, respectively. + +@deffn syntax and expr @dots{} +Evaluate the @var{expr}s from left to right and stop evaluation as soon +as one expression evaluates to @code{#f}; the remaining expressions are +not evaluated. The value of the last evaluated expression is returned. +If no expression evaluates to @code{#f}, the value of the last +expression is returned. + +If used without expressions, @code{#t} is returned. +@end deffn + +@deffn syntax or expr @dots{} +Evaluate the @var{expr}s from left to right and stop evaluation as soon +as one expression evaluates to a true value (that is, a value different +from @code{#f}); the remaining expressions are not evaluated. The value +of the last evaluated expression is returned. If all expressions +evaluate to @code{#f}, @code{#f} is returned. + +If used without expressions, @code{#f} is returned. +@end deffn + + +@node while do +@subsection Iteration mechanisms + +@cindex iteration +@cindex looping +@cindex named let + +Scheme has only few iteration mechanisms, mainly because iteration in +Scheme programs is normally expressed using recursion. Nevertheless, +R5RS defines a construct for programming loops, calling @code{do}. In +addition, Guile has an explicit looping syntax called @code{while}. + +@deffn syntax do ((variable init [step]) @dots{}) (test expr @dots{}) body @dots{} +Bind @var{variable}s and evaluate @var{body} until @var{test} is true. +The return value is the last @var{expr} after @var{test}, if given. A +simple example will illustrate the basic form, + +@example +(do ((i 1 (1+ i))) + ((> i 4)) + (display i)) +@print{} 1234 +@end example + +@noindent +Or with two variables and a final return value, + +@example +(do ((i 1 (1+ i)) + (p 3 (* 3 p))) + ((> i 4) + p) + (format #t "3**~s is ~s\n" i p)) +@print{} +3**1 is 3 +3**2 is 9 +3**3 is 27 +3**4 is 81 +@result{} +789 +@end example + +The @var{variable} bindings are established like a @code{let}, in that +the expressions are all evaluated and then all bindings made. When +iterating, the optional @var{step} expressions are evaluated with the +previous bindings in scope, then new bindings all made. + +The @var{test} expression is a termination condition. Looping stops +when the @var{test} is true. It's evaluated before running the +@var{body} each time, so if it's true the first time then @var{body} +is not run at all. + +The optional @var{expr}s after the @var{test} are evaluated at the end +of looping, with the final @var{variable} bindings available. The +last @var{expr} gives the return value, or if there are no @var{expr}s +the return value is unspecified. + +Each iteration establishes bindings to fresh locations for the +@var{variable}s, like a new @code{let} for each iteration. This is +done for @var{variable}s without @var{step} expressions too. The +following illustrates this, showing how a new @code{i} is captured by +the @code{lambda} in each iteration (@pxref{About Closure,, The +Concept of Closure}). + +@example +(define lst '()) +(do ((i 1 (1+ i))) + ((> i 4)) + (set! lst (cons (lambda () i) lst))) +(map (lambda (proc) (proc)) lst) +@result{} +(4 3 2 1) +@end example +@end deffn + +@deffn syntax while cond body @dots{} +Run a loop executing the @var{body} forms while @var{cond} is true. +@var{cond} is tested at the start of each iteration, so if it's +@code{#f} the first time then @var{body} is not executed at all. + +Within @code{while}, two extra bindings are provided, they can be used +from both @var{cond} and @var{body}. + +@deffn {Scheme Procedure} break break-arg @dots{} +Break out of the @code{while} form. +@end deffn + +@deffn {Scheme Procedure} continue +Abandon the current iteration, go back to the start and test +@var{cond} again, etc. +@end deffn + +If the loop terminates normally, by the @var{cond} evaluating to +@code{#f}, then the @code{while} expression as a whole evaluates to +@code{#f}. If it terminates by a call to @code{break} with some number +of arguments, those arguments are returned from the @code{while} +expression, as multiple values. Otherwise if it terminates by a call to +@code{break} with no arguments, then return value is @code{#t}. + +@example +(while #f (error "not reached")) @result{} #f +(while #t (break)) @result{} #t +(while #t (break 1 2 3)) @result{} 1 2 3 +@end example + +Each @code{while} form gets its own @code{break} and @code{continue} +procedures, operating on that @code{while}. This means when loops are +nested the outer @code{break} can be used to escape all the way out. +For example, + +@example +(while (test1) + (let ((outer-break break)) + (while (test2) + (if (something) + (outer-break #f)) + ...))) +@end example + +Note that each @code{break} and @code{continue} procedure can only be +used within the dynamic extent of its @code{while}. Outside the +@code{while} their behaviour is unspecified. +@end deffn + +@cindex named let +Another very common way of expressing iteration in Scheme programs is +the use of the so-called @dfn{named let}. + +Named let is a variant of @code{let} which creates a procedure and calls +it in one step. Because of the newly created procedure, named let is +more powerful than @code{do}--it can be used for iteration, but also +for arbitrary recursion. + +@deffn syntax let variable bindings body +For the definition of @var{bindings} see the documentation about +@code{let} (@pxref{Local Bindings}). + +Named @code{let} works as follows: + +@itemize @bullet +@item +A new procedure which accepts as many arguments as are in @var{bindings} +is created and bound locally (using @code{let}) to @var{variable}. The +new procedure's formal argument names are the name of the +@var{variables}. + +@item +The @var{body} expressions are inserted into the newly created procedure. + +@item +The procedure is called with the @var{init} expressions as the formal +arguments. +@end itemize + +The next example implements a loop which iterates (by recursion) 1000 +times. + +@lisp +(let lp ((x 1000)) + (if (positive? x) + (lp (- x 1)) + x)) +@result{} +0 +@end lisp +@end deffn + + +@node Prompts +@subsection Prompts +@cindex prompts +@cindex delimited continuations +@cindex composable continuations +@cindex non-local exit + +Prompts are control-flow barriers between different parts of a program. In the +same way that a user sees a shell prompt (e.g., the Bash prompt) as a barrier +between the operating system and her programs, Scheme prompts allow the Scheme +programmer to treat parts of programs as if they were running in different +operating systems. + +We use this roundabout explanation because, unless you're a functional +programming junkie, you probably haven't heard the term, ``delimited, composable +continuation''. That's OK; it's a relatively recent topic, but a very useful +one to know about. + +@menu +* Prompt Primitives:: Call-with-prompt and abort-to-prompt. +* Shift and Reset:: The zoo of delimited control operators. +@end menu + +@node Prompt Primitives +@subsubsection Prompt Primitives + +Guile's primitive delimited control operators are +@code{call-with-prompt} and @code{abort-to-prompt}. + +@deffn {Scheme Procedure} call-with-prompt tag thunk handler +Set up a prompt, and call @var{thunk} within that prompt. + +During the dynamic extent of the call to @var{thunk}, a prompt named @var{tag} +will be present in the dynamic context, such that if a user calls +@code{abort-to-prompt} (see below) with that tag, control rewinds back to the +prompt, and the @var{handler} is run. + +@var{handler} must be a procedure. The first argument to @var{handler} will be +the state of the computation begun when @var{thunk} was called, and ending with +the call to @code{abort-to-prompt}. The remaining arguments to @var{handler} are +those passed to @code{abort-to-prompt}. +@end deffn + +@deffn {Scheme Procedure} make-prompt-tag [stem] +Make a new prompt tag. A prompt tag is simply a unique object. +Currently, a prompt tag is a fresh pair. This may change in some future +Guile version. +@end deffn + +@deffn {Scheme Procedure} default-prompt-tag +Return the default prompt tag. Having a distinguished default prompt +tag allows some useful prompt and abort idioms, discussed in the next +section. Note that @code{default-prompt-tag} is actually a parameter, +and so may be dynamically rebound using @code{parameterize}. +@xref{Parameters}. +@end deffn + +@deffn {Scheme Procedure} abort-to-prompt tag val1 val2 @dots{} +Unwind the dynamic and control context to the nearest prompt named @var{tag}, +also passing the given values. +@end deffn + +C programmers may recognize @code{call-with-prompt} and @code{abort-to-prompt} +as a fancy kind of @code{setjmp} and @code{longjmp}, respectively. Prompts are +indeed quite useful as non-local escape mechanisms. Guile's @code{catch} and +@code{throw} are implemented in terms of prompts. Prompts are more convenient +than @code{longjmp}, in that one has the opportunity to pass multiple values to +the jump target. + +Also unlike @code{longjmp}, the prompt handler is given the full state of the +process that was aborted, as the first argument to the prompt's handler. That +state is the @dfn{continuation} of the computation wrapped by the prompt. It is +a @dfn{delimited continuation}, because it is not the whole continuation of the +program; rather, just the computation initiated by the call to +@code{call-with-prompt}. + +The continuation is a procedure, and may be reinstated simply by invoking it, +with any number of values. Here's where things get interesting, and complicated +as well. Besides being described as delimited, continuations reified by prompts +are also @dfn{composable}, because invoking a prompt-saved continuation composes +that continuation with the current one. + +Imagine you have saved a continuation via call-with-prompt: + +@example +(define cont + (call-with-prompt + ;; tag + 'foo + ;; thunk + (lambda () + (+ 34 (abort-to-prompt 'foo))) + ;; handler + (lambda (k) k))) +@end example + +The resulting continuation is the addition of 34. It's as if you had written: + +@example +(define cont + (lambda (x) + (+ 34 x))) +@end example + +So, if we call @code{cont} with one numeric value, we get that number, +incremented by 34: + +@example +(cont 8) +@result{} 42 +(* 2 (cont 8)) +@result{} 84 +@end example + +The last example illustrates what we mean when we say, "composes with the +current continuation". We mean that there is a current continuation -- some +remaining things to compute, like @code{(lambda (x) (* x 2))} -- and that +calling the saved continuation doesn't wipe out the current continuation, it +composes the saved continuation with the current one. + +We're belaboring the point here because traditional Scheme continuations, as +discussed in the next section, aren't composable, and are actually less +expressive than continuations captured by prompts. But there's a place for them +both. + +Before moving on, we should mention that if the handler of a prompt is a +@code{lambda} expression, and the first argument isn't referenced, an abort to +that prompt will not cause a continuation to be reified. This can be an +important efficiency consideration to keep in mind. + +@cindex continuation, escape +One example where this optimization matters is @dfn{escape +continuations}. Escape continuations are delimited continuations whose +only use is to make a non-local exit---i.e., to escape from the current +continuation. A common use of escape continuations is when throwing an +exception (@pxref{Exceptions}). + +The constructs below are syntactic sugar atop prompts to simplify the +use of escape continuations. + +@deffn {Scheme Procedure} call-with-escape-continuation proc +@deffnx {Scheme Procedure} call/ec proc +Call @var{proc} with an escape continuation. + +In the example below, the @var{return} continuation is used to escape +the continuation of the call to @code{fold}. + +@lisp +(use-modules (ice-9 control) + (srfi srfi-1)) + +(define (prefix x lst) + ;; Return all the elements before the first occurrence + ;; of X in LST. + (call/ec + (lambda (return) + (fold (lambda (element prefix) + (if (equal? element x) + (return (reverse prefix)) ; escape `fold' + (cons element prefix))) + '() + lst)))) + +(prefix 'a '(0 1 2 a 3 4 5)) +@result{} (0 1 2) +@end lisp +@end deffn + +@deffn {Scheme Syntax} let-escape-continuation k body @dots{} +@deffnx {Scheme Syntax} let/ec k body @dots{} +Bind @var{k} within @var{body} to an escape continuation. + +This is equivalent to +@code{(call/ec (lambda (@var{k}) @var{body} @dots{}))}. +@end deffn + +Additionally there is another helper primitive exported by @code{(ice-9 +control)}, so load up that module for @code{suspendable-continuation?}: + +@example +(use-modules (ice-9 control)) +@end example + +@deffn {Scheme Procedure} suspendable-continuation? tag +Return @code{#t} if a call to @code{abort-to-prompt} with the prompt tag +@var{tag} would produce a delimited continuation that could be resumed +later. + +Almost all continuations have this property. The exception is where +some code between the @code{call-with-prompt} and the +@code{abort-to-prompt} recursed through C for some reason, the +@code{abort-to-prompt} will succeed but any attempt to resume the +continuation (by calling it) would fail. This is because composing a +saved continuation with the current continuation involves relocating the +stack frames that were saved from the old stack onto a (possibly) new +position on the new stack, and Guile can only do this for stack frames +that it created for Scheme code, not stack frames created by the C +compiler. It's a bit gnarly but if you stick with Scheme, you won't +have any problem. + +If no prompt is found with the given tag, this procedure just returns +@code{#f}. +@end deffn + +@node Shift and Reset +@subsubsection Shift, Reset, and All That + +There is a whole zoo of delimited control operators, and as it does not +seem to be a bounded set, Guile implements support for them in a +separate module: + +@example +(use-modules (ice-9 control)) +@end example + +Firstly, we have a helpful abbreviation for the @code{call-with-prompt} +operator. + +@deffn {Scheme Syntax} % expr +@deffnx {Scheme Syntax} % expr handler +@deffnx {Scheme Syntax} % tag expr handler +Evaluate @var{expr} in a prompt, optionally specifying a tag and a +handler. If no tag is given, the default prompt tag is used. + +If no handler is given, a default handler is installed. The default +handler accepts a procedure of one argument, which will called on the +captured continuation, within a prompt. + +Sometimes it's easier just to show code, as in this case: + +@example +(define (default-prompt-handler k proc) + (% (default-prompt-tag) + (proc k) + default-prompt-handler)) +@end example + +The @code{%} symbol is chosen because it looks like a prompt. +@end deffn + +Likewise there is an abbreviation for @code{abort-to-prompt}, which +assumes the default prompt tag: + +@deffn {Scheme Procedure} abort val1 val2 @dots{} +Abort to the default prompt tag, passing @var{val1} @var{val2} @dots{} +to the handler. +@end deffn + +As mentioned before, @code{(ice-9 control)} also provides other +delimited control operators. This section is a bit technical, and +first-time users of delimited continuations should probably come back to +it after some practice with @code{%}. + +Still here? So, when one implements a delimited control operator like +@code{call-with-prompt}, one needs to make two decisions. Firstly, does +the handler run within or outside the prompt? Having the handler run +within the prompt allows an abort inside the handler to return to the +same prompt handler, which is often useful. However it prevents tail +calls from the handler, so it is less general. + +Similarly, does invoking a captured continuation reinstate a prompt? +Again we have the tradeoff of convenience versus proper tail calls. + +These decisions are captured in the Felleisen @dfn{F} operator. If +neither the continuations nor the handlers implicitly add a prompt, the +operator is known as @dfn{--F--}. This is the case for Guile's +@code{call-with-prompt} and @code{abort-to-prompt}. + +If both continuation and handler implicitly add prompts, then the +operator is @dfn{+F+}. @code{shift} and @code{reset} are such +operators. + +@deffn {Scheme Syntax} reset body1 body2 @dots{} +Establish a prompt, and evaluate @var{body1} @var{body2} @dots{} within +that prompt. + +The prompt handler is designed to work with @code{shift}, described +below. +@end deffn + +@deffn {Scheme Syntax} shift cont body1 body2 @dots{} +Abort to the nearest @code{reset}, and evaluate @var{body1} @var{body2} +@dots{} in a context in which the captured continuation is bound to +@var{cont}. + +As mentioned above, taken together, the @var{body1} @var{body2} @dots{} +expressions and the invocations of @var{cont} implicitly establish a +prompt. +@end deffn + +Interested readers are invited to explore Oleg Kiselyov's wonderful web +site at @uref{http://okmij.org/ftp/}, for more information on these +operators. + + +@node Continuations +@subsection Continuations +@cindex continuations + +A ``continuation'' is the code that will execute when a given function +or expression returns. For example, consider + +@example +(define (foo) + (display "hello\n") + (display (bar)) (newline) + (exit)) +@end example + +The continuation from the call to @code{bar} comprises a +@code{display} of the value returned, a @code{newline} and an +@code{exit}. This can be expressed as a function of one argument. + +@example +(lambda (r) + (display r) (newline) + (exit)) +@end example + +In Scheme, continuations are represented as special procedures just +like this. The special property is that when a continuation is called +it abandons the current program location and jumps directly to that +represented by the continuation. + +A continuation is like a dynamic label, capturing at run-time a point +in program execution, including all the nested calls that have lead to +it (or rather the code that will execute when those calls return). + +Continuations are created with the following functions. + +@deffn {Scheme Procedure} call-with-current-continuation proc +@deffnx {Scheme Procedure} call/cc proc +@rnindex call-with-current-continuation +Capture the current continuation and call @code{(@var{proc} +@var{cont})} with it. The return value is the value returned by +@var{proc}, or when @code{(@var{cont} @var{value})} is later invoked, +the return is the @var{value} passed. + +Normally @var{cont} should be called with one argument, but when the +location resumed is expecting multiple values (@pxref{Multiple +Values}) then they should be passed as multiple arguments, for +instance @code{(@var{cont} @var{x} @var{y} @var{z})}. + +@var{cont} may only be used from the same side of a continuation +barrier as it was created (@pxref{Continuation Barriers}), and in a +multi-threaded program only from the thread in which it was created. + +The call to @var{proc} is not part of the continuation captured, it runs +only when the continuation is created. Often a program will want to +store @var{cont} somewhere for later use; this can be done in +@var{proc}. + +The @code{call} in the name @code{call-with-current-continuation} +refers to the way a call to @var{proc} gives the newly created +continuation. It's not related to the way a call is used later to +invoke that continuation. + +@code{call/cc} is an alias for @code{call-with-current-continuation}. +This is in common use since the latter is rather long. +@end deffn + +@sp 1 +@noindent +Here is a simple example, + +@example +(define kont #f) +(format #t "the return is ~a\n" + (call/cc (lambda (k) + (set! kont k) + 1))) +@result{} the return is 1 + +(kont 2) +@result{} the return is 2 +@end example + +@code{call/cc} captures a continuation in which the value returned is +going to be displayed by @code{format}. The @code{lambda} stores this +in @code{kont} and gives an initial return @code{1} which is +displayed. The later invocation of @code{kont} resumes the captured +point, but this time returning @code{2}, which is displayed. + +When Guile is run interactively, a call to @code{format} like this has +an implicit return back to the read-eval-print loop. @code{call/cc} +captures that like any other return, which is why interactively +@code{kont} will come back to read more input. + +@sp 1 +C programmers may note that @code{call/cc} is like @code{setjmp} in +the way it records at runtime a point in program execution. A call to +a continuation is like a @code{longjmp} in that it abandons the +present location and goes to the recorded one. Like @code{longjmp}, +the value passed to the continuation is the value returned by +@code{call/cc} on resuming there. However @code{longjmp} can only go +up the program stack, but the continuation mechanism can go anywhere. + +When a continuation is invoked, @code{call/cc} and subsequent code +effectively ``returns'' a second time. It can be confusing to imagine +a function returning more times than it was called. It may help +instead to think of it being stealthily re-entered and then program +flow going on as normal. + +@code{dynamic-wind} (@pxref{Dynamic Wind}) can be used to ensure setup +and cleanup code is run when a program locus is resumed or abandoned +through the continuation mechanism. + +@sp 1 +Continuations are a powerful mechanism, and can be used to implement +almost any sort of control structure, such as loops, coroutines, or +exception handlers. + +However the implementation of continuations in Guile is not as +efficient as one might hope, because Guile is designed to cooperate +with programs written in other languages, such as C, which do not know +about continuations. Basically continuations are captured by a block +copy of the stack, and resumed by copying back. + +For this reason, continuations captured by @code{call/cc} should be used only +when there is no other simple way to achieve the desired result, or when the +elegance of the continuation mechanism outweighs the need for performance. + +Escapes upwards from loops or nested functions are generally best +handled with prompts (@pxref{Prompts}). Coroutines can be +efficiently implemented with cooperating threads (a thread holds a +full program stack but doesn't copy it around the way continuations +do). + + +@node Multiple Values +@subsection Returning and Accepting Multiple Values + +@cindex multiple values +@cindex receive + +Scheme allows a procedure to return more than one value to its caller. +This is quite different to other languages which only allow +single-value returns. Returning multiple values is different from +returning a list (or pair or vector) of values to the caller, because +conceptually not @emph{one} compound object is returned, but several +distinct values. + +The primitive procedures for handling multiple values are @code{values} +and @code{call-with-values}. @code{values} is used for returning +multiple values from a procedure. This is done by placing a call to +@code{values} with zero or more arguments in tail position in a +procedure body. @code{call-with-values} combines a procedure returning +multiple values with a procedure which accepts these values as +parameters. + +@rnindex values +@deffn {Scheme Procedure} values arg @dots{} +@deffnx {C Function} scm_values (args) +Delivers all of its arguments to its continuation. Except for +continuations created by the @code{call-with-values} procedure, +all continuations take exactly one value. The effect of +passing no value or more than one value to continuations that +were not created by @code{call-with-values} is unspecified. + +For @code{scm_values}, @var{args} is a list of arguments and the +return is a multiple-values object which the caller can return. In +the current implementation that object shares structure with +@var{args}, so @var{args} should not be modified subsequently. +@end deffn + +@deftypefn {C Function} SCM scm_c_values (SCM *base, size_t n) +@code{scm_c_values} is an alternative to @code{scm_values}. It creates +a new values object, and copies into it the @var{n} values starting from +@var{base}. + +Currently this creates a list and passes it to @code{scm_values}, but we +expect that in the future we will be able to use a more efficient +representation. +@end deftypefn + +@deftypefn {C Function} size_t scm_c_nvalues (SCM obj) +If @var{obj} is a multiple-values object, returns the number of values +it contains. Otherwise returns 1. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_value_ref (SCM obj, size_t idx) +Returns the value at the position specified by @var{idx} in +@var{obj}. Note that @var{obj} will ordinarily be a +multiple-values object, but it need not be. Any other object +represents a single value (itself), and is handled appropriately. +@end deftypefn + +@rnindex call-with-values +@deffn {Scheme Procedure} call-with-values producer consumer +Calls its @var{producer} argument with no values and a +continuation that, when passed some values, calls the +@var{consumer} procedure with those values as arguments. The +continuation for the call to @var{consumer} is the continuation +of the call to @code{call-with-values}. + +@example +(call-with-values (lambda () (values 4 5)) + (lambda (a b) b)) +@result{} 5 + +@end example +@example +(call-with-values * -) +@result{} -1 +@end example +@end deffn + +In addition to the fundamental procedures described above, Guile has a +module which exports a syntax called @code{receive}, which is much +more convenient. This is in the @code{(ice-9 receive)} and is the +same as specified by SRFI-8 (@pxref{SRFI-8}). + +@lisp +(use-modules (ice-9 receive)) +@end lisp + +@deffn {library syntax} receive formals expr body @dots{} +Evaluate the expression @var{expr}, and bind the result values (zero +or more) to the formal arguments in @var{formals}. @var{formals} is a +list of symbols, like the argument list in a @code{lambda} +(@pxref{Lambda}). After binding the variables, the expressions in +@var{body} @dots{} are evaluated in order, the return value is the +result from the last expression. + +For example getting results from @code{partition} in SRFI-1 +(@pxref{SRFI-1}), + +@example +(receive (odds evens) + (partition odd? '(7 4 2 8 3)) + (display odds) + (display " and ") + (display evens)) +@print{} (7 3) and (4 2 8) +@end example + +@end deffn + + +@node Exceptions +@subsection Exceptions +@cindex error handling +@cindex exception handling + +A common requirement in applications is to want to jump +@dfn{non-locally} from the depths of a computation back to, say, the +application's main processing loop. Usually, the place that is the +target of the jump is somewhere in the calling stack of procedures that +called the procedure that wants to jump back. For example, typical +logic for a key press driven application might look something like this: + +@example +main-loop: + read the next key press and call dispatch-key + +dispatch-key: + lookup the key in a keymap and call an appropriate procedure, + say find-file + +find-file: + interactively read the required file name, then call + find-specified-file + +find-specified-file: + check whether file exists; if not, jump back to main-loop + @dots{} +@end example + +The jump back to @code{main-loop} could be achieved by returning through +the stack one procedure at a time, using the return value of each +procedure to indicate the error condition, but Guile (like most modern +programming languages) provides an additional mechanism called +@dfn{exception handling} that can be used to implement such jumps much +more conveniently. + +@menu +* Exception Terminology:: Different ways to say the same thing. +* Catch:: Setting up to catch exceptions. +* Throw Handlers:: Handling exceptions before unwinding the stack. +* Throw:: Throwing an exception. +* Exception Implementation:: How Guile implements exceptions. +@end menu + + +@node Exception Terminology +@subsubsection Exception Terminology + +There are several variations on the terminology for dealing with +non-local jumps. It is useful to be aware of them, and to realize +that they all refer to the same basic mechanism. + +@itemize @bullet +@item +Actually making a non-local jump may be called @dfn{raising an +exception}, @dfn{raising a signal}, @dfn{throwing an exception} or +@dfn{doing a long jump}. When the jump indicates an error condition, +people may talk about @dfn{signalling}, @dfn{raising} or @dfn{throwing} +@dfn{an error}. + +@item +Handling the jump at its target may be referred to as @dfn{catching} or +@dfn{handling} the @dfn{exception}, @dfn{signal} or, where an error +condition is involved, @dfn{error}. +@end itemize + +Where @dfn{signal} and @dfn{signalling} are used, special care is needed +to avoid the risk of confusion with POSIX signals. + +This manual prefers to speak of throwing and catching exceptions, since +this terminology matches the corresponding Guile primitives. + +The exception mechanism described in this section has connections with +@dfn{delimited continuations} (@pxref{Prompts}). In particular, +throwing an exception is akin to invoking an @dfn{escape continuation} +(@pxref{Prompt Primitives, @code{call/ec}}). + + +@node Catch +@subsubsection Catching Exceptions + +@code{catch} is used to set up a target for a possible non-local jump. +The arguments of a @code{catch} expression are a @dfn{key}, which +restricts the set of exceptions to which this @code{catch} applies, a +thunk that specifies the code to execute and one or two @dfn{handler} +procedures that say what to do if an exception is thrown while executing +the code. If the execution thunk executes @dfn{normally}, which means +without throwing any exceptions, the handler procedures are not called +at all. + +When an exception is thrown using the @code{throw} function, the first +argument of the @code{throw} is a symbol that indicates the type of the +exception. For example, Guile throws an exception using the symbol +@code{numerical-overflow} to indicate numerical overflow errors such as +division by zero: + +@lisp +(/ 1 0) +@result{} +ABORT: (numerical-overflow) +@end lisp + +The @var{key} argument in a @code{catch} expression corresponds to this +symbol. @var{key} may be a specific symbol, such as +@code{numerical-overflow}, in which case the @code{catch} applies +specifically to exceptions of that type; or it may be @code{#t}, which +means that the @code{catch} applies to all exceptions, irrespective of +their type. + +The second argument of a @code{catch} expression should be a thunk +(i.e.@: a procedure that accepts no arguments) that specifies the normal +case code. The @code{catch} is active for the execution of this thunk, +including any code called directly or indirectly by the thunk's body. +Evaluation of the @code{catch} expression activates the catch and then +calls this thunk. + +The third argument of a @code{catch} expression is a handler procedure. +If an exception is thrown, this procedure is called with exactly the +arguments specified by the @code{throw}. Therefore, the handler +procedure must be designed to accept a number of arguments that +corresponds to the number of arguments in all @code{throw} expressions +that can be caught by this @code{catch}. + +The fourth, optional argument of a @code{catch} expression is another +handler procedure, called the @dfn{pre-unwind} handler. It differs from +the third argument in that if an exception is thrown, it is called, +@emph{before} the third argument handler, in exactly the dynamic context +of the @code{throw} expression that threw the exception. This means +that it is useful for capturing or displaying the stack at the point of +the @code{throw}, or for examining other aspects of the dynamic context, +such as fluid values, before the context is unwound back to that of the +prevailing @code{catch}. + +@deffn {Scheme Procedure} catch key thunk handler [pre-unwind-handler] +@deffnx {C Function} scm_catch_with_pre_unwind_handler (key, thunk, handler, pre_unwind_handler) +@deffnx {C Function} scm_catch (key, thunk, handler) +Invoke @var{thunk} in the dynamic context of @var{handler} for +exceptions matching @var{key}. If thunk throws to the symbol +@var{key}, then @var{handler} is invoked this way: +@lisp +(handler key args ...) +@end lisp + +@var{key} is a symbol or @code{#t}. + +@var{thunk} takes no arguments. If @var{thunk} returns +normally, that is the return value of @code{catch}. + +Handler is invoked outside the scope of its own @code{catch}. +If @var{handler} again throws to the same key, a new handler +from further up the call chain is invoked. + +If the key is @code{#t}, then a throw to @emph{any} symbol will +match this call to @code{catch}. + +If a @var{pre-unwind-handler} is given and @var{thunk} throws +an exception that matches @var{key}, Guile calls the +@var{pre-unwind-handler} before unwinding the dynamic state and +invoking the main @var{handler}. @var{pre-unwind-handler} should +be a procedure with the same signature as @var{handler}, that +is @code{(lambda (key . args))}. It is typically used to save +the stack at the point where the exception occurred, but can also +query other parts of the dynamic state at that point, such as +fluid values. + +A @var{pre-unwind-handler} can exit either normally or non-locally. +If it exits normally, Guile unwinds the stack and dynamic context +and then calls the normal (third argument) handler. If it exits +non-locally, that exit determines the continuation. +@end deffn + +If a handler procedure needs to match a variety of @code{throw} +expressions with varying numbers of arguments, you should write it like +this: + +@lisp +(lambda (key . args) + @dots{}) +@end lisp + +@noindent +The @var{key} argument is guaranteed always to be present, because a +@code{throw} without a @var{key} is not valid. The number and +interpretation of the @var{args} varies from one type of exception to +another, but should be specified by the documentation for each exception +type. + +Note that, once the normal (post-unwind) handler procedure is invoked, +the catch that led to the handler procedure being called is no longer +active. Therefore, if the handler procedure itself throws an exception, +that exception can only be caught by another active catch higher up the +call stack, if there is one. + +@sp 1 +@deftypefn {C Function} SCM scm_c_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, scm_t_catch_handler pre_unwind_handler, void *pre_unwind_handler_data) +@deftypefnx {C Function} SCM scm_internal_catch (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data) +The above @code{scm_catch_with_pre_unwind_handler} and @code{scm_catch} +take Scheme procedures as body and handler arguments. +@code{scm_c_catch} and @code{scm_internal_catch} are equivalents taking +C functions. + +@var{body} is called as @code{@var{body} (@var{body_data})} with a catch +on exceptions of the given @var{tag} type. If an exception is caught, +@var{pre_unwind_handler} and @var{handler} are called as +@code{@var{handler} (@var{handler_data}, @var{key}, @var{args})}. +@var{key} and @var{args} are the @code{SCM} key and argument list from +the @code{throw}. + +@tpindex scm_t_catch_body +@tpindex scm_t_catch_handler +@var{body} and @var{handler} should have the following prototypes. +@code{scm_t_catch_body} and @code{scm_t_catch_handler} are pointer +typedefs for these. + +@example +SCM body (void *data); +SCM handler (void *data, SCM key, SCM args); +@end example + +The @var{body_data} and @var{handler_data} parameters are passed to +the respective calls so an application can communicate extra +information to those functions. + +If the data consists of an @code{SCM} object, care should be taken that +it isn't garbage collected while still required. If the @code{SCM} is a +local C variable, one way to protect it is to pass a pointer to that +variable as the data parameter, since the C compiler will then know the +value must be held on the stack. Another way is to use +@code{scm_remember_upto_here_1} (@pxref{Foreign Object Memory +Management}). +@end deftypefn + + +@node Throw Handlers +@subsubsection Throw Handlers + +It's sometimes useful to be able to intercept an exception that is being +thrown before the stack is unwound. This could be to clean up some +related state, to print a backtrace, or to pass information about the +exception to a debugger, for example. The @code{with-throw-handler} +procedure provides a way to do this. + +@deffn {Scheme Procedure} with-throw-handler key thunk handler +@deffnx {C Function} scm_with_throw_handler (key, thunk, handler) +Add @var{handler} to the dynamic context as a throw handler +for key @var{key}, then invoke @var{thunk}. + +This behaves exactly like @code{catch}, except that it does not unwind +the stack before invoking @var{handler}. If the @var{handler} procedure +returns normally, Guile rethrows the same exception again to the next +innermost catch or throw handler. @var{handler} may exit nonlocally, of +course, via an explicit throw or via invoking a continuation. +@end deffn + +Typically @var{handler} is used to display a backtrace of the stack at +the point where the corresponding @code{throw} occurred, or to save off +this information for possible display later. + +Not unwinding the stack means that throwing an exception that is handled +via a throw handler is equivalent to calling the throw handler handler +inline instead of each @code{throw}, and then omitting the surrounding +@code{with-throw-handler}. In other words, + +@lisp +(with-throw-handler 'key + (lambda () @dots{} (throw 'key args @dots{}) @dots{}) + handler) +@end lisp + +@noindent +is mostly equivalent to + +@lisp +((lambda () @dots{} (handler 'key args @dots{}) @dots{})) +@end lisp + +In particular, the dynamic context when @var{handler} is invoked is that +of the site where @code{throw} is called. The examples are not quite +equivalent, because the body of a @code{with-throw-handler} is not in +tail position with respect to the @code{with-throw-handler}, and if +@var{handler} exits normally, Guile arranges to rethrow the error, but +hopefully the intention is clear. (For an introduction to what is meant +by dynamic context, @xref{Dynamic Wind}.) + +@deftypefn {C Function} SCM scm_c_with_throw_handler (SCM tag, scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data, int lazy_catch_p) +The above @code{scm_with_throw_handler} takes Scheme procedures as body +(thunk) and handler arguments. @code{scm_c_with_throw_handler} is an +equivalent taking C functions. See @code{scm_c_catch} (@pxref{Catch}) +for a description of the parameters, the behaviour however of course +follows @code{with-throw-handler}. +@end deftypefn + +If @var{thunk} throws an exception, Guile handles that exception by +invoking the innermost @code{catch} or throw handler whose key matches +that of the exception. When the innermost thing is a throw handler, +Guile calls the specified handler procedure using @code{(apply +@var{handler} key args)}. The handler procedure may either return +normally or exit non-locally. If it returns normally, Guile passes the +exception on to the next innermost @code{catch} or throw handler. If it +exits non-locally, that exit determines the continuation. + +The behaviour of a throw handler is very similar to that of a +@code{catch} expression's optional pre-unwind handler. In particular, a +throw handler's handler procedure is invoked in the exact dynamic +context of the @code{throw} expression, just as a pre-unwind handler is. +@code{with-throw-handler} may be seen as a half-@code{catch}: it does +everything that a @code{catch} would do until the point where +@code{catch} would start unwinding the stack and dynamic context, but +then it rethrows to the next innermost @code{catch} or throw handler +instead. + +Note also that since the dynamic context is not unwound, if a +@code{with-throw-handler} handler throws to a key that does not match +the @code{with-throw-handler} expression's @var{key}, the new throw may +be handled by a @code{catch} or throw handler that is @emph{closer} to +the throw than the first @code{with-throw-handler}. + +Here is an example to illustrate this behavior: + +@lisp +(catch 'a + (lambda () + (with-throw-handler 'b + (lambda () + (catch 'a + (lambda () + (throw 'b)) + inner-handler)) + (lambda (key . args) + (throw 'a)))) + outer-handler) +@end lisp + +@noindent +This code will call @code{inner-handler} and then continue with the +continuation of the inner @code{catch}. + + +@node Throw +@subsubsection Throwing Exceptions + +The @code{throw} primitive is used to throw an exception. One argument, +the @var{key}, is mandatory, and must be a symbol; it indicates the type +of exception that is being thrown. Following the @var{key}, +@code{throw} accepts any number of additional arguments, whose meaning +depends on the exception type. The documentation for each possible type +of exception should specify the additional arguments that are expected +for that kind of exception. + +@deffn {Scheme Procedure} throw key arg @dots{} +@deffnx {C Function} scm_throw (key, args) +Invoke the catch form matching @var{key}, passing @var{arg} @dots{} to +the @var{handler}. + +@var{key} is a symbol. It will match catches of the same symbol or of +@code{#t}. + +If there is no handler at all, Guile prints an error and then exits. +@end deffn + +When an exception is thrown, it will be caught by the innermost +@code{catch} or throw handler that applies to the type of the thrown +exception; in other words, whose @var{key} is either @code{#t} or the +same symbol as that used in the @code{throw} expression. Once Guile has +identified the appropriate @code{catch} or throw handler, it handles the +exception by applying the relevant handler procedure(s) to the arguments +of the @code{throw}. + +If there is no appropriate @code{catch} or throw handler for a thrown +exception, Guile prints an error to the current error port indicating an +uncaught exception, and then exits. In practice, it is quite difficult +to observe this behaviour, because Guile when used interactively +installs a top level @code{catch} handler that will catch all exceptions +and print an appropriate error message @emph{without} exiting. For +example, this is what happens if you try to throw an unhandled exception +in the standard Guile REPL; note that Guile's command loop continues +after the error message: + +@lisp +guile> (throw 'badex) +<unnamed port>:3:1: In procedure gsubr-apply @dots{} +<unnamed port>:3:1: unhandled-exception: badex +ABORT: (misc-error) +guile> +@end lisp + +The default uncaught exception behaviour can be observed by evaluating a +@code{throw} expression from the shell command line: + +@example +$ guile -c "(begin (throw 'badex) (display \"here\\n\"))" +guile: uncaught throw to badex: () +$ +@end example + +@noindent +That Guile exits immediately following the uncaught exception +is shown by the absence of any output from the @code{display} +expression, because Guile never gets to the point of evaluating that +expression. + + +@node Exception Implementation +@subsubsection How Guile Implements Exceptions + +It is traditional in Scheme to implement exception systems using +@code{call-with-current-continuation}. Continuations +(@pxref{Continuations}) are such a powerful concept that any other +control mechanism --- including @code{catch} and @code{throw} --- can be +implemented in terms of them. + +Guile does not implement @code{catch} and @code{throw} like this, +though. Why not? Because Guile is specifically designed to be easy to +integrate with applications written in C. In a mixed Scheme/C +environment, the concept of @dfn{continuation} must logically include +``what happens next'' in the C parts of the application as well as the +Scheme parts, and it turns out that the only reasonable way of +implementing continuations like this is to save and restore the complete +C stack. + +So Guile's implementation of @code{call-with-current-continuation} is a +stack copying one. This allows it to interact well with ordinary C +code, but means that creating and calling a continuation is slowed down +by the time that it takes to copy the C stack. + +The more targeted mechanism provided by @code{catch} and @code{throw} +does not need to save and restore the C stack because the @code{throw} +always jumps to a location higher up the stack of the code that executes +the @code{throw}. Therefore Guile implements the @code{catch} and +@code{throw} primitives independently of +@code{call-with-current-continuation}, in a way that takes advantage of +this @emph{upwards only} nature of exceptions. + + +@node Error Reporting +@subsection Procedures for Signaling Errors + +Guile provides a set of convenience procedures for signaling error +conditions that are implemented on top of the exception primitives just +described. + +@deffn {Scheme Procedure} error msg arg @dots{} +Raise an error with key @code{misc-error} and a message constructed by +displaying @var{msg} and writing @var{arg} @enddots{}. +@end deffn + +@deffn {Scheme Procedure} scm-error key subr message args data +@deffnx {C Function} scm_error_scm (key, subr, message, args, data) +Raise an error with key @var{key}. @var{subr} can be a string +naming the procedure associated with the error, or @code{#f}. +@var{message} is the error message string, possibly containing +@code{~S} and @code{~A} escapes. When an error is reported, +these are replaced by formatting the corresponding members of +@var{args}: @code{~A} (was @code{%s} in older versions of +Guile) formats using @code{display} and @code{~S} (was +@code{%S}) formats using @code{write}. @var{data} is a list or +@code{#f} depending on @var{key}: if @var{key} is +@code{system-error} then it should be a list containing the +Unix @code{errno} value; If @var{key} is @code{signal} then it +should be a list containing the Unix signal number; If +@var{key} is @code{out-of-range}, @code{wrong-type-arg}, +or @code{keyword-argument-error}, +it is a list containing the bad value; otherwise +it will usually be @code{#f}. +@end deffn + +@deffn {Scheme Procedure} strerror err +@deffnx {C Function} scm_strerror (err) +Return the Unix error message corresponding to @var{err}, an integer +@code{errno} value. + +When @code{setlocale} has been called (@pxref{Locales}), the message +is in the language and charset of @code{LC_MESSAGES}. (This is done +by the C library.) +@end deffn + +@c begin (scm-doc-string "boot-9.scm" "false-if-exception") +@deffn syntax false-if-exception expr +Returns the result of evaluating its argument; however +if an exception occurs then @code{#f} is returned instead. +@end deffn +@c end + + +@node Dynamic Wind +@subsection Dynamic Wind + +For Scheme code, the fundamental procedure to react to non-local entry +and exits of dynamic contexts is @code{dynamic-wind}. C code could +use @code{scm_internal_dynamic_wind}, but since C does not allow the +convenient construction of anonymous procedures that close over +lexical variables, this will be, well, inconvenient. + +Therefore, Guile offers the functions @code{scm_dynwind_begin} and +@code{scm_dynwind_end} to delimit a dynamic extent. Within this +dynamic extent, which is called a @dfn{dynwind context}, you can +perform various @dfn{dynwind actions} that control what happens when +the dynwind context is entered or left. For example, you can register +a cleanup routine with @code{scm_dynwind_unwind_handler} that is +executed when the context is left. There are several other more +specialized dynwind actions as well, for example to temporarily block +the execution of asyncs or to temporarily change the current output +port. They are described elsewhere in this manual. + +Here is an example that shows how to prevent memory leaks. + +@example + +/* Suppose there is a function called FOO in some library that you + would like to make available to Scheme code (or to C code that + follows the Scheme conventions). + + FOO takes two C strings and returns a new string. When an error has + occurred in FOO, it returns NULL. +*/ + +char *foo (char *s1, char *s2); + +/* SCM_FOO interfaces the C function FOO to the Scheme way of life. + It takes care to free up all temporary strings in the case of + non-local exits. + */ + +SCM +scm_foo (SCM s1, SCM s2) +@{ + char *c_s1, *c_s2, *c_res; + + scm_dynwind_begin (0); + + c_s1 = scm_to_locale_string (s1); + + /* Call 'free (c_s1)' when the dynwind context is left. + */ + scm_dynwind_unwind_handler (free, c_s1, SCM_F_WIND_EXPLICITLY); + + c_s2 = scm_to_locale_string (s2); + + /* Same as above, but more concisely. + */ + scm_dynwind_free (c_s2); + + c_res = foo (c_s1, c_s2); + if (c_res == NULL) + scm_memory_error ("foo"); + + scm_dynwind_end (); + + return scm_take_locale_string (res); +@} +@end example + +@rnindex dynamic-wind +@deffn {Scheme Procedure} dynamic-wind in_guard thunk out_guard +@deffnx {C Function} scm_dynamic_wind (in_guard, thunk, out_guard) +All three arguments must be 0-argument procedures. +@var{in_guard} is called, then @var{thunk}, then +@var{out_guard}. + +If, any time during the execution of @var{thunk}, the +dynamic extent of the @code{dynamic-wind} expression is escaped +non-locally, @var{out_guard} is called. If the dynamic extent of +the dynamic-wind is re-entered, @var{in_guard} is called. Thus +@var{in_guard} and @var{out_guard} may be called any number of +times. + +@lisp +(define x 'normal-binding) +@result{} x +(define a-cont + (call-with-current-continuation + (lambda (escape) + (let ((old-x x)) + (dynamic-wind + ;; in-guard: + ;; + (lambda () (set! x 'special-binding)) + + ;; thunk + ;; + (lambda () (display x) (newline) + (call-with-current-continuation escape) + (display x) (newline) + x) + + ;; out-guard: + ;; + (lambda () (set! x old-x))))))) +;; Prints: +special-binding +;; Evaluates to: +@result{} a-cont +x +@result{} normal-binding +(a-cont #f) +;; Prints: +special-binding +;; Evaluates to: +@result{} a-cont ;; the value of the (define a-cont...) +x +@result{} normal-binding +a-cont +@result{} special-binding +@end lisp +@end deffn + +@deftp {C Type} scm_t_dynwind_flags +This is an enumeration of several flags that modify the behavior of +@code{scm_dynwind_begin}. The flags are listed in the following +table. + +@table @code +@item SCM_F_DYNWIND_REWINDABLE +The dynamic context is @dfn{rewindable}. This means that it can be +reentered non-locally (via the invocation of a continuation). The +default is that a dynwind context can not be reentered non-locally. +@end table + +@end deftp + +@deftypefn {C Function} void scm_dynwind_begin (scm_t_dynwind_flags flags) +The function @code{scm_dynwind_begin} starts a new dynamic context and +makes it the `current' one. + +The @var{flags} argument determines the default behavior of the +context. Normally, use 0. This will result in a context that can not +be reentered with a captured continuation. When you are prepared to +handle reentries, include @code{SCM_F_DYNWIND_REWINDABLE} in +@var{flags}. + +Being prepared for reentry means that the effects of unwind handlers +can be undone on reentry. In the example above, we want to prevent a +memory leak on non-local exit and thus register an unwind handler that +frees the memory. But once the memory is freed, we can not get it +back on reentry. Thus reentry can not be allowed. + +The consequence is that continuations become less useful when +non-reentrant contexts are captured, but you don't need to worry +about that too much. + +The context is ended either implicitly when a non-local exit happens, +or explicitly with @code{scm_dynwind_end}. You must make sure that a +dynwind context is indeed ended properly. If you fail to call +@code{scm_dynwind_end} for each @code{scm_dynwind_begin}, the behavior +is undefined. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_end () +End the current dynamic context explicitly and make the previous one +current. +@end deftypefn + +@deftp {C Type} scm_t_wind_flags +This is an enumeration of several flags that modify the behavior of +@code{scm_dynwind_unwind_handler} and +@code{scm_dynwind_rewind_handler}. The flags are listed in the +following table. + +@table @code +@item SCM_F_WIND_EXPLICITLY +@vindex SCM_F_WIND_EXPLICITLY +The registered action is also carried out when the dynwind context is +entered or left locally. +@end table +@end deftp + +@deftypefn {C Function} void scm_dynwind_unwind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags) +@deftypefnx {C Function} void scm_dynwind_unwind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags) +Arranges for @var{func} to be called with @var{data} as its arguments +when the current context ends implicitly. If @var{flags} contains +@code{SCM_F_WIND_EXPLICITLY}, @var{func} is also called when the +context ends explicitly with @code{scm_dynwind_end}. + +The function @code{scm_dynwind_unwind_handler_with_scm} takes care that +@var{data} is protected from garbage collection. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_rewind_handler (void (*func)(void *), void *data, scm_t_wind_flags flags) +@deftypefnx {C Function} void scm_dynwind_rewind_handler_with_scm (void (*func)(SCM), SCM data, scm_t_wind_flags flags) +Arrange for @var{func} to be called with @var{data} as its argument when +the current context is restarted by rewinding the stack. When @var{flags} +contains @code{SCM_F_WIND_EXPLICITLY}, @var{func} is called immediately +as well. + +The function @code{scm_dynwind_rewind_handler_with_scm} takes care that +@var{data} is protected from garbage collection. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_free (void *mem) +Arrange for @var{mem} to be freed automatically whenever the current +context is exited, whether normally or non-locally. +@code{scm_dynwind_free (mem)} is an equivalent shorthand for +@code{scm_dynwind_unwind_handler (free, mem, SCM_F_WIND_EXPLICITLY)}. +@end deftypefn + + +@node Fluids and Dynamic States +@subsection Fluids and Dynamic States + +@cindex fluids + +A @emph{fluid} is a variable whose value is associated with the dynamic +extent of a function call. In the same way that an operating system +runs a process with a given set of current input and output ports (or +file descriptors), in Guile you can arrange to call a function while +binding a fluid to a particular value. That association between fluid +and value will exist during the dynamic extent of the function call. + +Fluids are a therefore a building block for implementing dynamically +scoped variables. Dynamically scoped variables are useful when you want +to set a variable to a value during some dynamic extent in the execution +of your program and have them revert to their original value when the +control flow is outside of this dynamic extent. See the description of +@code{with-fluids} below for details. This association between fluids, +values, and dynamic extents is robust to multiple entries (as when a +captured continuation is invoked more than once) and early exits (for +example, when throwing exceptions). + +Guile uses fluids to implement parameters (@pxref{Parameters}). Usually +you just want to use parameters directly. However it can be useful to +know what a fluid is and how it works, so that's what this section is +about. + +The current set of fluid-value associations can be captured in a +@emph{dynamic state} object. A dynamic extent is simply that: a +snapshot of the current fluid-value associations. Guile users can +capture the current dynamic state with @code{current-dynamic-state} and +restore it later via @code{with-dynamic-state} or similar procedures. +This facility is especially useful when implementing lightweight +thread-like abstractions. + +New fluids are created with @code{make-fluid} and @code{fluid?} is +used for testing whether an object is actually a fluid. The values +stored in a fluid can be accessed with @code{fluid-ref} and +@code{fluid-set!}. + +@xref{Thread Local Variables}, for further notes on fluids, threads, +parameters, and dynamic states. + +@deffn {Scheme Procedure} make-fluid [dflt] +@deffnx {C Function} scm_make_fluid () +@deffnx {C Function} scm_make_fluid_with_default (dflt) +Return a newly created fluid, whose initial value is @var{dflt}, or +@code{#f} if @var{dflt} is not given. +Fluids are objects that can hold one +value per dynamic state. That is, modifications to this value are +only visible to code that executes with the same dynamic state as +the modifying code. When a new dynamic state is constructed, it +inherits the values from its parent. Because each thread normally executes +with its own dynamic state, you can use fluids for thread local storage. +@end deffn + +@deffn {Scheme Procedure} make-unbound-fluid +@deffnx {C Function} scm_make_unbound_fluid () +Return a new fluid that is initially unbound (instead of being +implicitly bound to some definite value). +@end deffn + +@deffn {Scheme Procedure} fluid? obj +@deffnx {C Function} scm_fluid_p (obj) +Return @code{#t} if @var{obj} is a fluid; otherwise, return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} fluid-ref fluid +@deffnx {C Function} scm_fluid_ref (fluid) +Return the value associated with @var{fluid} in the current +dynamic root. If @var{fluid} has not been set, then return +its default value. Calling @code{fluid-ref} on an unbound fluid produces +a runtime error. +@end deffn + +@deffn {Scheme Procedure} fluid-set! fluid value +@deffnx {C Function} scm_fluid_set_x (fluid, value) +Set the value associated with @var{fluid} in the current dynamic root. +@end deffn + +@deffn {Scheme Procedure} fluid-ref* fluid depth +@deffnx {C Function} scm_fluid_ref_star (fluid, depth) +Return the @var{depth}th oldest value associated with @var{fluid} in the +current thread. If @var{depth} equals or exceeds the number of values +that have been assigned to @var{fluid}, return the default value of the +fluid. @code{(fluid-ref* f 0)} is equivalent to @code{(fluid-ref f)}. + +@code{fluid-ref*} is useful when you want to maintain a stack-like +structure in a fluid, such as the stack of current exception handlers. +Using @code{fluid-ref*} instead of an explicit stack allows any partial +continuation captured by @code{call-with-prompt} to only capture the +bindings made within the limits of the prompt instead of the entire +continuation. @xref{Prompts}, for more on delimited continuations. +@end deffn + +@deffn {Scheme Procedure} fluid-unset! fluid +@deffnx {C Function} scm_fluid_unset_x (fluid) +Disassociate the given fluid from any value, making it unbound. +@end deffn + +@deffn {Scheme Procedure} fluid-bound? fluid +@deffnx {C Function} scm_fluid_bound_p (fluid) +Returns @code{#t} if the given fluid is bound to a value, otherwise +@code{#f}. +@end deffn + +@code{with-fluids*} temporarily changes the values of one or more fluids, +so that the given procedure and each procedure called by it access the +given values. After the procedure returns, the old values are restored. + +@deffn {Scheme Procedure} with-fluid* fluid value thunk +@deffnx {C Function} scm_with_fluid (fluid, value, thunk) +Set @var{fluid} to @var{value} temporarily, and call @var{thunk}. +@var{thunk} must be a procedure with no argument. +@end deffn + +@deffn {Scheme Procedure} with-fluids* fluids values thunk +@deffnx {C Function} scm_with_fluids (fluids, values, thunk) +Set @var{fluids} to @var{values} temporary, and call @var{thunk}. +@var{fluids} must be a list of fluids and @var{values} must be the +same number of their values to be applied. Each substitution is done +in the order given. @var{thunk} must be a procedure with no argument. +It is called inside a @code{dynamic-wind} and the fluids are +set/restored when control enter or leaves the established dynamic +extent. +@end deffn + +@deffn {Scheme Macro} with-fluids ((fluid value) @dots{}) body1 body2 @dots{} +Execute body @var{body1} @var{body2} @dots{} while each @var{fluid} is +set to the corresponding @var{value}. Both @var{fluid} and @var{value} +are evaluated and @var{fluid} must yield a fluid. The body is executed +inside a @code{dynamic-wind} and the fluids are set/restored when +control enter or leaves the established dynamic extent. +@end deffn + +@deftypefn {C Function} SCM scm_c_with_fluids (SCM fluids, SCM vals, SCM (*cproc)(void *), void *data) +@deftypefnx {C Function} SCM scm_c_with_fluid (SCM fluid, SCM val, SCM (*cproc)(void *), void *data) +The function @code{scm_c_with_fluids} is like @code{scm_with_fluids} +except that it takes a C function to call instead of a Scheme thunk. + +The function @code{scm_c_with_fluid} is similar but only allows one +fluid to be set instead of a list. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_fluid (SCM fluid, SCM val) +This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). During the dynwind context, the fluid @var{fluid} is set to +@var{val}. + +More precisely, the value of the fluid is swapped with a `backup' +value whenever the dynwind context is entered or left. The backup +value is initialized with the @var{val} argument. +@end deftypefn + +@deffn {Scheme Procedure} dynamic-state? obj +@deffnx {C Function} scm_dynamic_state_p (obj) +Return @code{#t} if @var{obj} is a dynamic state object; +return @code{#f} otherwise. +@end deffn + +@deftypefn {C Procedure} int scm_is_dynamic_state (SCM obj) +Return non-zero if @var{obj} is a dynamic state object; +return zero otherwise. +@end deftypefn + +@deffn {Scheme Procedure} current-dynamic-state +@deffnx {C Function} scm_current_dynamic_state () +Return a snapshot of the current fluid-value associations as a fresh +dynamic state object. +@end deffn + +@deffn {Scheme Procedure} set-current-dynamic-state state +@deffnx {C Function} scm_set_current_dynamic_state (state) +Restore the saved fluid-value associations from @var{state}, replacing +the current fluid-value associations. Return the current fluid-value +associatoins as a dynamic state object, as in +@code{current-dynamic-state}. +@end deffn + +@deffn {Scheme Procedure} with-dynamic-state state proc +@deffnx {C Function} scm_with_dynamic_state (state, proc) +Call @var{proc} while the fluid bindings from @var{state} have been made +current, saving the current fluid bindings. When control leaves the +invocation of @var{proc}, restore the saved bindings, saving instead the +fluid bindings from inside the call. If control later re-enters +@var{proc}, restore those saved bindings, saving the current bindings, +and so on. +@end deffn + +@deftypefn {C Procedure} void scm_dynwind_current_dynamic_state (SCM state) +Set the current dynamic state to @var{state} for the current dynwind +context. Like @code{with-dynamic-state}, but in terms of Guile's +``dynwind'' C API. +@end deftypefn + +@deftypefn {C Procedure} {void *} scm_c_with_dynamic_state (SCM state, void *(*func)(void *), void *data) +Like @code{scm_with_dynamic_state}, but call @var{func} with +@var{data}. +@end deftypefn + +@node Parameters +@subsection Parameters + +@cindex SRFI-39 +@cindex parameter object +@tindex Parameter + +Parameters are Guile's facility for dynamically bound variables. + +On the most basic level, a parameter object is a procedure. Calling it +with no arguments returns its value. Calling it with one argument sets +the value. + +@example +(define my-param (make-parameter 123)) +(my-param) @result{} 123 +(my-param 456) +(my-param) @result{} 456 +@end example + +The @code{parameterize} special form establishes new locations for +parameters, those new locations having effect within the dynamic extent +of the @code{parameterize} body. Leaving restores the previous +locations. Re-entering (through a saved continuation) will again use +the new locations. + +@example +(parameterize ((my-param 789)) + (my-param)) @result{} 789 +(my-param) @result{} 456 +@end example + +Parameters are like dynamically bound variables in other Lisp dialects. +They allow an application to establish parameter settings (as the name +suggests) just for the execution of a particular bit of code, restoring +when done. Examples of such parameters might be case-sensitivity for a +search, or a prompt for user input. + +Global variables are not as good as parameter objects for this sort of +thing. Changes to them are visible to all threads, but in Guile +parameter object locations are per-thread, thereby truly limiting the +effect of @code{parameterize} to just its dynamic execution. + +Passing arguments to functions is thread-safe, but that soon becomes +tedious when there's more than a few or when they need to pass down +through several layers of calls before reaching the point they should +affect. Introducing a new setting to existing code is often easier with +a parameter object than adding arguments. + +@deffn {Scheme Procedure} make-parameter init [converter] +Return a new parameter object, with initial value @var{init}. + +If a @var{converter} is given, then a call @code{(@var{converter} +val)} is made for each value set, its return is the value stored. +Such a call is made for the @var{init} initial value too. + +A @var{converter} allows values to be validated, or put into a +canonical form. For example, + +@example +(define my-param (make-parameter 123 + (lambda (val) + (if (not (number? val)) + (error "must be a number")) + (inexact->exact val)))) +(my-param 0.75) +(my-param) @result{} 3/4 +@end example +@end deffn + +@deffn {library syntax} parameterize ((param value) @dots{}) body1 body2 @dots{} +Establish a new dynamic scope with the given @var{param}s bound to new +locations and set to the given @var{value}s. @var{body1} @var{body2} +@dots{} is evaluated in that environment. The value returned is that of +last body form. + +Each @var{param} is an expression which is evaluated to get the +parameter object. Often this will just be the name of a variable +holding the object, but it can be anything that evaluates to a +parameter. + +The @var{param} expressions and @var{value} expressions are all +evaluated before establishing the new dynamic bindings, and they're +evaluated in an unspecified order. + +For example, + +@example +(define prompt (make-parameter "Type something: ")) +(define (get-input) + (display (prompt)) + ...) + +(parameterize ((prompt "Type a number: ")) + (get-input) + ...) +@end example +@end deffn + +Parameter objects are implemented using fluids (@pxref{Fluids and +Dynamic States}), so each dynamic state has its own parameter +locations. That includes the separate locations when outside any +@code{parameterize} form. When a parameter is created it gets a +separate initial location in each dynamic state, all initialized to the +given @var{init} value. + +New code should probably just use parameters instead of fluids, because +the interface is better. But for migrating old code or otherwise +providing interoperability, Guile provides the @code{fluid->parameter} +procedure: + +@deffn {Scheme Procedure} fluid->parameter fluid [conv] +Make a parameter that wraps a fluid. + +The value of the parameter will be the same as the value of the fluid. +If the parameter is rebound in some dynamic extent, perhaps via +@code{parameterize}, the new value will be run through the optional +@var{conv} procedure, as with any parameter. Note that unlike +@code{make-parameter}, @var{conv} is not applied to the initial value. +@end deffn + +As alluded to above, because each thread usually has a separate dynamic +state, each thread has its own locations behind parameter objects, and +changes in one thread are not visible to any other. When a new dynamic +state or thread is created, the values of parameters in the originating +context are copied, into new locations. + +@cindex SRFI-39 +Guile's parameters conform to SRFI-39 (@pxref{SRFI-39}). + + +@node Handling Errors +@subsection How to Handle Errors + +Error handling is based on @code{catch} and @code{throw}. Errors are +always thrown with a @var{key} and four arguments: + +@itemize @bullet +@item +@var{key}: a symbol which indicates the type of error. The symbols used +by libguile are listed below. + +@item +@var{subr}: the name of the procedure from which the error is thrown, or +@code{#f}. + +@item +@var{message}: a string (possibly language and system dependent) +describing the error. The tokens @code{~A} and @code{~S} can be +embedded within the message: they will be replaced with members of the +@var{args} list when the message is printed. @code{~A} indicates an +argument printed using @code{display}, while @code{~S} indicates an +argument printed using @code{write}. @var{message} can also be +@code{#f}, to allow it to be derived from the @var{key} by the error +handler (may be useful if the @var{key} is to be thrown from both C and +Scheme). + +@item +@var{args}: a list of arguments to be used to expand @code{~A} and +@code{~S} tokens in @var{message}. Can also be @code{#f} if no +arguments are required. + +@item +@var{rest}: a list of any additional objects required. e.g., when the +key is @code{'system-error}, this contains the C errno value. Can also +be @code{#f} if no additional objects are required. +@end itemize + +In addition to @code{catch} and @code{throw}, the following Scheme +facilities are available: + +@deffn {Scheme Procedure} display-error frame port subr message args rest +@deffnx {C Function} scm_display_error (frame, port, subr, message, args, rest) +Display an error message to the output port @var{port}. +@var{frame} is the frame in which the error occurred, @var{subr} is +the name of the procedure in which the error occurred and +@var{message} is the actual error message, which may contain +formatting instructions. These will format the arguments in +the list @var{args} accordingly. @var{rest} is currently +ignored. +@end deffn + +The following are the error keys defined by libguile and the situations +in which they are used: + +@itemize @bullet +@item +@cindex @code{error-signal} +@code{error-signal}: thrown after receiving an unhandled fatal signal +such as SIGSEGV, SIGBUS, SIGFPE etc. The @var{rest} argument in the throw +contains the coded signal number (at present this is not the same as the +usual Unix signal number). + +@item +@cindex @code{system-error} +@code{system-error}: thrown after the operating system indicates an +error condition. The @var{rest} argument in the throw contains the +errno value. + +@item +@cindex @code{numerical-overflow} +@code{numerical-overflow}: numerical overflow. + +@item +@cindex @code{out-of-range} +@code{out-of-range}: the arguments to a procedure do not fall within the +accepted domain. + +@item +@cindex @code{wrong-type-arg} +@code{wrong-type-arg}: an argument to a procedure has the wrong type. + +@item +@cindex @code{wrong-number-of-args} +@code{wrong-number-of-args}: a procedure was called with the wrong number +of arguments. + +@item +@cindex @code{memory-allocation-error} +@code{memory-allocation-error}: memory allocation error. + +@item +@cindex @code{stack-overflow} +@code{stack-overflow}: stack overflow error. + +@item +@cindex @code{regular-expression-syntax} +@code{regular-expression-syntax}: errors generated by the regular +expression library. + +@item +@cindex @code{misc-error} +@code{misc-error}: other errors. +@end itemize + + +@subsubsection C Support + +In the following C functions, @var{SUBR} and @var{MESSAGE} parameters +can be @code{NULL} to give the effect of @code{#f} described above. + +@deftypefn {C Function} SCM scm_error (SCM @var{key}, char *@var{subr}, char *@var{message}, SCM @var{args}, SCM @var{rest}) +Throw an error, as per @code{scm-error} (@pxref{Error Reporting}). +@end deftypefn + +@deftypefn {C Function} void scm_syserror (char *@var{subr}) +@deftypefnx {C Function} void scm_syserror_msg (char *@var{subr}, char *@var{message}, SCM @var{args}) +Throw an error with key @code{system-error} and supply @code{errno} in +the @var{rest} argument. For @code{scm_syserror} the message is +generated using @code{strerror}. + +Care should be taken that any code in between the failing operation +and the call to these routines doesn't change @code{errno}. +@end deftypefn + +@deftypefn {C Function} void scm_num_overflow (char *@var{subr}) +@deftypefnx {C Function} void scm_out_of_range (char *@var{subr}, SCM @var{bad_value}) +@deftypefnx {C Function} void scm_wrong_num_args (SCM @var{proc}) +@deftypefnx {C Function} void scm_wrong_type_arg (char *@var{subr}, int @var{argnum}, SCM @var{bad_value}) +@deftypefnx {C Function} void scm_wrong_type_arg_msg (char *@var{subr}, int @var{argnum}, SCM @var{bad_value}, const char *@var{expected}) +@deftypefnx {C Function} void scm_memory_error (char *@var{subr}) +@deftypefnx {C Function} void scm_misc_error (const char *@var{subr}, const char *@var{message}, SCM @var{args}) +Throw an error with the various keys described above. + +In @code{scm_wrong_num_args}, @var{proc} should be a Scheme symbol +which is the name of the procedure incorrectly invoked. The other +routines take the name of the invoked procedure as a C string. + +In @code{scm_wrong_type_arg_msg}, @var{expected} is a C string +describing the type of argument that was expected. + +In @code{scm_misc_error}, @var{message} is the error message string, +possibly containing @code{simple-format} escapes (@pxref{Simple +Output}), and the corresponding arguments in the @var{args} list. +@end deftypefn + + +@subsubsection Signalling Type Errors + +Every function visible at the Scheme level should aggressively check the +types of its arguments, to avoid misinterpreting a value, and perhaps +causing a segmentation fault. Guile provides some macros to make this +easier. + +@deftypefn Macro void SCM_ASSERT (int @var{test}, SCM @var{obj}, unsigned int @var{position}, const char *@var{subr}) +@deftypefnx Macro void SCM_ASSERT_TYPE (int @var{test}, SCM @var{obj}, unsigned int @var{position}, const char *@var{subr}, const char *@var{expected}) +If @var{test} is zero, signal a ``wrong type argument'' error, +attributed to the subroutine named @var{subr}, operating on the value +@var{obj}, which is the @var{position}'th argument of @var{subr}. + +In @code{SCM_ASSERT_TYPE}, @var{expected} is a C string describing the +type of argument that was expected. +@end deftypefn + +@deftypefn Macro int SCM_ARG1 +@deftypefnx Macro int SCM_ARG2 +@deftypefnx Macro int SCM_ARG3 +@deftypefnx Macro int SCM_ARG4 +@deftypefnx Macro int SCM_ARG5 +@deftypefnx Macro int SCM_ARG6 +@deftypefnx Macro int SCM_ARG7 +One of the above values can be used for @var{position} to indicate the +number of the argument of @var{subr} which is being checked. +Alternatively, a positive integer number can be used, which allows to +check arguments after the seventh. However, for parameter numbers up to +seven it is preferable to use @code{SCM_ARGN} instead of the +corresponding raw number, since it will make the code easier to +understand. +@end deftypefn + +@deftypefn Macro int SCM_ARGn +Passing a value of zero or @code{SCM_ARGn} for @var{position} allows to +leave it unspecified which argument's type is incorrect. Again, +@code{SCM_ARGn} should be preferred over a raw zero constant. +@end deftypefn + +@node Continuation Barriers +@subsection Continuation Barriers + +The non-local flow of control caused by continuations might sometimes +not be wanted. You can use @code{with-continuation-barrier} to erect +fences that continuations can not pass. + +@deffn {Scheme Procedure} with-continuation-barrier proc +@deffnx {C Function} scm_with_continuation_barrier (proc) +Call @var{proc} and return its result. Do not allow the invocation of +continuations that would leave or enter the dynamic extent of the call +to @code{with-continuation-barrier}. Such an attempt causes an error +to be signaled. + +Throws (such as errors) that are not caught from within @var{proc} are +caught by @code{with-continuation-barrier}. In that case, a short +message is printed to the current error port and @code{#f} is returned. + +Thus, @code{with-continuation-barrier} returns exactly once. +@end deffn + +@deftypefn {C Function} {void *} scm_c_with_continuation_barrier (void *(*func) (void *), void *data) +Like @code{scm_with_continuation_barrier} but call @var{func} on +@var{data}. When an error is caught, @code{NULL} is returned. +@end deftypefn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-coverage.texi b/doc/ref/api-coverage.texi new file mode 100644 index 000000000..5081d343b --- /dev/null +++ b/doc/ref/api-coverage.texi @@ -0,0 +1,80 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2010, 2013 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + + +@node Code Coverage +@section Code Coverage Reports + +@cindex code coverage +@cindex coverage +When writing a test suite for a program or library, it is desirable to know what +part of the code is @dfn{covered} by the test suite. The @code{(system vm +coverage)} module provides tools to gather code coverage data and to present +them, as detailed below. + +@deffn {Scheme Procedure} with-code-coverage thunk +Run @var{thunk}, a zero-argument procedure, while instrumenting Guile's +virtual machine to collect code coverage data. Return code coverage +data and the values returned by @var{thunk}. +@end deffn + +@deffn {Scheme Procedure} coverage-data? obj +Return @code{#t} if @var{obj} is a @dfn{coverage data} object as returned by +@code{with-code-coverage}. +@end deffn + +@deffn {Scheme Procedure} coverage-data->lcov data port #:key modules +Traverse code coverage information @var{data}, as obtained with +@code{with-code-coverage}, and write coverage information to port in the +@code{.info} format used by @url{http://ltp.sourceforge.net/coverage/lcov.php, +LCOV}. The report will include all of @var{modules} (or, by default, all the +currently loaded modules) even if their code was not executed. + +The generated data can be fed to LCOV's @command{genhtml} command to produce an +HTML report, which aids coverage data visualization. +@end deffn + +Here's an example use: + +@example +(use-modules (system vm coverage) + (system vm vm)) + +(call-with-values (lambda () + (with-code-coverage + (lambda () + (do-something-tricky)))) + (lambda (data result) + (let ((port (open-output-file "lcov.info"))) + (coverage-data->lcov data port) + (close file)))) +@end example + +In addition, the module provides low-level procedures that would make it +possible to write other user interfaces to the coverage data. + +@deffn {Scheme Procedures} instrumented-source-files data +Return the list of ``instrumented'' source files, i.e., source files whose +code was loaded at the time @var{data} was collected. +@end deffn + +@deffn {Scheme Procedures} line-execution-counts data file +Return a list of line number/execution count pairs for @var{file}, or +@code{#f} if @var{file} is not among the files covered by @var{data}. This +includes lines with zero count. +@end deffn + +@deffn {Scheme Procedures} instrumented/executed-lines data file +Return the number of instrumented and the number of executed source lines +in @var{file} according to @var{data}. +@end deffn + +@deffn {Scheme Procedures} procedure-execution-count data proc +Return the number of times @var{proc}'s code was executed, according to +@var{data}, or @code{#f} if @var{proc} was not executed. When @var{proc} +is a closure, the number of times its code was executed is returned, not +the number of times this code associated with this particular closure was +executed. +@end deffn diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi new file mode 100644 index 000000000..5b9c5654e --- /dev/null +++ b/doc/ref/api-data.texi @@ -0,0 +1,10158 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2006-2017 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Data Types +@section Data Types + +Guile's data types form a powerful built-in library of representations +and functionality that you can apply to your problem domain. This +chapter surveys the data types built-in to Guile, from the simple to the +complex. + +@menu +* Booleans:: True/false values. +* Numbers:: Numerical data types. +* Characters:: Single characters. +* Character Sets:: Sets of characters. +* Strings:: Sequences of characters. +* Symbols:: Symbols. +* Keywords:: Self-quoting, customizable display keywords. +* Pairs:: Scheme's basic building block. +* Lists:: Special list functions supported by Guile. +* Vectors:: One-dimensional arrays of Scheme objects. +* Bit Vectors:: Vectors of bits. +* Bytevectors:: Sequences of bytes. +* Arrays:: Multidimensional matrices. +* VLists:: Vector-like lists. +* Record Overview:: Walking through the maze of record APIs. +* SRFI-9 Records:: The standard, recommended record API. +* Records:: Guile's historical record API. +* Structures:: Low-level record representation. +* Dictionary Types:: About dictionary types in general. +* Association Lists:: List-based dictionaries. +* VHashes:: VList-based dictionaries. +* Hash Tables:: Table-based dictionaries. +* Other Types:: Other sections describe data types too. +@end menu + + +@node Booleans +@subsection Booleans +@tpindex Booleans + +The two boolean values are @code{#t} for true and @code{#f} for false. +They can also be written as @code{#true} and @code{#false}, as per R7RS. + +Boolean values are returned by predicate procedures, such as the general +equality predicates @code{eq?}, @code{eqv?} and @code{equal?} +(@pxref{Equality}) and numerical and string comparison operators like +@code{string=?} (@pxref{String Comparison}) and @code{<=} +(@pxref{Comparison}). + +@lisp +(<= 3 8) +@result{} #t + +(<= 3 -3) +@result{} #f + +(equal? "house" "houses") +@result{} #f + +(eq? #f #f) +@result{} +#t +@end lisp + +In test condition contexts like @code{if} and @code{cond} +(@pxref{Conditionals}), where a group of subexpressions will be +evaluated only if a @var{condition} expression evaluates to ``true'', +``true'' means any value at all except @code{#f}. + +@lisp +(if #t "yes" "no") +@result{} "yes" + +(if 0 "yes" "no") +@result{} "yes" + +(if #f "yes" "no") +@result{} "no" +@end lisp + +A result of this asymmetry is that typical Scheme source code more often +uses @code{#f} explicitly than @code{#t}: @code{#f} is necessary to +represent an @code{if} or @code{cond} false value, whereas @code{#t} is +not necessary to represent an @code{if} or @code{cond} true value. + +It is important to note that @code{#f} is @strong{not} equivalent to any +other Scheme value. In particular, @code{#f} is not the same as the +number 0 (like in C and C++), and not the same as the ``empty list'' +(like in some Lisp dialects). + +In C, the two Scheme boolean values are available as the two constants +@code{SCM_BOOL_T} for @code{#t} and @code{SCM_BOOL_F} for @code{#f}. +Care must be taken with the false value @code{SCM_BOOL_F}: it is not +false when used in C conditionals. In order to test for it, use +@code{scm_is_false} or @code{scm_is_true}. + +@rnindex not +@deffn {Scheme Procedure} not x +@deffnx {C Function} scm_not (x) +Return @code{#t} if @var{x} is @code{#f}, else return @code{#f}. +@end deffn + +@rnindex boolean? +@deffn {Scheme Procedure} boolean? obj +@deffnx {C Function} scm_boolean_p (obj) +Return @code{#t} if @var{obj} is either @code{#t} or @code{#f}, else +return @code{#f}. +@end deffn + +@deftypevr {C Macro} SCM SCM_BOOL_T +The @code{SCM} representation of the Scheme object @code{#t}. +@end deftypevr + +@deftypevr {C Macro} SCM SCM_BOOL_F +The @code{SCM} representation of the Scheme object @code{#f}. +@end deftypevr + +@deftypefn {C Function} int scm_is_true (SCM obj) +Return @code{0} if @var{obj} is @code{#f}, else return @code{1}. +@end deftypefn + +@deftypefn {C Function} int scm_is_false (SCM obj) +Return @code{1} if @var{obj} is @code{#f}, else return @code{0}. +@end deftypefn + +@deftypefn {C Function} int scm_is_bool (SCM obj) +Return @code{1} if @var{obj} is either @code{#t} or @code{#f}, else +return @code{0}. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_bool (int val) +Return @code{#f} if @var{val} is @code{0}, else return @code{#t}. +@end deftypefn + +@deftypefn {C Function} int scm_to_bool (SCM val) +Return @code{1} if @var{val} is @code{SCM_BOOL_T}, return @code{0} +when @var{val} is @code{SCM_BOOL_F}, else signal a `wrong type' error. + +You should probably use @code{scm_is_true} instead of this function +when you just want to test a @code{SCM} value for trueness. +@end deftypefn + +@node Numbers +@subsection Numerical data types +@tpindex Numbers + +Guile supports a rich ``tower'' of numerical types --- integer, +rational, real and complex --- and provides an extensive set of +mathematical and scientific functions for operating on numerical +data. This section of the manual documents those types and functions. + +You may also find it illuminating to read R5RS's presentation of numbers +in Scheme, which is particularly clear and accessible: see +@ref{Numbers,,,r5rs,R5RS}. + +@menu +* Numerical Tower:: Scheme's numerical "tower". +* Integers:: Whole numbers. +* Reals and Rationals:: Real and rational numbers. +* Complex Numbers:: Complex numbers. +* Exactness:: Exactness and inexactness. +* Number Syntax:: Read syntax for numerical data. +* Integer Operations:: Operations on integer values. +* Comparison:: Comparison predicates. +* Conversion:: Converting numbers to and from strings. +* Complex:: Complex number operations. +* Arithmetic:: Arithmetic functions. +* Scientific:: Scientific functions. +* Bitwise Operations:: Logical AND, OR, NOT, and so on. +* Random:: Random number generation. +@end menu + + +@node Numerical Tower +@subsubsection Scheme's Numerical ``Tower'' +@rnindex number? + +Scheme's numerical ``tower'' consists of the following categories of +numbers: + +@table @dfn +@item integers +Whole numbers, positive or negative; e.g.@: --5, 0, 18. + +@item rationals +The set of numbers that can be expressed as @math{@var{p}/@var{q}} +where @var{p} and @var{q} are integers; e.g.@: @math{9/16} works, but +pi (an irrational number) doesn't. These include integers +(@math{@var{n}/1}). + +@item real numbers +The set of numbers that describes all possible positions along a +one-dimensional line. This includes rationals as well as irrational +numbers. + +@item complex numbers +The set of numbers that describes all possible positions in a two +dimensional space. This includes real as well as imaginary numbers +(@math{@var{a}+@var{b}i}, where @var{a} is the @dfn{real part}, +@var{b} is the @dfn{imaginary part}, and @math{i} is the square root of +@minus{}1.) +@end table + +It is called a tower because each category ``sits on'' the one that +follows it, in the sense that every integer is also a rational, every +rational is also real, and every real number is also a complex number +(but with zero imaginary part). + +In addition to the classification into integers, rationals, reals and +complex numbers, Scheme also distinguishes between whether a number is +represented exactly or not. For example, the result of +@m{2\sin(\pi/4),2*sin(pi/4)} is exactly @m{\sqrt{2},2^(1/2)}, but Guile +can represent neither @m{\pi/4,pi/4} nor @m{\sqrt{2},2^(1/2)} exactly. +Instead, it stores an inexact approximation, using the C type +@code{double}. + +Guile can represent exact rationals of any magnitude, inexact +rationals that fit into a C @code{double}, and inexact complex numbers +with @code{double} real and imaginary parts. + +The @code{number?} predicate may be applied to any Scheme value to +discover whether the value is any of the supported numerical types. + +@deffn {Scheme Procedure} number? obj +@deffnx {C Function} scm_number_p (obj) +Return @code{#t} if @var{obj} is any kind of number, else @code{#f}. +@end deffn + +For example: + +@lisp +(number? 3) +@result{} #t + +(number? "hello there!") +@result{} #f + +(define pi 3.141592654) +(number? pi) +@result{} #t +@end lisp + +@deftypefn {C Function} int scm_is_number (SCM obj) +This is equivalent to @code{scm_is_true (scm_number_p (obj))}. +@end deftypefn + +The next few subsections document each of Guile's numerical data types +in detail. + +@node Integers +@subsubsection Integers + +@tpindex Integer numbers + +@rnindex integer? + +Integers are whole numbers, that is numbers with no fractional part, +such as 2, 83, and @minus{}3789. + +Integers in Guile can be arbitrarily big, as shown by the following +example. + +@lisp +(define (factorial n) + (let loop ((n n) (product 1)) + (if (= n 0) + product + (loop (- n 1) (* product n))))) + +(factorial 3) +@result{} 6 + +(factorial 20) +@result{} 2432902008176640000 + +(- (factorial 45)) +@result{} -119622220865480194561963161495657715064383733760000000000 +@end lisp + +Readers whose background is in programming languages where integers are +limited by the need to fit into just 4 or 8 bytes of memory may find +this surprising, or suspect that Guile's representation of integers is +inefficient. In fact, Guile achieves a near optimal balance of +convenience and efficiency by using the host computer's native +representation of integers where possible, and a more general +representation where the required number does not fit in the native +form. Conversion between these two representations is automatic and +completely invisible to the Scheme level programmer. + +C has a host of different integer types, and Guile offers a host of +functions to convert between them and the @code{SCM} representation. +For example, a C @code{int} can be handled with @code{scm_to_int} and +@code{scm_from_int}. Guile also defines a few C integer types of its +own, to help with differences between systems. + +C integer types that are not covered can be handled with the generic +@code{scm_to_signed_integer} and @code{scm_from_signed_integer} for +signed types, or with @code{scm_to_unsigned_integer} and +@code{scm_from_unsigned_integer} for unsigned types. + +Scheme integers can be exact and inexact. For example, a number +written as @code{3.0} with an explicit decimal-point is inexact, but +it is also an integer. The functions @code{integer?} and +@code{scm_is_integer} report true for such a number, but the functions +@code{exact-integer?}, @code{scm_is_exact_integer}, +@code{scm_is_signed_integer}, and @code{scm_is_unsigned_integer} only +allow exact integers and thus report false. Likewise, the conversion +functions like @code{scm_to_signed_integer} only accept exact +integers. + +The motivation for this behavior is that the inexactness of a number +should not be lost silently. If you want to allow inexact integers, +you can explicitly insert a call to @code{inexact->exact} or to its C +equivalent @code{scm_inexact_to_exact}. (Only inexact integers will +be converted by this call into exact integers; inexact non-integers +will become exact fractions.) + +@deffn {Scheme Procedure} integer? x +@deffnx {C Function} scm_integer_p (x) +Return @code{#t} if @var{x} is an exact or inexact integer number, else +return @code{#f}. + +@lisp +(integer? 487) +@result{} #t + +(integer? 3.0) +@result{} #t + +(integer? -3.4) +@result{} #f + +(integer? +inf.0) +@result{} #f +@end lisp +@end deffn + +@deftypefn {C Function} int scm_is_integer (SCM x) +This is equivalent to @code{scm_is_true (scm_integer_p (x))}. +@end deftypefn + +@deffn {Scheme Procedure} exact-integer? x +@deffnx {C Function} scm_exact_integer_p (x) +Return @code{#t} if @var{x} is an exact integer number, else +return @code{#f}. + +@lisp +(exact-integer? 37) +@result{} #t + +(exact-integer? 3.0) +@result{} #f +@end lisp +@end deffn + +@deftypefn {C Function} int scm_is_exact_integer (SCM x) +This is equivalent to @code{scm_is_true (scm_exact_integer_p (x))}. +@end deftypefn + +@defvr {C Type} scm_t_int8 +@defvrx {C Type} scm_t_uint8 +@defvrx {C Type} scm_t_int16 +@defvrx {C Type} scm_t_uint16 +@defvrx {C Type} scm_t_int32 +@defvrx {C Type} scm_t_uint32 +@defvrx {C Type} scm_t_int64 +@defvrx {C Type} scm_t_uint64 +@defvrx {C Type} scm_t_intmax +@defvrx {C Type} scm_t_uintmax +The C types are equivalent to the corresponding ISO C types but are +defined on all platforms, with the exception of @code{scm_t_int64} and +@code{scm_t_uint64}, which are only defined when a 64-bit type is +available. For example, @code{scm_t_int8} is equivalent to +@code{int8_t}. + +You can regard these definitions as a stop-gap measure until all +platforms provide these types. If you know that all the platforms +that you are interested in already provide these types, it is better +to use them directly instead of the types provided by Guile. +@end defvr + +@deftypefn {C Function} int scm_is_signed_integer (SCM x, scm_t_intmax min, scm_t_intmax max) +@deftypefnx {C Function} int scm_is_unsigned_integer (SCM x, scm_t_uintmax min, scm_t_uintmax max) +Return @code{1} when @var{x} represents an exact integer that is +between @var{min} and @var{max}, inclusive. + +These functions can be used to check whether a @code{SCM} value will +fit into a given range, such as the range of a given C integer type. +If you just want to convert a @code{SCM} value to a given C integer +type, use one of the conversion functions directly. +@end deftypefn + +@deftypefn {C Function} scm_t_intmax scm_to_signed_integer (SCM x, scm_t_intmax min, scm_t_intmax max) +@deftypefnx {C Function} scm_t_uintmax scm_to_unsigned_integer (SCM x, scm_t_uintmax min, scm_t_uintmax max) +When @var{x} represents an exact integer that is between @var{min} and +@var{max} inclusive, return that integer. Else signal an error, +either a `wrong-type' error when @var{x} is not an exact integer, or +an `out-of-range' error when it doesn't fit the given range. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_signed_integer (scm_t_intmax x) +@deftypefnx {C Function} SCM scm_from_unsigned_integer (scm_t_uintmax x) +Return the @code{SCM} value that represents the integer @var{x}. This +function will always succeed and will always return an exact number. +@end deftypefn + +@deftypefn {C Function} char scm_to_char (SCM x) +@deftypefnx {C Function} {signed char} scm_to_schar (SCM x) +@deftypefnx {C Function} {unsigned char} scm_to_uchar (SCM x) +@deftypefnx {C Function} short scm_to_short (SCM x) +@deftypefnx {C Function} {unsigned short} scm_to_ushort (SCM x) +@deftypefnx {C Function} int scm_to_int (SCM x) +@deftypefnx {C Function} {unsigned int} scm_to_uint (SCM x) +@deftypefnx {C Function} long scm_to_long (SCM x) +@deftypefnx {C Function} {unsigned long} scm_to_ulong (SCM x) +@deftypefnx {C Function} {long long} scm_to_long_long (SCM x) +@deftypefnx {C Function} {unsigned long long} scm_to_ulong_long (SCM x) +@deftypefnx {C Function} size_t scm_to_size_t (SCM x) +@deftypefnx {C Function} ssize_t scm_to_ssize_t (SCM x) +@deftypefnx {C Function} scm_t_uintptr scm_to_uintptr_t (SCM x) +@deftypefnx {C Function} scm_t_ptrdiff scm_to_ptrdiff_t (SCM x) +@deftypefnx {C Function} scm_t_int8 scm_to_int8 (SCM x) +@deftypefnx {C Function} scm_t_uint8 scm_to_uint8 (SCM x) +@deftypefnx {C Function} scm_t_int16 scm_to_int16 (SCM x) +@deftypefnx {C Function} scm_t_uint16 scm_to_uint16 (SCM x) +@deftypefnx {C Function} scm_t_int32 scm_to_int32 (SCM x) +@deftypefnx {C Function} scm_t_uint32 scm_to_uint32 (SCM x) +@deftypefnx {C Function} scm_t_int64 scm_to_int64 (SCM x) +@deftypefnx {C Function} scm_t_uint64 scm_to_uint64 (SCM x) +@deftypefnx {C Function} scm_t_intmax scm_to_intmax (SCM x) +@deftypefnx {C Function} scm_t_uintmax scm_to_uintmax (SCM x) +@deftypefnx {C Function} scm_t_intptr scm_to_intptr_t (SCM x) +@deftypefnx {C Function} scm_t_uintptr scm_to_uintptr_t (SCM x) +When @var{x} represents an exact integer that fits into the indicated +C type, return that integer. Else signal an error, either a +`wrong-type' error when @var{x} is not an exact integer, or an +`out-of-range' error when it doesn't fit the given range. + +The functions @code{scm_to_long_long}, @code{scm_to_ulong_long}, +@code{scm_to_int64}, and @code{scm_to_uint64} are only available when +the corresponding types are. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_char (char x) +@deftypefnx {C Function} SCM scm_from_schar (signed char x) +@deftypefnx {C Function} SCM scm_from_uchar (unsigned char x) +@deftypefnx {C Function} SCM scm_from_short (short x) +@deftypefnx {C Function} SCM scm_from_ushort (unsigned short x) +@deftypefnx {C Function} SCM scm_from_int (int x) +@deftypefnx {C Function} SCM scm_from_uint (unsigned int x) +@deftypefnx {C Function} SCM scm_from_long (long x) +@deftypefnx {C Function} SCM scm_from_ulong (unsigned long x) +@deftypefnx {C Function} SCM scm_from_long_long (long long x) +@deftypefnx {C Function} SCM scm_from_ulong_long (unsigned long long x) +@deftypefnx {C Function} SCM scm_from_size_t (size_t x) +@deftypefnx {C Function} SCM scm_from_ssize_t (ssize_t x) +@deftypefnx {C Function} SCM scm_from_uintptr_t (uintptr_t x) +@deftypefnx {C Function} SCM scm_from_ptrdiff_t (scm_t_ptrdiff x) +@deftypefnx {C Function} SCM scm_from_int8 (scm_t_int8 x) +@deftypefnx {C Function} SCM scm_from_uint8 (scm_t_uint8 x) +@deftypefnx {C Function} SCM scm_from_int16 (scm_t_int16 x) +@deftypefnx {C Function} SCM scm_from_uint16 (scm_t_uint16 x) +@deftypefnx {C Function} SCM scm_from_int32 (scm_t_int32 x) +@deftypefnx {C Function} SCM scm_from_uint32 (scm_t_uint32 x) +@deftypefnx {C Function} SCM scm_from_int64 (scm_t_int64 x) +@deftypefnx {C Function} SCM scm_from_uint64 (scm_t_uint64 x) +@deftypefnx {C Function} SCM scm_from_intmax (scm_t_intmax x) +@deftypefnx {C Function} SCM scm_from_uintmax (scm_t_uintmax x) +@deftypefnx {C Function} SCM scm_from_intptr_t (scm_t_intptr x) +@deftypefnx {C Function} SCM scm_from_uintptr_t (scm_t_uintptr x) +Return the @code{SCM} value that represents the integer @var{x}. +These functions will always succeed and will always return an exact +number. +@end deftypefn + +@deftypefn {C Function} void scm_to_mpz (SCM val, mpz_t rop) +Assign @var{val} to the multiple precision integer @var{rop}. +@var{val} must be an exact integer, otherwise an error will be +signalled. @var{rop} must have been initialized with @code{mpz_init} +before this function is called. When @var{rop} is no longer needed +the occupied space must be freed with @code{mpz_clear}. +@xref{Initializing Integers,,, gmp, GNU MP Manual}, for details. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_mpz (mpz_t val) +Return the @code{SCM} value that represents @var{val}. +@end deftypefn + +@node Reals and Rationals +@subsubsection Real and Rational Numbers +@tpindex Real numbers +@tpindex Rational numbers + +@rnindex real? +@rnindex rational? + +Mathematically, the real numbers are the set of numbers that describe +all possible points along a continuous, infinite, one-dimensional line. +The rational numbers are the set of all numbers that can be written as +fractions @var{p}/@var{q}, where @var{p} and @var{q} are integers. +All rational numbers are also real, but there are real numbers that +are not rational, for example @m{\sqrt{2}, the square root of 2}, and +@m{\pi,pi}. + +Guile can represent both exact and inexact rational numbers, but it +cannot represent precise finite irrational numbers. Exact rationals are +represented by storing the numerator and denominator as two exact +integers. Inexact rationals are stored as floating point numbers using +the C type @code{double}. + +Exact rationals are written as a fraction of integers. There must be +no whitespace around the slash: + +@lisp +1/2 +-22/7 +@end lisp + +Even though the actual encoding of inexact rationals is in binary, it +may be helpful to think of it as a decimal number with a limited +number of significant figures and a decimal point somewhere, since +this corresponds to the standard notation for non-whole numbers. For +example: + +@lisp +0.34 +-0.00000142857931198 +-5648394822220000000000.0 +4.0 +@end lisp + +The limited precision of Guile's encoding means that any finite ``real'' +number in Guile can be written in a rational form, by multiplying and +then dividing by sufficient powers of 10 (or in fact, 2). For example, +@samp{-0.00000142857931198} is the same as @minus{}142857931198 divided +by 100000000000000000. In Guile's current incarnation, therefore, the +@code{rational?} and @code{real?} predicates are equivalent for finite +numbers. + + +Dividing by an exact zero leads to a error message, as one might expect. +However, dividing by an inexact zero does not produce an error. +Instead, the result of the division is either plus or minus infinity, +depending on the sign of the divided number and the sign of the zero +divisor (some platforms support signed zeroes @samp{-0.0} and +@samp{+0.0}; @samp{0.0} is the same as @samp{+0.0}). + +Dividing zero by an inexact zero yields a @acronym{NaN} (`not a number') +value, although they are actually considered numbers by Scheme. +Attempts to compare a @acronym{NaN} value with any number (including +itself) using @code{=}, @code{<}, @code{>}, @code{<=} or @code{>=} +always returns @code{#f}. Although a @acronym{NaN} value is not +@code{=} to itself, it is both @code{eqv?} and @code{equal?} to itself +and other @acronym{NaN} values. However, the preferred way to test for +them is by using @code{nan?}. + +The real @acronym{NaN} values and infinities are written @samp{+nan.0}, +@samp{+inf.0} and @samp{-inf.0}. This syntax is also recognized by +@code{read} as an extension to the usual Scheme syntax. These special +values are considered by Scheme to be inexact real numbers but not +rational. Note that non-real complex numbers may also contain +infinities or @acronym{NaN} values in their real or imaginary parts. To +test a real number to see if it is infinite, a @acronym{NaN} value, or +neither, use @code{inf?}, @code{nan?}, or @code{finite?}, respectively. +Every real number in Scheme belongs to precisely one of those three +classes. + +On platforms that follow @acronym{IEEE} 754 for their floating point +arithmetic, the @samp{+inf.0}, @samp{-inf.0}, and @samp{+nan.0} values +are implemented using the corresponding @acronym{IEEE} 754 values. +They behave in arithmetic operations like @acronym{IEEE} 754 describes +it, i.e., @code{(= +nan.0 +nan.0)} @result{} @code{#f}. + +@deffn {Scheme Procedure} real? obj +@deffnx {C Function} scm_real_p (obj) +Return @code{#t} if @var{obj} is a real number, else @code{#f}. Note +that the sets of integer and rational values form subsets of the set +of real numbers, so the predicate will also be fulfilled if @var{obj} +is an integer number or a rational number. +@end deffn + +@deffn {Scheme Procedure} rational? x +@deffnx {C Function} scm_rational_p (x) +Return @code{#t} if @var{x} is a rational number, @code{#f} otherwise. +Note that the set of integer values forms a subset of the set of +rational numbers, i.e.@: the predicate will also be fulfilled if +@var{x} is an integer number. +@end deffn + +@deffn {Scheme Procedure} rationalize x eps +@deffnx {C Function} scm_rationalize (x, eps) +Returns the @emph{simplest} rational number differing +from @var{x} by no more than @var{eps}. + +As required by @acronym{R5RS}, @code{rationalize} only returns an +exact result when both its arguments are exact. Thus, you might need +to use @code{inexact->exact} on the arguments. + +@lisp +(rationalize (inexact->exact 1.2) 1/100) +@result{} 6/5 +@end lisp + +@end deffn + +@deffn {Scheme Procedure} inf? x +@deffnx {C Function} scm_inf_p (x) +Return @code{#t} if the real number @var{x} is @samp{+inf.0} or +@samp{-inf.0}. Otherwise return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} nan? x +@deffnx {C Function} scm_nan_p (x) +Return @code{#t} if the real number @var{x} is @samp{+nan.0}, or +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} finite? x +@deffnx {C Function} scm_finite_p (x) +Return @code{#t} if the real number @var{x} is neither infinite nor a +NaN, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} nan +@deffnx {C Function} scm_nan () +Return @samp{+nan.0}, a @acronym{NaN} value. +@end deffn + +@deffn {Scheme Procedure} inf +@deffnx {C Function} scm_inf () +Return @samp{+inf.0}, positive infinity. +@end deffn + +@deffn {Scheme Procedure} numerator x +@deffnx {C Function} scm_numerator (x) +Return the numerator of the rational number @var{x}. +@end deffn + +@deffn {Scheme Procedure} denominator x +@deffnx {C Function} scm_denominator (x) +Return the denominator of the rational number @var{x}. +@end deffn + +@deftypefn {C Function} int scm_is_real (SCM val) +@deftypefnx {C Function} int scm_is_rational (SCM val) +Equivalent to @code{scm_is_true (scm_real_p (val))} and +@code{scm_is_true (scm_rational_p (val))}, respectively. +@end deftypefn + +@deftypefn {C Function} double scm_to_double (SCM val) +Returns the number closest to @var{val} that is representable as a +@code{double}. Returns infinity for a @var{val} that is too large in +magnitude. The argument @var{val} must be a real number. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_double (double val) +Return the @code{SCM} value that represents @var{val}. The returned +value is inexact according to the predicate @code{inexact?}, but it +will be exactly equal to @var{val}. +@end deftypefn + +@node Complex Numbers +@subsubsection Complex Numbers +@tpindex Complex numbers + +@rnindex complex? + +Complex numbers are the set of numbers that describe all possible points +in a two-dimensional space. The two coordinates of a particular point +in this space are known as the @dfn{real} and @dfn{imaginary} parts of +the complex number that describes that point. + +In Guile, complex numbers are written in rectangular form as the sum of +their real and imaginary parts, using the symbol @code{i} to indicate +the imaginary part. + +@lisp +3+4i +@result{} +3.0+4.0i + +(* 3-8i 2.3+0.3i) +@result{} +9.3-17.5i +@end lisp + +@cindex polar form +@noindent +Polar form can also be used, with an @samp{@@} between magnitude and +angle, + +@lisp +1@@3.141592 @result{} -1.0 (approx) +-1@@1.57079 @result{} 0.0-1.0i (approx) +@end lisp + +Guile represents a complex number as a pair of inexact reals, so the +real and imaginary parts of a complex number have the same properties of +inexactness and limited precision as single inexact real numbers. + +Note that each part of a complex number may contain any inexact real +value, including the special values @samp{+nan.0}, @samp{+inf.0} and +@samp{-inf.0}, as well as either of the signed zeroes @samp{0.0} or +@samp{-0.0}. + + +@deffn {Scheme Procedure} complex? z +@deffnx {C Function} scm_complex_p (z) +Return @code{#t} if @var{z} is a complex number, @code{#f} +otherwise. Note that the sets of real, rational and integer +values form subsets of the set of complex numbers, i.e.@: the +predicate will also be fulfilled if @var{z} is a real, +rational or integer number. +@end deffn + +@deftypefn {C Function} int scm_is_complex (SCM val) +Equivalent to @code{scm_is_true (scm_complex_p (val))}. +@end deftypefn + +@node Exactness +@subsubsection Exact and Inexact Numbers +@tpindex Exact numbers +@tpindex Inexact numbers + +@rnindex exact? +@rnindex inexact? +@rnindex exact->inexact +@rnindex inexact->exact + +R5RS requires that, with few exceptions, a calculation involving inexact +numbers always produces an inexact result. To meet this requirement, +Guile distinguishes between an exact integer value such as @samp{5} and +the corresponding inexact integer value which, to the limited precision +available, has no fractional part, and is printed as @samp{5.0}. Guile +will only convert the latter value to the former when forced to do so by +an invocation of the @code{inexact->exact} procedure. + +The only exception to the above requirement is when the values of the +inexact numbers do not affect the result. For example @code{(expt n 0)} +is @samp{1} for any value of @code{n}, therefore @code{(expt 5.0 0)} is +permitted to return an exact @samp{1}. + +@deffn {Scheme Procedure} exact? z +@deffnx {C Function} scm_exact_p (z) +Return @code{#t} if the number @var{z} is exact, @code{#f} +otherwise. + +@lisp +(exact? 2) +@result{} #t + +(exact? 0.5) +@result{} #f + +(exact? (/ 2)) +@result{} #t +@end lisp + +@end deffn + +@deftypefn {C Function} int scm_is_exact (SCM z) +Return a @code{1} if the number @var{z} is exact, and @code{0} +otherwise. This is equivalent to @code{scm_is_true (scm_exact_p (z))}. + +An alternate approch to testing the exactness of a number is to +use @code{scm_is_signed_integer} or @code{scm_is_unsigned_integer}. +@end deftypefn + +@deffn {Scheme Procedure} inexact? z +@deffnx {C Function} scm_inexact_p (z) +Return @code{#t} if the number @var{z} is inexact, @code{#f} +else. +@end deffn + +@deftypefn {C Function} int scm_is_inexact (SCM z) +Return a @code{1} if the number @var{z} is inexact, and @code{0} +otherwise. This is equivalent to @code{scm_is_true (scm_inexact_p (z))}. +@end deftypefn + +@deffn {Scheme Procedure} inexact->exact z +@deffnx {C Function} scm_inexact_to_exact (z) +Return an exact number that is numerically closest to @var{z}, when +there is one. For inexact rationals, Guile returns the exact rational +that is numerically equal to the inexact rational. Inexact complex +numbers with a non-zero imaginary part can not be made exact. + +@lisp +(inexact->exact 0.5) +@result{} 1/2 +@end lisp + +The following happens because 12/10 is not exactly representable as a +@code{double} (on most platforms). However, when reading a decimal +number that has been marked exact with the ``#e'' prefix, Guile is +able to represent it correctly. + +@lisp +(inexact->exact 1.2) +@result{} 5404319552844595/4503599627370496 + +#e1.2 +@result{} 6/5 +@end lisp + +@end deffn + +@c begin (texi-doc-string "guile" "exact->inexact") +@deffn {Scheme Procedure} exact->inexact z +@deffnx {C Function} scm_exact_to_inexact (z) +Convert the number @var{z} to its inexact representation. +@end deffn + + +@node Number Syntax +@subsubsection Read Syntax for Numerical Data + +The read syntax for integers is a string of digits, optionally +preceded by a minus or plus character, a code indicating the +base in which the integer is encoded, and a code indicating whether +the number is exact or inexact. The supported base codes are: + +@table @code +@item #b +@itemx #B +the integer is written in binary (base 2) + +@item #o +@itemx #O +the integer is written in octal (base 8) + +@item #d +@itemx #D +the integer is written in decimal (base 10) + +@item #x +@itemx #X +the integer is written in hexadecimal (base 16) +@end table + +If the base code is omitted, the integer is assumed to be decimal. The +following examples show how these base codes are used. + +@lisp +-13 +@result{} -13 + +#d-13 +@result{} -13 + +#x-13 +@result{} -19 + +#b+1101 +@result{} 13 + +#o377 +@result{} 255 +@end lisp + +The codes for indicating exactness (which can, incidentally, be applied +to all numerical values) are: + +@table @code +@item #e +@itemx #E +the number is exact + +@item #i +@itemx #I +the number is inexact. +@end table + +If the exactness indicator is omitted, the number is exact unless it +contains a radix point. Since Guile can not represent exact complex +numbers, an error is signalled when asking for them. + +@lisp +(exact? 1.2) +@result{} #f + +(exact? #e1.2) +@result{} #t + +(exact? #e+1i) +ERROR: Wrong type argument +@end lisp + +Guile also understands the syntax @samp{+inf.0} and @samp{-inf.0} for +plus and minus infinity, respectively. The value must be written +exactly as shown, that is, they always must have a sign and exactly +one zero digit after the decimal point. It also understands +@samp{+nan.0} and @samp{-nan.0} for the special `not-a-number' value. +The sign is ignored for `not-a-number' and the value is always printed +as @samp{+nan.0}. + +@node Integer Operations +@subsubsection Operations on Integer Values +@rnindex odd? +@rnindex even? +@rnindex quotient +@rnindex remainder +@rnindex modulo +@rnindex gcd +@rnindex lcm + +@deffn {Scheme Procedure} odd? n +@deffnx {C Function} scm_odd_p (n) +Return @code{#t} if @var{n} is an odd number, @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} even? n +@deffnx {C Function} scm_even_p (n) +Return @code{#t} if @var{n} is an even number, @code{#f} +otherwise. +@end deffn + +@c begin (texi-doc-string "guile" "quotient") +@c begin (texi-doc-string "guile" "remainder") +@deffn {Scheme Procedure} quotient n d +@deffnx {Scheme Procedure} remainder n d +@deffnx {C Function} scm_quotient (n, d) +@deffnx {C Function} scm_remainder (n, d) +Return the quotient or remainder from @var{n} divided by @var{d}. The +quotient is rounded towards zero, and the remainder will have the same +sign as @var{n}. In all cases quotient and remainder satisfy +@math{@var{n} = @var{q}*@var{d} + @var{r}}. + +@lisp +(remainder 13 4) @result{} 1 +(remainder -13 4) @result{} -1 +@end lisp + +See also @code{truncate-quotient}, @code{truncate-remainder} and +related operations in @ref{Arithmetic}. +@end deffn + +@c begin (texi-doc-string "guile" "modulo") +@deffn {Scheme Procedure} modulo n d +@deffnx {C Function} scm_modulo (n, d) +Return the remainder from @var{n} divided by @var{d}, with the same +sign as @var{d}. + +@lisp +(modulo 13 4) @result{} 1 +(modulo -13 4) @result{} 3 +(modulo 13 -4) @result{} -3 +(modulo -13 -4) @result{} -1 +@end lisp + +See also @code{floor-quotient}, @code{floor-remainder} and +related operations in @ref{Arithmetic}. +@end deffn + +@c begin (texi-doc-string "guile" "gcd") +@deffn {Scheme Procedure} gcd x@dots{} +@deffnx {C Function} scm_gcd (x, y) +Return the greatest common divisor of all arguments. +If called without arguments, 0 is returned. + +The C function @code{scm_gcd} always takes two arguments, while the +Scheme function can take an arbitrary number. +@end deffn + +@c begin (texi-doc-string "guile" "lcm") +@deffn {Scheme Procedure} lcm x@dots{} +@deffnx {C Function} scm_lcm (x, y) +Return the least common multiple of the arguments. +If called without arguments, 1 is returned. + +The C function @code{scm_lcm} always takes two arguments, while the +Scheme function can take an arbitrary number. +@end deffn + +@deffn {Scheme Procedure} modulo-expt n k m +@deffnx {C Function} scm_modulo_expt (n, k, m) +Return @var{n} raised to the integer exponent +@var{k}, modulo @var{m}. + +@lisp +(modulo-expt 2 3 5) + @result{} 3 +@end lisp +@end deffn + +@deftypefn {Scheme Procedure} {} exact-integer-sqrt @var{k} +@deftypefnx {C Function} void scm_exact_integer_sqrt (SCM @var{k}, SCM *@var{s}, SCM *@var{r}) +Return two exact non-negative integers @var{s} and @var{r} +such that @math{@var{k} = @var{s}^2 + @var{r}} and +@math{@var{s}^2 <= @var{k} < (@var{s} + 1)^2}. +An error is raised if @var{k} is not an exact non-negative integer. + +@lisp +(exact-integer-sqrt 10) @result{} 3 and 1 +@end lisp +@end deftypefn + +@node Comparison +@subsubsection Comparison Predicates +@rnindex zero? +@rnindex positive? +@rnindex negative? + +The C comparison functions below always takes two arguments, while the +Scheme functions can take an arbitrary number. Also keep in mind that +the C functions return one of the Scheme boolean values +@code{SCM_BOOL_T} or @code{SCM_BOOL_F} which are both true as far as C +is concerned. Thus, always write @code{scm_is_true (scm_num_eq_p (x, +y))} when testing the two Scheme numbers @code{x} and @code{y} for +equality, for example. + +@c begin (texi-doc-string "guile" "=") +@deffn {Scheme Procedure} = +@deffnx {C Function} scm_num_eq_p (x, y) +Return @code{#t} if all parameters are numerically equal. +@end deffn + +@c begin (texi-doc-string "guile" "<") +@deffn {Scheme Procedure} < +@deffnx {C Function} scm_less_p (x, y) +Return @code{#t} if the list of parameters is monotonically +increasing. +@end deffn + +@c begin (texi-doc-string "guile" ">") +@deffn {Scheme Procedure} > +@deffnx {C Function} scm_gr_p (x, y) +Return @code{#t} if the list of parameters is monotonically +decreasing. +@end deffn + +@c begin (texi-doc-string "guile" "<=") +@deffn {Scheme Procedure} <= +@deffnx {C Function} scm_leq_p (x, y) +Return @code{#t} if the list of parameters is monotonically +non-decreasing. +@end deffn + +@c begin (texi-doc-string "guile" ">=") +@deffn {Scheme Procedure} >= +@deffnx {C Function} scm_geq_p (x, y) +Return @code{#t} if the list of parameters is monotonically +non-increasing. +@end deffn + +@c begin (texi-doc-string "guile" "zero?") +@deffn {Scheme Procedure} zero? z +@deffnx {C Function} scm_zero_p (z) +Return @code{#t} if @var{z} is an exact or inexact number equal to +zero. +@end deffn + +@c begin (texi-doc-string "guile" "positive?") +@deffn {Scheme Procedure} positive? x +@deffnx {C Function} scm_positive_p (x) +Return @code{#t} if @var{x} is an exact or inexact number greater than +zero. +@end deffn + +@c begin (texi-doc-string "guile" "negative?") +@deffn {Scheme Procedure} negative? x +@deffnx {C Function} scm_negative_p (x) +Return @code{#t} if @var{x} is an exact or inexact number less than +zero. +@end deffn + + +@node Conversion +@subsubsection Converting Numbers To and From Strings +@rnindex number->string +@rnindex string->number + +The following procedures read and write numbers according to their +external representation as defined by R5RS (@pxref{Lexical structure, +R5RS Lexical Structure,, r5rs, The Revised^5 Report on the Algorithmic +Language Scheme}). @xref{Number Input and Output, the @code{(ice-9 +i18n)} module}, for locale-dependent number parsing. + +@deffn {Scheme Procedure} number->string n [radix] +@deffnx {C Function} scm_number_to_string (n, radix) +Return a string holding the external representation of the +number @var{n} in the given @var{radix}. If @var{n} is +inexact, a radix of 10 will be used. +@end deffn + +@deffn {Scheme Procedure} string->number string [radix] +@deffnx {C Function} scm_string_to_number (string, radix) +Return a number of the maximally precise representation +expressed by the given @var{string}. @var{radix} must be an +exact integer, either 2, 8, 10, or 16. If supplied, @var{radix} +is a default radix that may be overridden by an explicit radix +prefix in @var{string} (e.g.@: "#o177"). If @var{radix} is not +supplied, then the default radix is 10. If string is not a +syntactically valid notation for a number, then +@code{string->number} returns @code{#f}. +@end deffn + +@deftypefn {C Function} SCM scm_c_locale_stringn_to_number (const char *string, size_t len, unsigned radix) +As per @code{string->number} above, but taking a C string, as pointer +and length. The string characters should be in the current locale +encoding (@code{locale} in the name refers only to that, there's no +locale-dependent parsing). +@end deftypefn + + +@node Complex +@subsubsection Complex Number Operations +@rnindex make-rectangular +@rnindex make-polar +@rnindex real-part +@rnindex imag-part +@rnindex magnitude +@rnindex angle + +@deffn {Scheme Procedure} make-rectangular real_part imaginary_part +@deffnx {C Function} scm_make_rectangular (real_part, imaginary_part) +Return a complex number constructed of the given @var{real-part} and @var{imaginary-part} parts. +@end deffn + +@deffn {Scheme Procedure} make-polar mag ang +@deffnx {C Function} scm_make_polar (mag, ang) +@cindex polar form +Return the complex number @var{mag} * e^(i * @var{ang}). +@end deffn + +@c begin (texi-doc-string "guile" "real-part") +@deffn {Scheme Procedure} real-part z +@deffnx {C Function} scm_real_part (z) +Return the real part of the number @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "imag-part") +@deffn {Scheme Procedure} imag-part z +@deffnx {C Function} scm_imag_part (z) +Return the imaginary part of the number @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "magnitude") +@deffn {Scheme Procedure} magnitude z +@deffnx {C Function} scm_magnitude (z) +Return the magnitude of the number @var{z}. This is the same as +@code{abs} for real arguments, but also allows complex numbers. +@end deffn + +@c begin (texi-doc-string "guile" "angle") +@deffn {Scheme Procedure} angle z +@deffnx {C Function} scm_angle (z) +Return the angle of the complex number @var{z}. +@end deffn + +@deftypefn {C Function} SCM scm_c_make_rectangular (double re, double im) +@deftypefnx {C Function} SCM scm_c_make_polar (double x, double y) +Like @code{scm_make_rectangular} or @code{scm_make_polar}, +respectively, but these functions take @code{double}s as their +arguments. +@end deftypefn + +@deftypefn {C Function} double scm_c_real_part (z) +@deftypefnx {C Function} double scm_c_imag_part (z) +Returns the real or imaginary part of @var{z} as a @code{double}. +@end deftypefn + +@deftypefn {C Function} double scm_c_magnitude (z) +@deftypefnx {C Function} double scm_c_angle (z) +Returns the magnitude or angle of @var{z} as a @code{double}. +@end deftypefn + + +@node Arithmetic +@subsubsection Arithmetic Functions +@rnindex max +@rnindex min +@rnindex + +@rnindex * +@rnindex - +@rnindex / +@findex 1+ +@findex 1- +@rnindex abs +@rnindex floor +@rnindex ceiling +@rnindex truncate +@rnindex round +@rnindex euclidean/ +@rnindex euclidean-quotient +@rnindex euclidean-remainder +@rnindex floor/ +@rnindex floor-quotient +@rnindex floor-remainder +@rnindex ceiling/ +@rnindex ceiling-quotient +@rnindex ceiling-remainder +@rnindex truncate/ +@rnindex truncate-quotient +@rnindex truncate-remainder +@rnindex centered/ +@rnindex centered-quotient +@rnindex centered-remainder +@rnindex round/ +@rnindex round-quotient +@rnindex round-remainder + +The C arithmetic functions below always takes two arguments, while the +Scheme functions can take an arbitrary number. When you need to +invoke them with just one argument, for example to compute the +equivalent of @code{(- x)}, pass @code{SCM_UNDEFINED} as the second +one: @code{scm_difference (x, SCM_UNDEFINED)}. + +@c begin (texi-doc-string "guile" "+") +@deffn {Scheme Procedure} + z1 @dots{} +@deffnx {C Function} scm_sum (z1, z2) +Return the sum of all parameter values. Return 0 if called without any +parameters. +@end deffn + +@c begin (texi-doc-string "guile" "-") +@deffn {Scheme Procedure} - z1 z2 @dots{} +@deffnx {C Function} scm_difference (z1, z2) +If called with one argument @var{z1}, -@var{z1} is returned. Otherwise +the sum of all but the first argument are subtracted from the first +argument. +@end deffn + +@c begin (texi-doc-string "guile" "*") +@deffn {Scheme Procedure} * z1 @dots{} +@deffnx {C Function} scm_product (z1, z2) +Return the product of all arguments. If called without arguments, 1 is +returned. +@end deffn + +@c begin (texi-doc-string "guile" "/") +@deffn {Scheme Procedure} / z1 z2 @dots{} +@deffnx {C Function} scm_divide (z1, z2) +Divide the first argument by the product of the remaining arguments. If +called with one argument @var{z1}, 1/@var{z1} is returned. +@end deffn + +@deffn {Scheme Procedure} 1+ z +@deffnx {C Function} scm_oneplus (z) +Return @math{@var{z} + 1}. +@end deffn + +@deffn {Scheme Procedure} 1- z +@deffnx {C function} scm_oneminus (z) +Return @math{@var{z} - 1}. +@end deffn + +@c begin (texi-doc-string "guile" "abs") +@deffn {Scheme Procedure} abs x +@deffnx {C Function} scm_abs (x) +Return the absolute value of @var{x}. + +@var{x} must be a number with zero imaginary part. To calculate the +magnitude of a complex number, use @code{magnitude} instead. +@end deffn + +@c begin (texi-doc-string "guile" "max") +@deffn {Scheme Procedure} max x1 x2 @dots{} +@deffnx {C Function} scm_max (x1, x2) +Return the maximum of all parameter values. +@end deffn + +@c begin (texi-doc-string "guile" "min") +@deffn {Scheme Procedure} min x1 x2 @dots{} +@deffnx {C Function} scm_min (x1, x2) +Return the minimum of all parameter values. +@end deffn + +@c begin (texi-doc-string "guile" "truncate") +@deffn {Scheme Procedure} truncate x +@deffnx {C Function} scm_truncate_number (x) +Round the inexact number @var{x} towards zero. +@end deffn + +@c begin (texi-doc-string "guile" "round") +@deffn {Scheme Procedure} round x +@deffnx {C Function} scm_round_number (x) +Round the inexact number @var{x} to the nearest integer. When exactly +halfway between two integers, round to the even one. +@end deffn + +@c begin (texi-doc-string "guile" "floor") +@deffn {Scheme Procedure} floor x +@deffnx {C Function} scm_floor (x) +Round the number @var{x} towards minus infinity. +@end deffn + +@c begin (texi-doc-string "guile" "ceiling") +@deffn {Scheme Procedure} ceiling x +@deffnx {C Function} scm_ceiling (x) +Round the number @var{x} towards infinity. +@end deffn + +@deftypefn {C Function} double scm_c_truncate (double x) +@deftypefnx {C Function} double scm_c_round (double x) +Like @code{scm_truncate_number} or @code{scm_round_number}, +respectively, but these functions take and return @code{double} +values. +@end deftypefn + +@deftypefn {Scheme Procedure} {} euclidean/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} euclidean-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} euclidean-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_euclidean_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_euclidean_quotient (SCM @var{x}, SCM @var{y}) +@deftypefnx {C Function} SCM scm_euclidean_remainder (SCM @var{x}, SCM @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{euclidean-quotient} returns the +integer @var{q} and @code{euclidean-remainder} returns the real number +@var{r} such that @math{@var{x} = @var{q}*@var{y} + @var{r}} and +@math{0 <= @var{r} < |@var{y}|}. @code{euclidean/} returns both @var{q} and +@var{r}, and is more efficient than computing each separately. Note +that when @math{@var{y} > 0}, @code{euclidean-quotient} returns +@math{floor(@var{x}/@var{y})}, otherwise it returns +@math{ceiling(@var{x}/@var{y})}. + +Note that these operators are equivalent to the R6RS operators +@code{div}, @code{mod}, and @code{div-and-mod}. + +@lisp +(euclidean-quotient 123 10) @result{} 12 +(euclidean-remainder 123 10) @result{} 3 +(euclidean/ 123 10) @result{} 12 and 3 +(euclidean/ 123 -10) @result{} -12 and 3 +(euclidean/ -123 10) @result{} -13 and 7 +(euclidean/ -123 -10) @result{} 13 and 7 +(euclidean/ -123.2 -63.5) @result{} 2.0 and 3.8 +(euclidean/ 16/3 -10/7) @result{} -3 and 22/21 +@end lisp +@end deftypefn + +@deftypefn {Scheme Procedure} {} floor/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} floor-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} floor-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_floor_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_floor_quotient (@var{x}, @var{y}) +@deftypefnx {C Function} SCM scm_floor_remainder (@var{x}, @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{floor-quotient} returns the +integer @var{q} and @code{floor-remainder} returns the real number +@var{r} such that @math{@var{q} = floor(@var{x}/@var{y})} and +@math{@var{x} = @var{q}*@var{y} + @var{r}}. @code{floor/} returns +both @var{q} and @var{r}, and is more efficient than computing each +separately. Note that @var{r}, if non-zero, will have the same sign +as @var{y}. + +When @var{x} and @var{y} are integers, @code{floor-remainder} is +equivalent to the R5RS integer-only operator @code{modulo}. + +@lisp +(floor-quotient 123 10) @result{} 12 +(floor-remainder 123 10) @result{} 3 +(floor/ 123 10) @result{} 12 and 3 +(floor/ 123 -10) @result{} -13 and -7 +(floor/ -123 10) @result{} -13 and 7 +(floor/ -123 -10) @result{} 12 and -3 +(floor/ -123.2 -63.5) @result{} 1.0 and -59.7 +(floor/ 16/3 -10/7) @result{} -4 and -8/21 +@end lisp +@end deftypefn + +@deftypefn {Scheme Procedure} {} ceiling/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} ceiling-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} ceiling-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_ceiling_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_ceiling_quotient (@var{x}, @var{y}) +@deftypefnx {C Function} SCM scm_ceiling_remainder (@var{x}, @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{ceiling-quotient} returns the +integer @var{q} and @code{ceiling-remainder} returns the real number +@var{r} such that @math{@var{q} = ceiling(@var{x}/@var{y})} and +@math{@var{x} = @var{q}*@var{y} + @var{r}}. @code{ceiling/} returns +both @var{q} and @var{r}, and is more efficient than computing each +separately. Note that @var{r}, if non-zero, will have the opposite sign +of @var{y}. + +@lisp +(ceiling-quotient 123 10) @result{} 13 +(ceiling-remainder 123 10) @result{} -7 +(ceiling/ 123 10) @result{} 13 and -7 +(ceiling/ 123 -10) @result{} -12 and 3 +(ceiling/ -123 10) @result{} -12 and -3 +(ceiling/ -123 -10) @result{} 13 and 7 +(ceiling/ -123.2 -63.5) @result{} 2.0 and 3.8 +(ceiling/ 16/3 -10/7) @result{} -3 and 22/21 +@end lisp +@end deftypefn + +@deftypefn {Scheme Procedure} {} truncate/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} truncate-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} truncate-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_truncate_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_truncate_quotient (@var{x}, @var{y}) +@deftypefnx {C Function} SCM scm_truncate_remainder (@var{x}, @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{truncate-quotient} returns the +integer @var{q} and @code{truncate-remainder} returns the real number +@var{r} such that @var{q} is @math{@var{x}/@var{y}} rounded toward zero, +and @math{@var{x} = @var{q}*@var{y} + @var{r}}. @code{truncate/} returns +both @var{q} and @var{r}, and is more efficient than computing each +separately. Note that @var{r}, if non-zero, will have the same sign +as @var{x}. + +When @var{x} and @var{y} are integers, these operators are +equivalent to the R5RS integer-only operators @code{quotient} and +@code{remainder}. + +@lisp +(truncate-quotient 123 10) @result{} 12 +(truncate-remainder 123 10) @result{} 3 +(truncate/ 123 10) @result{} 12 and 3 +(truncate/ 123 -10) @result{} -12 and 3 +(truncate/ -123 10) @result{} -12 and -3 +(truncate/ -123 -10) @result{} 12 and -3 +(truncate/ -123.2 -63.5) @result{} 1.0 and -59.7 +(truncate/ 16/3 -10/7) @result{} -3 and 22/21 +@end lisp +@end deftypefn + +@deftypefn {Scheme Procedure} {} centered/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} centered-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} centered-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_centered_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_centered_quotient (SCM @var{x}, SCM @var{y}) +@deftypefnx {C Function} SCM scm_centered_remainder (SCM @var{x}, SCM @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{centered-quotient} returns the +integer @var{q} and @code{centered-remainder} returns the real number +@var{r} such that @math{@var{x} = @var{q}*@var{y} + @var{r}} and +@math{-|@var{y}/2| <= @var{r} < |@var{y}/2|}. @code{centered/} +returns both @var{q} and @var{r}, and is more efficient than computing +each separately. + +Note that @code{centered-quotient} returns @math{@var{x}/@var{y}} +rounded to the nearest integer. When @math{@var{x}/@var{y}} lies +exactly half-way between two integers, the tie is broken according to +the sign of @var{y}. If @math{@var{y} > 0}, ties are rounded toward +positive infinity, otherwise they are rounded toward negative infinity. +This is a consequence of the requirement that +@math{-|@var{y}/2| <= @var{r} < |@var{y}/2|}. + +Note that these operators are equivalent to the R6RS operators +@code{div0}, @code{mod0}, and @code{div0-and-mod0}. + +@lisp +(centered-quotient 123 10) @result{} 12 +(centered-remainder 123 10) @result{} 3 +(centered/ 123 10) @result{} 12 and 3 +(centered/ 123 -10) @result{} -12 and 3 +(centered/ -123 10) @result{} -12 and -3 +(centered/ -123 -10) @result{} 12 and -3 +(centered/ 125 10) @result{} 13 and -5 +(centered/ 127 10) @result{} 13 and -3 +(centered/ 135 10) @result{} 14 and -5 +(centered/ -123.2 -63.5) @result{} 2.0 and 3.8 +(centered/ 16/3 -10/7) @result{} -4 and -8/21 +@end lisp +@end deftypefn + +@deftypefn {Scheme Procedure} {} round/ @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} round-quotient @var{x} @var{y} +@deftypefnx {Scheme Procedure} {} round-remainder @var{x} @var{y} +@deftypefnx {C Function} void scm_round_divide (SCM @var{x}, SCM @var{y}, SCM *@var{q}, SCM *@var{r}) +@deftypefnx {C Function} SCM scm_round_quotient (@var{x}, @var{y}) +@deftypefnx {C Function} SCM scm_round_remainder (@var{x}, @var{y}) +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{round-quotient} returns the +integer @var{q} and @code{round-remainder} returns the real number +@var{r} such that @math{@var{x} = @var{q}*@var{y} + @var{r}} and +@var{q} is @math{@var{x}/@var{y}} rounded to the nearest integer, +with ties going to the nearest even integer. @code{round/} +returns both @var{q} and @var{r}, and is more efficient than computing +each separately. + +Note that @code{round/} and @code{centered/} are almost equivalent, but +their behavior differs when @math{@var{x}/@var{y}} lies exactly half-way +between two integers. In this case, @code{round/} chooses the nearest +even integer, whereas @code{centered/} chooses in such a way to satisfy +the constraint @math{-|@var{y}/2| <= @var{r} < |@var{y}/2|}, which +is stronger than the corresponding constraint for @code{round/}, +@math{-|@var{y}/2| <= @var{r} <= |@var{y}/2|}. In particular, +when @var{x} and @var{y} are integers, the number of possible remainders +returned by @code{centered/} is @math{|@var{y}|}, whereas the number of +possible remainders returned by @code{round/} is @math{|@var{y}|+1} when +@var{y} is even. + +@lisp +(round-quotient 123 10) @result{} 12 +(round-remainder 123 10) @result{} 3 +(round/ 123 10) @result{} 12 and 3 +(round/ 123 -10) @result{} -12 and 3 +(round/ -123 10) @result{} -12 and -3 +(round/ -123 -10) @result{} 12 and -3 +(round/ 125 10) @result{} 12 and 5 +(round/ 127 10) @result{} 13 and -3 +(round/ 135 10) @result{} 14 and -5 +(round/ -123.2 -63.5) @result{} 2.0 and 3.8 +(round/ 16/3 -10/7) @result{} -4 and -8/21 +@end lisp +@end deftypefn + +@node Scientific +@subsubsection Scientific Functions + +The following procedures accept any kind of number as arguments, +including complex numbers. + +@rnindex sqrt +@c begin (texi-doc-string "guile" "sqrt") +@deffn {Scheme Procedure} sqrt z +Return the square root of @var{z}. Of the two possible roots +(positive and negative), the one with a positive real part is +returned, or if that's zero then a positive imaginary part. Thus, + +@example +(sqrt 9.0) @result{} 3.0 +(sqrt -9.0) @result{} 0.0+3.0i +(sqrt 1.0+1.0i) @result{} 1.09868411346781+0.455089860562227i +(sqrt -1.0-1.0i) @result{} 0.455089860562227-1.09868411346781i +@end example +@end deffn + +@rnindex expt +@c begin (texi-doc-string "guile" "expt") +@deffn {Scheme Procedure} expt z1 z2 +Return @var{z1} raised to the power of @var{z2}. +@end deffn + +@rnindex sin +@c begin (texi-doc-string "guile" "sin") +@deffn {Scheme Procedure} sin z +Return the sine of @var{z}. +@end deffn + +@rnindex cos +@c begin (texi-doc-string "guile" "cos") +@deffn {Scheme Procedure} cos z +Return the cosine of @var{z}. +@end deffn + +@rnindex tan +@c begin (texi-doc-string "guile" "tan") +@deffn {Scheme Procedure} tan z +Return the tangent of @var{z}. +@end deffn + +@rnindex asin +@c begin (texi-doc-string "guile" "asin") +@deffn {Scheme Procedure} asin z +Return the arcsine of @var{z}. +@end deffn + +@rnindex acos +@c begin (texi-doc-string "guile" "acos") +@deffn {Scheme Procedure} acos z +Return the arccosine of @var{z}. +@end deffn + +@rnindex atan +@c begin (texi-doc-string "guile" "atan") +@deffn {Scheme Procedure} atan z +@deffnx {Scheme Procedure} atan y x +Return the arctangent of @var{z}, or of @math{@var{y}/@var{x}}. +@end deffn + +@rnindex exp +@c begin (texi-doc-string "guile" "exp") +@deffn {Scheme Procedure} exp z +Return e to the power of @var{z}, where e is the base of natural +logarithms (2.71828@dots{}). +@end deffn + +@rnindex log +@c begin (texi-doc-string "guile" "log") +@deffn {Scheme Procedure} log z +Return the natural logarithm of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "log10") +@deffn {Scheme Procedure} log10 z +Return the base 10 logarithm of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "sinh") +@deffn {Scheme Procedure} sinh z +Return the hyperbolic sine of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "cosh") +@deffn {Scheme Procedure} cosh z +Return the hyperbolic cosine of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "tanh") +@deffn {Scheme Procedure} tanh z +Return the hyperbolic tangent of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "asinh") +@deffn {Scheme Procedure} asinh z +Return the hyperbolic arcsine of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "acosh") +@deffn {Scheme Procedure} acosh z +Return the hyperbolic arccosine of @var{z}. +@end deffn + +@c begin (texi-doc-string "guile" "atanh") +@deffn {Scheme Procedure} atanh z +Return the hyperbolic arctangent of @var{z}. +@end deffn + + +@node Bitwise Operations +@subsubsection Bitwise Operations + +For the following bitwise functions, negative numbers are treated as +infinite precision twos-complements. For instance @math{-6} is bits +@math{@dots{}111010}, with infinitely many ones on the left. It can +be seen that adding 6 (binary 110) to such a bit pattern gives all +zeros. + +@deffn {Scheme Procedure} logand n1 n2 @dots{} +@deffnx {C Function} scm_logand (n1, n2) +Return the bitwise @sc{and} of the integer arguments. + +@lisp +(logand) @result{} -1 +(logand 7) @result{} 7 +(logand #b111 #b011 #b001) @result{} 1 +@end lisp +@end deffn + +@deffn {Scheme Procedure} logior n1 n2 @dots{} +@deffnx {C Function} scm_logior (n1, n2) +Return the bitwise @sc{or} of the integer arguments. + +@lisp +(logior) @result{} 0 +(logior 7) @result{} 7 +(logior #b000 #b001 #b011) @result{} 3 +@end lisp +@end deffn + +@deffn {Scheme Procedure} logxor n1 n2 @dots{} +@deffnx {C Function} scm_loxor (n1, n2) +Return the bitwise @sc{xor} of the integer arguments. A bit is +set in the result if it is set in an odd number of arguments. + +@lisp +(logxor) @result{} 0 +(logxor 7) @result{} 7 +(logxor #b000 #b001 #b011) @result{} 2 +(logxor #b000 #b001 #b011 #b011) @result{} 1 +@end lisp +@end deffn + +@deffn {Scheme Procedure} lognot n +@deffnx {C Function} scm_lognot (n) +Return the integer which is the ones-complement of the integer +argument, ie.@: each 0 bit is changed to 1 and each 1 bit to 0. + +@lisp +(number->string (lognot #b10000000) 2) + @result{} "-10000001" +(number->string (lognot #b0) 2) + @result{} "-1" +@end lisp +@end deffn + +@deffn {Scheme Procedure} logtest j k +@deffnx {C Function} scm_logtest (j, k) +Test whether @var{j} and @var{k} have any 1 bits in common. This is +equivalent to @code{(not (zero? (logand j k)))}, but without actually +calculating the @code{logand}, just testing for non-zero. + +@lisp +(logtest #b0100 #b1011) @result{} #f +(logtest #b0100 #b0111) @result{} #t +@end lisp +@end deffn + +@deffn {Scheme Procedure} logbit? index j +@deffnx {C Function} scm_logbit_p (index, j) +Test whether bit number @var{index} in @var{j} is set. @var{index} +starts from 0 for the least significant bit. + +@lisp +(logbit? 0 #b1101) @result{} #t +(logbit? 1 #b1101) @result{} #f +(logbit? 2 #b1101) @result{} #t +(logbit? 3 #b1101) @result{} #t +(logbit? 4 #b1101) @result{} #f +@end lisp +@end deffn + +@deffn {Scheme Procedure} ash n count +@deffnx {C Function} scm_ash (n, count) +Return @math{floor(n * 2^{count})}. +@var{n} and @var{count} must be exact integers. + +With @var{n} viewed as an infinite-precision twos-complement +integer, @code{ash} means a left shift introducing zero bits +when @var{count} is positive, or a right shift dropping bits +when @var{count} is negative. This is an ``arithmetic'' shift. + +@lisp +(number->string (ash #b1 3) 2) @result{} "1000" +(number->string (ash #b1010 -1) 2) @result{} "101" + +;; -23 is bits ...11101001, -6 is bits ...111010 +(ash -23 -2) @result{} -6 +@end lisp +@end deffn + +@deffn {Scheme Procedure} round-ash n count +@deffnx {C Function} scm_round_ash (n, count) +Return @math{round(n * 2^count)}. +@var{n} and @var{count} must be exact integers. + +With @var{n} viewed as an infinite-precision twos-complement +integer, @code{round-ash} means a left shift introducing zero +bits when @var{count} is positive, or a right shift rounding +to the nearest integer (with ties going to the nearest even +integer) when @var{count} is negative. This is a rounded +``arithmetic'' shift. + +@lisp +(number->string (round-ash #b1 3) 2) @result{} \"1000\" +(number->string (round-ash #b1010 -1) 2) @result{} \"101\" +(number->string (round-ash #b1010 -2) 2) @result{} \"10\" +(number->string (round-ash #b1011 -2) 2) @result{} \"11\" +(number->string (round-ash #b1101 -2) 2) @result{} \"11\" +(number->string (round-ash #b1110 -2) 2) @result{} \"100\" +@end lisp +@end deffn + +@deffn {Scheme Procedure} logcount n +@deffnx {C Function} scm_logcount (n) +Return the number of bits in integer @var{n}. If @var{n} is +positive, the 1-bits in its binary representation are counted. +If negative, the 0-bits in its two's-complement binary +representation are counted. If zero, 0 is returned. + +@lisp +(logcount #b10101010) + @result{} 4 +(logcount 0) + @result{} 0 +(logcount -2) + @result{} 1 +@end lisp +@end deffn + +@deffn {Scheme Procedure} integer-length n +@deffnx {C Function} scm_integer_length (n) +Return the number of bits necessary to represent @var{n}. + +For positive @var{n} this is how many bits to the most significant one +bit. For negative @var{n} it's how many bits to the most significant +zero bit in twos complement form. + +@lisp +(integer-length #b10101010) @result{} 8 +(integer-length #b1111) @result{} 4 +(integer-length 0) @result{} 0 +(integer-length -1) @result{} 0 +(integer-length -256) @result{} 8 +(integer-length -257) @result{} 9 +@end lisp +@end deffn + +@deffn {Scheme Procedure} integer-expt n k +@deffnx {C Function} scm_integer_expt (n, k) +Return @var{n} raised to the power @var{k}. @var{k} must be an exact +integer, @var{n} can be any number. + +Negative @var{k} is supported, and results in @m{1/n^|k|, 1/n^abs(k)} +in the usual way. @math{@var{n}^0} is 1, as usual, and that includes +@math{0^0} is 1. + +@lisp +(integer-expt 2 5) @result{} 32 +(integer-expt -3 3) @result{} -27 +(integer-expt 5 -3) @result{} 1/125 +(integer-expt 0 0) @result{} 1 +@end lisp +@end deffn + +@deffn {Scheme Procedure} bit-extract n start end +@deffnx {C Function} scm_bit_extract (n, start, end) +Return the integer composed of the @var{start} (inclusive) +through @var{end} (exclusive) bits of @var{n}. The +@var{start}th bit becomes the 0-th bit in the result. + +@lisp +(number->string (bit-extract #b1101101010 0 4) 2) + @result{} "1010" +(number->string (bit-extract #b1101101010 4 9) 2) + @result{} "10110" +@end lisp +@end deffn + + +@node Random +@subsubsection Random Number Generation + +Pseudo-random numbers are generated from a random state object, which +can be created with @code{seed->random-state} or +@code{datum->random-state}. An external representation (i.e.@: one +which can written with @code{write} and read with @code{read}) of a +random state object can be obtained via +@code{random-state->datum}. The @var{state} parameter to the +various functions below is optional, it defaults to the state object +in the @code{*random-state*} variable. + +@deffn {Scheme Procedure} copy-random-state [state] +@deffnx {C Function} scm_copy_random_state (state) +Return a copy of the random state @var{state}. +@end deffn + +@deffn {Scheme Procedure} random n [state] +@deffnx {C Function} scm_random (n, state) +Return a number in [0, @var{n}). + +Accepts a positive integer or real n and returns a +number of the same type between zero (inclusive) and +@var{n} (exclusive). The values returned have a uniform +distribution. +@end deffn + +@deffn {Scheme Procedure} random:exp [state] +@deffnx {C Function} scm_random_exp (state) +Return an inexact real in an exponential distribution with mean +1. For an exponential distribution with mean @var{u} use @code{(* +@var{u} (random:exp))}. +@end deffn + +@deffn {Scheme Procedure} random:hollow-sphere! vect [state] +@deffnx {C Function} scm_random_hollow_sphere_x (vect, state) +Fills @var{vect} with inexact real random numbers the sum of whose +squares is equal to 1.0. Thinking of @var{vect} as coordinates in +space of dimension @var{n} @math{=} @code{(vector-length @var{vect})}, +the coordinates are uniformly distributed over the surface of the unit +n-sphere. +@end deffn + +@deffn {Scheme Procedure} random:normal [state] +@deffnx {C Function} scm_random_normal (state) +Return an inexact real in a normal distribution. The distribution +used has mean 0 and standard deviation 1. For a normal distribution +with mean @var{m} and standard deviation @var{d} use @code{(+ @var{m} +(* @var{d} (random:normal)))}. +@end deffn + +@deffn {Scheme Procedure} random:normal-vector! vect [state] +@deffnx {C Function} scm_random_normal_vector_x (vect, state) +Fills @var{vect} with inexact real random numbers that are +independent and standard normally distributed +(i.e., with mean 0 and variance 1). +@end deffn + +@deffn {Scheme Procedure} random:solid-sphere! vect [state] +@deffnx {C Function} scm_random_solid_sphere_x (vect, state) +Fills @var{vect} with inexact real random numbers the sum of whose +squares is less than 1.0. Thinking of @var{vect} as coordinates in +space of dimension @var{n} @math{=} @code{(vector-length @var{vect})}, +the coordinates are uniformly distributed within the unit +@var{n}-sphere. +@c FIXME: What does this mean, particularly the n-sphere part? +@end deffn + +@deffn {Scheme Procedure} random:uniform [state] +@deffnx {C Function} scm_random_uniform (state) +Return a uniformly distributed inexact real random number in +[0,1). +@end deffn + +@deffn {Scheme Procedure} seed->random-state seed +@deffnx {C Function} scm_seed_to_random_state (seed) +Return a new random state using @var{seed}. +@end deffn + +@deffn {Scheme Procedure} datum->random-state datum +@deffnx {C Function} scm_datum_to_random_state (datum) +Return a new random state from @var{datum}, which should have been +obtained by @code{random-state->datum}. +@end deffn + +@deffn {Scheme Procedure} random-state->datum state +@deffnx {C Function} scm_random_state_to_datum (state) +Return a datum representation of @var{state} that may be written out and +read back with the Scheme reader. +@end deffn + +@deffn {Scheme Procedure} random-state-from-platform +@deffnx {C Function} scm_random_state_from_platform () +Construct a new random state seeded from a platform-specific source of +entropy, appropriate for use in non-security-critical applications. +Currently @file{/dev/urandom} is tried first, or else the seed is based +on the time, date, process ID, an address from a freshly allocated heap +cell, an address from the local stack frame, and a high-resolution timer +if available. +@end deffn + +@defvar *random-state* +The global random state used by the above functions when the +@var{state} parameter is not given. +@end defvar + +Note that the initial value of @code{*random-state*} is the same every +time Guile starts up. Therefore, if you don't pass a @var{state} +parameter to the above procedures, and you don't set +@code{*random-state*} to @code{(seed->random-state your-seed)}, where +@code{your-seed} is something that @emph{isn't} the same every time, +you'll get the same sequence of ``random'' numbers on every run. + +For example, unless the relevant source code has changed, @code{(map +random (cdr (iota 30)))}, if the first use of random numbers since +Guile started up, will always give: + +@lisp +(map random (cdr (iota 19))) +@result{} +(0 1 1 2 2 2 1 2 6 7 10 0 5 3 12 5 5 12) +@end lisp + +To seed the random state in a sensible way for non-security-critical +applications, do this during initialization of your program: + +@lisp +(set! *random-state* (random-state-from-platform)) +@end lisp + + +@node Characters +@subsection Characters +@tpindex Characters + +In Scheme, there is a data type to describe a single character. + +Defining what exactly a character @emph{is} can be more complicated +than it seems. Guile follows the advice of R6RS and uses The Unicode +Standard to help define what a character is. So, for Guile, a +character is anything in the Unicode Character Database. + +@cindex code point +@cindex Unicode code point + +The Unicode Character Database is basically a table of characters +indexed using integers called 'code points'. Valid code points are in +the ranges 0 to @code{#xD7FF} inclusive or @code{#xE000} to +@code{#x10FFFF} inclusive, which is about 1.1 million code points. + +@cindex designated code point +@cindex code point, designated + +Any code point that has been assigned to a character or that has +otherwise been given a meaning by Unicode is called a 'designated code +point'. Most of the designated code points, about 200,000 of them, +indicate characters, accents or other combining marks that modify +other characters, symbols, whitespace, and control characters. Some +are not characters but indicators that suggest how to format or +display neighboring characters. + +@cindex reserved code point +@cindex code point, reserved + +If a code point is not a designated code point -- if it has not been +assigned to a character by The Unicode Standard -- it is a 'reserved +code point', meaning that they are reserved for future use. Most of +the code points, about 800,000, are 'reserved code points'. + +By convention, a Unicode code point is written as +``U+XXXX'' where ``XXXX'' is a hexadecimal number. Please note that +this convenient notation is not valid code. Guile does not interpret +``U+XXXX'' as a character. + +In Scheme, a character literal is written as @code{#\@var{name}} where +@var{name} is the name of the character that you want. Printable +characters have their usual single character name; for example, +@code{#\a} is a lower case @code{a}. + +Some of the code points are 'combining characters' that are not meant +to be printed by themselves but are instead meant to modify the +appearance of the previous character. For combining characters, an +alternate form of the character literal is @code{#\} followed by +U+25CC (a small, dotted circle), followed by the combining character. +This allows the combining character to be drawn on the circle, not on +the backslash of @code{#\}. + +Many of the non-printing characters, such as whitespace characters and +control characters, also have names. + +The most commonly used non-printing characters have long character +names, described in the table below. + +@multitable {@code{#\backspace}} {Preferred} +@item Character Name @tab Codepoint +@item @code{#\nul} @tab U+0000 +@item @code{#\alarm} @tab U+0007 +@item @code{#\backspace} @tab U+0008 +@item @code{#\tab} @tab U+0009 +@item @code{#\linefeed} @tab U+000A +@item @code{#\newline} @tab U+000A +@item @code{#\vtab} @tab U+000B +@item @code{#\page} @tab U+000C +@item @code{#\return} @tab U+000D +@item @code{#\esc} @tab U+001B +@item @code{#\space} @tab U+0020 +@item @code{#\delete} @tab U+007F +@end multitable + +There are also short names for all of the ``C0 control characters'' +(those with code points below 32). The following table lists the short +name for each character. + +@multitable @columnfractions .25 .25 .25 .25 +@item 0 = @code{#\nul} + @tab 1 = @code{#\soh} + @tab 2 = @code{#\stx} + @tab 3 = @code{#\etx} +@item 4 = @code{#\eot} + @tab 5 = @code{#\enq} + @tab 6 = @code{#\ack} + @tab 7 = @code{#\bel} +@item 8 = @code{#\bs} + @tab 9 = @code{#\ht} + @tab 10 = @code{#\lf} + @tab 11 = @code{#\vt} +@item 12 = @code{#\ff} + @tab 13 = @code{#\cr} + @tab 14 = @code{#\so} + @tab 15 = @code{#\si} +@item 16 = @code{#\dle} + @tab 17 = @code{#\dc1} + @tab 18 = @code{#\dc2} + @tab 19 = @code{#\dc3} +@item 20 = @code{#\dc4} + @tab 21 = @code{#\nak} + @tab 22 = @code{#\syn} + @tab 23 = @code{#\etb} +@item 24 = @code{#\can} + @tab 25 = @code{#\em} + @tab 26 = @code{#\sub} + @tab 27 = @code{#\esc} +@item 28 = @code{#\fs} + @tab 29 = @code{#\gs} + @tab 30 = @code{#\rs} + @tab 31 = @code{#\us} +@item 32 = @code{#\sp} +@end multitable + +The short name for the ``delete'' character (code point U+007F) is +@code{#\del}. + +The R7RS name for the ``escape'' character (code point U+001B) is +@code{#\escape}. + +There are also a few alternative names left over for compatibility with +previous versions of Guile. + +@multitable {@code{#\backspace}} {Preferred} +@item Alternate @tab Standard +@item @code{#\nl} @tab @code{#\newline} +@item @code{#\np} @tab @code{#\page} +@item @code{#\null} @tab @code{#\nul} +@end multitable + +Characters may also be written using their code point values. They can +be written with as an octal number, such as @code{#\10} for +@code{#\bs} or @code{#\177} for @code{#\del}. + +If one prefers hex to octal, there is an additional syntax for character +escapes: @code{#\xHHHH} -- the letter 'x' followed by a hexadecimal +number of one to eight digits. + +@rnindex char? +@deffn {Scheme Procedure} char? x +@deffnx {C Function} scm_char_p (x) +Return @code{#t} if @var{x} is a character, else @code{#f}. +@end deffn + +Fundamentally, the character comparison operations below are +numeric comparisons of the character's code points. + +@rnindex char=? +@deffn {Scheme Procedure} char=? x y +Return @code{#t} if code point of @var{x} is equal to the code point +of @var{y}, else @code{#f}. +@end deffn + +@rnindex char<? +@deffn {Scheme Procedure} char<? x y +Return @code{#t} if the code point of @var{x} is less than the code +point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char<=? +@deffn {Scheme Procedure} char<=? x y +Return @code{#t} if the code point of @var{x} is less than or equal +to the code point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char>? +@deffn {Scheme Procedure} char>? x y +Return @code{#t} if the code point of @var{x} is greater than the +code point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char>=? +@deffn {Scheme Procedure} char>=? x y +Return @code{#t} if the code point of @var{x} is greater than or +equal to the code point of @var{y}, else @code{#f}. +@end deffn + +@cindex case folding + +Case-insensitive character comparisons use @emph{Unicode case +folding}. In case folding comparisons, if a character is lowercase +and has an uppercase form that can be expressed as a single character, +it is converted to uppercase before comparison. All other characters +undergo no conversion before the comparison occurs. This includes the +German sharp S (Eszett) which is not uppercased before conversion +because its uppercase form has two characters. Unicode case folding +is language independent: it uses rules that are generally true, but, +it cannot cover all cases for all languages. + +@rnindex char-ci=? +@deffn {Scheme Procedure} char-ci=? x y +Return @code{#t} if the case-folded code point of @var{x} is the same +as the case-folded code point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char-ci<? +@deffn {Scheme Procedure} char-ci<? x y +Return @code{#t} if the case-folded code point of @var{x} is less +than the case-folded code point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char-ci<=? +@deffn {Scheme Procedure} char-ci<=? x y +Return @code{#t} if the case-folded code point of @var{x} is less +than or equal to the case-folded code point of @var{y}, else +@code{#f}. +@end deffn + +@rnindex char-ci>? +@deffn {Scheme Procedure} char-ci>? x y +Return @code{#t} if the case-folded code point of @var{x} is greater +than the case-folded code point of @var{y}, else @code{#f}. +@end deffn + +@rnindex char-ci>=? +@deffn {Scheme Procedure} char-ci>=? x y +Return @code{#t} if the case-folded code point of @var{x} is greater +than or equal to the case-folded code point of @var{y}, else +@code{#f}. +@end deffn + +@rnindex char-alphabetic? +@deffn {Scheme Procedure} char-alphabetic? chr +@deffnx {C Function} scm_char_alphabetic_p (chr) +Return @code{#t} if @var{chr} is alphabetic, else @code{#f}. +@end deffn + +@rnindex char-numeric? +@deffn {Scheme Procedure} char-numeric? chr +@deffnx {C Function} scm_char_numeric_p (chr) +Return @code{#t} if @var{chr} is numeric, else @code{#f}. +@end deffn + +@rnindex char-whitespace? +@deffn {Scheme Procedure} char-whitespace? chr +@deffnx {C Function} scm_char_whitespace_p (chr) +Return @code{#t} if @var{chr} is whitespace, else @code{#f}. +@end deffn + +@rnindex char-upper-case? +@deffn {Scheme Procedure} char-upper-case? chr +@deffnx {C Function} scm_char_upper_case_p (chr) +Return @code{#t} if @var{chr} is uppercase, else @code{#f}. +@end deffn + +@rnindex char-lower-case? +@deffn {Scheme Procedure} char-lower-case? chr +@deffnx {C Function} scm_char_lower_case_p (chr) +Return @code{#t} if @var{chr} is lowercase, else @code{#f}. +@end deffn + +@deffn {Scheme Procedure} char-is-both? chr +@deffnx {C Function} scm_char_is_both_p (chr) +Return @code{#t} if @var{chr} is either uppercase or lowercase, else +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} char-general-category chr +@deffnx {C Function} scm_char_general_category (chr) +Return a symbol giving the two-letter name of the Unicode general +category assigned to @var{chr} or @code{#f} if no named category is +assigned. The following table provides a list of category names along +with their meanings. + +@multitable @columnfractions .1 .4 .1 .4 +@item Lu + @tab Uppercase letter + @tab Pf + @tab Final quote punctuation +@item Ll + @tab Lowercase letter + @tab Po + @tab Other punctuation +@item Lt + @tab Titlecase letter + @tab Sm + @tab Math symbol +@item Lm + @tab Modifier letter + @tab Sc + @tab Currency symbol +@item Lo + @tab Other letter + @tab Sk + @tab Modifier symbol +@item Mn + @tab Non-spacing mark + @tab So + @tab Other symbol +@item Mc + @tab Combining spacing mark + @tab Zs + @tab Space separator +@item Me + @tab Enclosing mark + @tab Zl + @tab Line separator +@item Nd + @tab Decimal digit number + @tab Zp + @tab Paragraph separator +@item Nl + @tab Letter number + @tab Cc + @tab Control +@item No + @tab Other number + @tab Cf + @tab Format +@item Pc + @tab Connector punctuation + @tab Cs + @tab Surrogate +@item Pd + @tab Dash punctuation + @tab Co + @tab Private use +@item Ps + @tab Open punctuation + @tab Cn + @tab Unassigned +@item Pe + @tab Close punctuation + @tab + @tab +@item Pi + @tab Initial quote punctuation + @tab + @tab +@end multitable +@end deffn + +@rnindex char->integer +@deffn {Scheme Procedure} char->integer chr +@deffnx {C Function} scm_char_to_integer (chr) +Return the code point of @var{chr}. +@end deffn + +@rnindex integer->char +@deffn {Scheme Procedure} integer->char n +@deffnx {C Function} scm_integer_to_char (n) +Return the character that has code point @var{n}. The integer @var{n} +must be a valid code point. Valid code points are in the ranges 0 to +@code{#xD7FF} inclusive or @code{#xE000} to @code{#x10FFFF} inclusive. +@end deffn + +@rnindex char-upcase +@deffn {Scheme Procedure} char-upcase chr +@deffnx {C Function} scm_char_upcase (chr) +Return the uppercase character version of @var{chr}. +@end deffn + +@rnindex char-downcase +@deffn {Scheme Procedure} char-downcase chr +@deffnx {C Function} scm_char_downcase (chr) +Return the lowercase character version of @var{chr}. +@end deffn + +@rnindex char-titlecase +@deffn {Scheme Procedure} char-titlecase chr +@deffnx {C Function} scm_char_titlecase (chr) +Return the titlecase character version of @var{chr} if one exists; +otherwise return the uppercase version. + +For most characters these will be the same, but the Unicode Standard +includes certain digraph compatibility characters, such as @code{U+01F3} +``dz'', for which the uppercase and titlecase characters are different +(@code{U+01F1} ``DZ'' and @code{U+01F2} ``Dz'' in this case, +respectively). +@end deffn + +@tindex scm_t_wchar +@deftypefn {C Function} scm_t_wchar scm_c_upcase (scm_t_wchar @var{c}) +@deftypefnx {C Function} scm_t_wchar scm_c_downcase (scm_t_wchar @var{c}) +@deftypefnx {C Function} scm_t_wchar scm_c_titlecase (scm_t_wchar @var{c}) + +These C functions take an integer representation of a Unicode +codepoint and return the codepoint corresponding to its uppercase, +lowercase, and titlecase forms respectively. The type +@code{scm_t_wchar} is a signed, 32-bit integer. +@end deftypefn + +Characters also have ``formal names'', which are defined by Unicode. +These names can be accessed in Guile from the @code{(ice-9 unicode)} +module: + +@example +(use-modules (ice-9 unicode)) +@end example + +@deffn {Scheme Procedure} char->formal-name chr +Return the formal all-upper-case Unicode name of @var{ch}, +as a string, or @code{#f} if the character has no name. +@end deffn + +@deffn {Scheme Procedure} formal-name->char name +Return the character whose formal all-upper-case Unicode name is +@var{name}, or @code{#f} if no such character is known. +@end deffn + +@node Character Sets +@subsection Character Sets + +The features described in this section correspond directly to SRFI-14. + +The data type @dfn{charset} implements sets of characters +(@pxref{Characters}). Because the internal representation of +character sets is not visible to the user, a lot of procedures for +handling them are provided. + +Character sets can be created, extended, tested for the membership of a +characters and be compared to other character sets. + +@menu +* Character Set Predicates/Comparison:: +* Iterating Over Character Sets:: Enumerate charset elements. +* Creating Character Sets:: Making new charsets. +* Querying Character Sets:: Test charsets for membership etc. +* Character-Set Algebra:: Calculating new charsets. +* Standard Character Sets:: Variables containing predefined charsets. +@end menu + +@node Character Set Predicates/Comparison +@subsubsection Character Set Predicates/Comparison + +Use these procedures for testing whether an object is a character set, +or whether several character sets are equal or subsets of each other. +@code{char-set-hash} can be used for calculating a hash value, maybe for +usage in fast lookup procedures. + +@deffn {Scheme Procedure} char-set? obj +@deffnx {C Function} scm_char_set_p (obj) +Return @code{#t} if @var{obj} is a character set, @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} char-set= char_set @dots{} +@deffnx {C Function} scm_char_set_eq (char_sets) +Return @code{#t} if all given character sets are equal. +@end deffn + +@deffn {Scheme Procedure} char-set<= char_set @dots{} +@deffnx {C Function} scm_char_set_leq (char_sets) +Return @code{#t} if every character set @var{char_set}i is a subset +of character set @var{char_set}i+1. +@end deffn + +@deffn {Scheme Procedure} char-set-hash cs [bound] +@deffnx {C Function} scm_char_set_hash (cs, bound) +Compute a hash value for the character set @var{cs}. If +@var{bound} is given and non-zero, it restricts the +returned value to the range 0 @dots{} @var{bound} - 1. +@end deffn + +@c =================================================================== + +@node Iterating Over Character Sets +@subsubsection Iterating Over Character Sets + +Character set cursors are a means for iterating over the members of a +character sets. After creating a character set cursor with +@code{char-set-cursor}, a cursor can be dereferenced with +@code{char-set-ref}, advanced to the next member with +@code{char-set-cursor-next}. Whether a cursor has passed past the last +element of the set can be checked with @code{end-of-char-set?}. + +Additionally, mapping and (un-)folding procedures for character sets are +provided. + +@deffn {Scheme Procedure} char-set-cursor cs +@deffnx {C Function} scm_char_set_cursor (cs) +Return a cursor into the character set @var{cs}. +@end deffn + +@deffn {Scheme Procedure} char-set-ref cs cursor +@deffnx {C Function} scm_char_set_ref (cs, cursor) +Return the character at the current cursor position +@var{cursor} in the character set @var{cs}. It is an error to +pass a cursor for which @code{end-of-char-set?} returns true. +@end deffn + +@deffn {Scheme Procedure} char-set-cursor-next cs cursor +@deffnx {C Function} scm_char_set_cursor_next (cs, cursor) +Advance the character set cursor @var{cursor} to the next +character in the character set @var{cs}. It is an error if the +cursor given satisfies @code{end-of-char-set?}. +@end deffn + +@deffn {Scheme Procedure} end-of-char-set? cursor +@deffnx {C Function} scm_end_of_char_set_p (cursor) +Return @code{#t} if @var{cursor} has reached the end of a +character set, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} char-set-fold kons knil cs +@deffnx {C Function} scm_char_set_fold (kons, knil, cs) +Fold the procedure @var{kons} over the character set @var{cs}, +initializing it with @var{knil}. +@end deffn + +@deffn {Scheme Procedure} char-set-unfold p f g seed [base_cs] +@deffnx {C Function} scm_char_set_unfold (p, f, g, seed, base_cs) +This is a fundamental constructor for character sets. +@itemize @bullet +@item @var{g} is used to generate a series of ``seed'' values +from the initial seed: @var{seed}, (@var{g} @var{seed}), +(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{} +@item @var{p} tells us when to stop -- when it returns true +when applied to one of the seed values. +@item @var{f} maps each seed value to a character. These +characters are added to the base character set @var{base_cs} to +form the result; @var{base_cs} defaults to the empty set. +@end itemize +@end deffn + +@deffn {Scheme Procedure} char-set-unfold! p f g seed base_cs +@deffnx {C Function} scm_char_set_unfold_x (p, f, g, seed, base_cs) +This is a fundamental constructor for character sets. +@itemize @bullet +@item @var{g} is used to generate a series of ``seed'' values +from the initial seed: @var{seed}, (@var{g} @var{seed}), +(@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), @dots{} +@item @var{p} tells us when to stop -- when it returns true +when applied to one of the seed values. +@item @var{f} maps each seed value to a character. These +characters are added to the base character set @var{base_cs} to +form the result; @var{base_cs} defaults to the empty set. +@end itemize +@end deffn + +@deffn {Scheme Procedure} char-set-for-each proc cs +@deffnx {C Function} scm_char_set_for_each (proc, cs) +Apply @var{proc} to every character in the character set +@var{cs}. The return value is not specified. +@end deffn + +@deffn {Scheme Procedure} char-set-map proc cs +@deffnx {C Function} scm_char_set_map (proc, cs) +Map the procedure @var{proc} over every character in @var{cs}. +@var{proc} must be a character -> character procedure. +@end deffn + +@c =================================================================== + +@node Creating Character Sets +@subsubsection Creating Character Sets + +New character sets are produced with these procedures. + +@deffn {Scheme Procedure} char-set-copy cs +@deffnx {C Function} scm_char_set_copy (cs) +Return a newly allocated character set containing all +characters in @var{cs}. +@end deffn + +@deffn {Scheme Procedure} char-set chr @dots{} +@deffnx {C Function} scm_char_set (chrs) +Return a character set containing all given characters. +@end deffn + +@deffn {Scheme Procedure} list->char-set list [base_cs] +@deffnx {C Function} scm_list_to_char_set (list, base_cs) +Convert the character list @var{list} to a character set. If +the character set @var{base_cs} is given, the character in this +set are also included in the result. +@end deffn + +@deffn {Scheme Procedure} list->char-set! list base_cs +@deffnx {C Function} scm_list_to_char_set_x (list, base_cs) +Convert the character list @var{list} to a character set. The +characters are added to @var{base_cs} and @var{base_cs} is +returned. +@end deffn + +@deffn {Scheme Procedure} string->char-set str [base_cs] +@deffnx {C Function} scm_string_to_char_set (str, base_cs) +Convert the string @var{str} to a character set. If the +character set @var{base_cs} is given, the characters in this +set are also included in the result. +@end deffn + +@deffn {Scheme Procedure} string->char-set! str base_cs +@deffnx {C Function} scm_string_to_char_set_x (str, base_cs) +Convert the string @var{str} to a character set. The +characters from the string are added to @var{base_cs}, and +@var{base_cs} is returned. +@end deffn + +@deffn {Scheme Procedure} char-set-filter pred cs [base_cs] +@deffnx {C Function} scm_char_set_filter (pred, cs, base_cs) +Return a character set containing every character from @var{cs} +so that it satisfies @var{pred}. If provided, the characters +from @var{base_cs} are added to the result. +@end deffn + +@deffn {Scheme Procedure} char-set-filter! pred cs base_cs +@deffnx {C Function} scm_char_set_filter_x (pred, cs, base_cs) +Return a character set containing every character from @var{cs} +so that it satisfies @var{pred}. The characters are added to +@var{base_cs} and @var{base_cs} is returned. +@end deffn + +@deffn {Scheme Procedure} ucs-range->char-set lower upper [error [base_cs]] +@deffnx {C Function} scm_ucs_range_to_char_set (lower, upper, error, base_cs) +Return a character set containing all characters whose +character codes lie in the half-open range +[@var{lower},@var{upper}). + +If @var{error} is a true value, an error is signalled if the +specified range contains characters which are not contained in +the implemented character range. If @var{error} is @code{#f}, +these characters are silently left out of the resulting +character set. + +The characters in @var{base_cs} are added to the result, if +given. +@end deffn + +@deffn {Scheme Procedure} ucs-range->char-set! lower upper error base_cs +@deffnx {C Function} scm_ucs_range_to_char_set_x (lower, upper, error, base_cs) +Return a character set containing all characters whose +character codes lie in the half-open range +[@var{lower},@var{upper}). + +If @var{error} is a true value, an error is signalled if the +specified range contains characters which are not contained in +the implemented character range. If @var{error} is @code{#f}, +these characters are silently left out of the resulting +character set. + +The characters are added to @var{base_cs} and @var{base_cs} is +returned. +@end deffn + +@deffn {Scheme Procedure} ->char-set x +@deffnx {C Function} scm_to_char_set (x) +Coerces x into a char-set. @var{x} may be a string, character or +char-set. A string is converted to the set of its constituent +characters; a character is converted to a singleton set; a char-set is +returned as-is. +@end deffn + +@c =================================================================== + +@node Querying Character Sets +@subsubsection Querying Character Sets + +Access the elements and other information of a character set with these +procedures. + +@deffn {Scheme Procedure} %char-set-dump cs +Returns an association list containing debugging information +for @var{cs}. The association list has the following entries. +@table @code +@item char-set +The char-set itself +@item len +The number of groups of contiguous code points the char-set +contains +@item ranges +A list of lists where each sublist is a range of code points +and their associated characters +@end table +The return value of this function cannot be relied upon to be +consistent between versions of Guile and should not be used in code. +@end deffn + +@deffn {Scheme Procedure} char-set-size cs +@deffnx {C Function} scm_char_set_size (cs) +Return the number of elements in character set @var{cs}. +@end deffn + +@deffn {Scheme Procedure} char-set-count pred cs +@deffnx {C Function} scm_char_set_count (pred, cs) +Return the number of the elements int the character set +@var{cs} which satisfy the predicate @var{pred}. +@end deffn + +@deffn {Scheme Procedure} char-set->list cs +@deffnx {C Function} scm_char_set_to_list (cs) +Return a list containing the elements of the character set +@var{cs}. +@end deffn + +@deffn {Scheme Procedure} char-set->string cs +@deffnx {C Function} scm_char_set_to_string (cs) +Return a string containing the elements of the character set +@var{cs}. The order in which the characters are placed in the +string is not defined. +@end deffn + +@deffn {Scheme Procedure} char-set-contains? cs ch +@deffnx {C Function} scm_char_set_contains_p (cs, ch) +Return @code{#t} if the character @var{ch} is contained in the +character set @var{cs}, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} char-set-every pred cs +@deffnx {C Function} scm_char_set_every (pred, cs) +Return a true value if every character in the character set +@var{cs} satisfies the predicate @var{pred}. +@end deffn + +@deffn {Scheme Procedure} char-set-any pred cs +@deffnx {C Function} scm_char_set_any (pred, cs) +Return a true value if any character in the character set +@var{cs} satisfies the predicate @var{pred}. +@end deffn + +@c =================================================================== + +@node Character-Set Algebra +@subsubsection Character-Set Algebra + +Character sets can be manipulated with the common set algebra operation, +such as union, complement, intersection etc. All of these procedures +provide side-effecting variants, which modify their character set +argument(s). + +@deffn {Scheme Procedure} char-set-adjoin cs chr @dots{} +@deffnx {C Function} scm_char_set_adjoin (cs, chrs) +Add all character arguments to the first argument, which must +be a character set. +@end deffn + +@deffn {Scheme Procedure} char-set-delete cs chr @dots{} +@deffnx {C Function} scm_char_set_delete (cs, chrs) +Delete all character arguments from the first argument, which +must be a character set. +@end deffn + +@deffn {Scheme Procedure} char-set-adjoin! cs chr @dots{} +@deffnx {C Function} scm_char_set_adjoin_x (cs, chrs) +Add all character arguments to the first argument, which must +be a character set. +@end deffn + +@deffn {Scheme Procedure} char-set-delete! cs chr @dots{} +@deffnx {C Function} scm_char_set_delete_x (cs, chrs) +Delete all character arguments from the first argument, which +must be a character set. +@end deffn + +@deffn {Scheme Procedure} char-set-complement cs +@deffnx {C Function} scm_char_set_complement (cs) +Return the complement of the character set @var{cs}. +@end deffn + +Note that the complement of a character set is likely to contain many +reserved code points (code points that are not associated with +characters). It may be helpful to modify the output of +@code{char-set-complement} by computing its intersection with the set +of designated code points, @code{char-set:designated}. + +@deffn {Scheme Procedure} char-set-union cs @dots{} +@deffnx {C Function} scm_char_set_union (char_sets) +Return the union of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-intersection cs @dots{} +@deffnx {C Function} scm_char_set_intersection (char_sets) +Return the intersection of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-difference cs1 cs @dots{} +@deffnx {C Function} scm_char_set_difference (cs1, char_sets) +Return the difference of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-xor cs @dots{} +@deffnx {C Function} scm_char_set_xor (char_sets) +Return the exclusive-or of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-diff+intersection cs1 cs @dots{} +@deffnx {C Function} scm_char_set_diff_plus_intersection (cs1, char_sets) +Return the difference and the intersection of all argument +character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-complement! cs +@deffnx {C Function} scm_char_set_complement_x (cs) +Return the complement of the character set @var{cs}. +@end deffn + +@deffn {Scheme Procedure} char-set-union! cs1 cs @dots{} +@deffnx {C Function} scm_char_set_union_x (cs1, char_sets) +Return the union of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-intersection! cs1 cs @dots{} +@deffnx {C Function} scm_char_set_intersection_x (cs1, char_sets) +Return the intersection of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-difference! cs1 cs @dots{} +@deffnx {C Function} scm_char_set_difference_x (cs1, char_sets) +Return the difference of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-xor! cs1 cs @dots{} +@deffnx {C Function} scm_char_set_xor_x (cs1, char_sets) +Return the exclusive-or of all argument character sets. +@end deffn + +@deffn {Scheme Procedure} char-set-diff+intersection! cs1 cs2 cs @dots{} +@deffnx {C Function} scm_char_set_diff_plus_intersection_x (cs1, cs2, char_sets) +Return the difference and the intersection of all argument +character sets. +@end deffn + +@c =================================================================== + +@node Standard Character Sets +@subsubsection Standard Character Sets + +In order to make the use of the character set data type and procedures +useful, several predefined character set variables exist. + +@cindex codeset +@cindex charset +@cindex locale + +These character sets are locale independent and are not recomputed +upon a @code{setlocale} call. They contain characters from the whole +range of Unicode code points. For instance, @code{char-set:letter} +contains about 100,000 characters. + +@defvr {Scheme Variable} char-set:lower-case +@defvrx {C Variable} scm_char_set_lower_case +All lower-case characters. +@end defvr + +@defvr {Scheme Variable} char-set:upper-case +@defvrx {C Variable} scm_char_set_upper_case +All upper-case characters. +@end defvr + +@defvr {Scheme Variable} char-set:title-case +@defvrx {C Variable} scm_char_set_title_case +All single characters that function as if they were an upper-case +letter followed by a lower-case letter. +@end defvr + +@defvr {Scheme Variable} char-set:letter +@defvrx {C Variable} scm_char_set_letter +All letters. This includes @code{char-set:lower-case}, +@code{char-set:upper-case}, @code{char-set:title-case}, and many +letters that have no case at all. For example, Chinese and Japanese +characters typically have no concept of case. +@end defvr + +@defvr {Scheme Variable} char-set:digit +@defvrx {C Variable} scm_char_set_digit +All digits. +@end defvr + +@defvr {Scheme Variable} char-set:letter+digit +@defvrx {C Variable} scm_char_set_letter_and_digit +The union of @code{char-set:letter} and @code{char-set:digit}. +@end defvr + +@defvr {Scheme Variable} char-set:graphic +@defvrx {C Variable} scm_char_set_graphic +All characters which would put ink on the paper. +@end defvr + +@defvr {Scheme Variable} char-set:printing +@defvrx {C Variable} scm_char_set_printing +The union of @code{char-set:graphic} and @code{char-set:whitespace}. +@end defvr + +@defvr {Scheme Variable} char-set:whitespace +@defvrx {C Variable} scm_char_set_whitespace +All whitespace characters. +@end defvr + +@defvr {Scheme Variable} char-set:blank +@defvrx {C Variable} scm_char_set_blank +All horizontal whitespace characters, which notably includes +@code{#\space} and @code{#\tab}. +@end defvr + +@defvr {Scheme Variable} char-set:iso-control +@defvrx {C Variable} scm_char_set_iso_control +The ISO control characters are the C0 control characters (U+0000 to +U+001F), delete (U+007F), and the C1 control characters (U+0080 to +U+009F). +@end defvr + +@defvr {Scheme Variable} char-set:punctuation +@defvrx {C Variable} scm_char_set_punctuation +All punctuation characters, such as the characters +@code{!"#%&'()*,-./:;?@@[\\]_@{@}} +@end defvr + +@defvr {Scheme Variable} char-set:symbol +@defvrx {C Variable} scm_char_set_symbol +All symbol characters, such as the characters @code{$+<=>^`|~}. +@end defvr + +@defvr {Scheme Variable} char-set:hex-digit +@defvrx {C Variable} scm_char_set_hex_digit +The hexadecimal digits @code{0123456789abcdefABCDEF}. +@end defvr + +@defvr {Scheme Variable} char-set:ascii +@defvrx {C Variable} scm_char_set_ascii +All ASCII characters. +@end defvr + +@defvr {Scheme Variable} char-set:empty +@defvrx {C Variable} scm_char_set_empty +The empty character set. +@end defvr + +@defvr {Scheme Variable} char-set:designated +@defvrx {C Variable} scm_char_set_designated +This character set contains all designated code points. This includes +all the code points to which Unicode has assigned a character or other +meaning. +@end defvr + +@defvr {Scheme Variable} char-set:full +@defvrx {C Variable} scm_char_set_full +This character set contains all possible code points. This includes +both designated and reserved code points. +@end defvr + +@node Strings +@subsection Strings +@tpindex Strings + +Strings are fixed-length sequences of characters. They can be created +by calling constructor procedures, but they can also literally get +entered at the @acronym{REPL} or in Scheme source files. + +@c Guile provides a rich set of string processing procedures, because text +@c handling is very important when Guile is used as a scripting language. + +Strings always carry the information about how many characters they are +composed of with them, so there is no special end-of-string character, +like in C. That means that Scheme strings can contain any character, +even the @samp{#\nul} character @samp{\0}. + +To use strings efficiently, you need to know a bit about how Guile +implements them. In Guile, a string consists of two parts, a head and +the actual memory where the characters are stored. When a string (or +a substring of it) is copied, only a new head gets created, the memory +is usually not copied. The two heads start out pointing to the same +memory. + +When one of these two strings is modified, as with @code{string-set!}, +their common memory does get copied so that each string has its own +memory and modifying one does not accidentally modify the other as well. +Thus, Guile's strings are `copy on write'; the actual copying of their +memory is delayed until one string is written to. + +This implementation makes functions like @code{substring} very +efficient in the common case that no modifications are done to the +involved strings. + +If you do know that your strings are getting modified right away, you +can use @code{substring/copy} instead of @code{substring}. This +function performs the copy immediately at the time of creation. This +is more efficient, especially in a multi-threaded program. Also, +@code{substring/copy} can avoid the problem that a short substring +holds on to the memory of a very large original string that could +otherwise be recycled. + +If you want to avoid the copy altogether, so that modifications of one +string show up in the other, you can use @code{substring/shared}. The +strings created by this procedure are called @dfn{mutation sharing +substrings} since the substring and the original string share +modifications to each other. + +If you want to prevent modifications, use @code{substring/read-only}. + +Guile provides all procedures of SRFI-13 and a few more. + +@menu +* String Syntax:: Read syntax for strings. +* String Predicates:: Testing strings for certain properties. +* String Constructors:: Creating new string objects. +* List/String Conversion:: Converting from/to lists of characters. +* String Selection:: Select portions from strings. +* String Modification:: Modify parts or whole strings. +* String Comparison:: Lexicographic ordering predicates. +* String Searching:: Searching in strings. +* Alphabetic Case Mapping:: Convert the alphabetic case of strings. +* Reversing and Appending Strings:: Appending strings to form a new string. +* Mapping Folding and Unfolding:: Iterating over strings. +* Miscellaneous String Operations:: Replicating, insertion, parsing, ... +* Representing Strings as Bytes:: Encoding and decoding strings. +* Conversion to/from C:: +* String Internals:: The storage strategy for strings. +@end menu + +@node String Syntax +@subsubsection String Read Syntax + +@c In the following @code is used to get a good font in TeX etc, but +@c is omitted for Info format, so as not to risk any confusion over +@c whether surrounding ` ' quotes are part of the escape or are +@c special in a string (they're not). + +The read syntax for strings is an arbitrarily long sequence of +characters enclosed in double quotes (@nicode{"}). + +Backslash is an escape character and can be used to insert the following +special characters. @nicode{\"} and @nicode{\\} are R5RS standard, +@nicode{\|} is R7RS standard, the next seven are R6RS standard --- +notice they follow C syntax --- and the remaining four are Guile +extensions. + +@table @asis +@item @nicode{\\} +Backslash character. + +@item @nicode{\"} +Double quote character (an unescaped @nicode{"} is otherwise the end +of the string). + +@item @nicode{\|} +Vertical bar character. + +@item @nicode{\a} +Bell character (ASCII 7). + +@item @nicode{\f} +Formfeed character (ASCII 12). + +@item @nicode{\n} +Newline character (ASCII 10). + +@item @nicode{\r} +Carriage return character (ASCII 13). + +@item @nicode{\t} +Tab character (ASCII 9). + +@item @nicode{\v} +Vertical tab character (ASCII 11). + +@item @nicode{\b} +Backspace character (ASCII 8). + +@item @nicode{\0} +NUL character (ASCII 0). + +@item @nicode{\(} +Open parenthesis. This is intended for use at the beginning of lines in +multiline strings to avoid confusing Emacs lisp modes. + +@item @nicode{\} followed by newline (ASCII 10) +Nothing. This way if @nicode{\} is the last character in a line, the +string will continue with the first character from the next line, +without a line break. + +If the @code{hungry-eol-escapes} reader option is enabled, which is not +the case by default, leading whitespace on the next line is discarded. + +@lisp +"foo\ + bar" +@result{} "foo bar" +(read-enable 'hungry-eol-escapes) +"foo\ + bar" +@result{} "foobar" +@end lisp +@item @nicode{\xHH} +Character code given by two hexadecimal digits. For example +@nicode{\x7f} for an ASCII DEL (127). + +@item @nicode{\uHHHH} +Character code given by four hexadecimal digits. For example +@nicode{\u0100} for a capital A with macron (U+0100). + +@item @nicode{\UHHHHHH} +Character code given by six hexadecimal digits. For example +@nicode{\U010402}. +@end table + +@noindent +The following are examples of string literals: + +@lisp +"foo" +"bar plonk" +"Hello World" +"\"Hi\", he said." +@end lisp + +The three escape sequences @code{\xHH}, @code{\uHHHH} and @code{\UHHHHHH} were +chosen to not break compatibility with code written for previous versions of +Guile. The R6RS specification suggests a different, incompatible syntax for hex +escapes: @code{\xHHHH;} -- a character code followed by one to eight hexadecimal +digits terminated with a semicolon. If this escape format is desired instead, +it can be enabled with the reader option @code{r6rs-hex-escapes}. + +@lisp +(read-enable 'r6rs-hex-escapes) +@end lisp + +For more on reader options, @xref{Scheme Read}. + +@node String Predicates +@subsubsection String Predicates + +The following procedures can be used to check whether a given string +fulfills some specified property. + +@rnindex string? +@deffn {Scheme Procedure} string? obj +@deffnx {C Function} scm_string_p (obj) +Return @code{#t} if @var{obj} is a string, else @code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_string (SCM obj) +Returns @code{1} if @var{obj} is a string, @code{0} otherwise. +@end deftypefn + +@deffn {Scheme Procedure} string-null? str +@deffnx {C Function} scm_string_null_p (str) +Return @code{#t} if @var{str}'s length is zero, and +@code{#f} otherwise. +@lisp +(string-null? "") @result{} #t +y @result{} "foo" +(string-null? y) @result{} #f +@end lisp +@end deffn + +@deffn {Scheme Procedure} string-any char_pred s [start [end]] +@deffnx {C Function} scm_string_any (char_pred, s, start, end) +Check if @var{char_pred} is true for any character in string @var{s}. + +@var{char_pred} can be a character to check for any equal to that, or +a character set (@pxref{Character Sets}) to check for any in that set, +or a predicate procedure to call. + +For a procedure, calls @code{(@var{char_pred} c)} are made +successively on the characters from @var{start} to @var{end}. If +@var{char_pred} returns true (ie.@: non-@code{#f}), @code{string-any} +stops and that return value is the return from @code{string-any}. The +call on the last character (ie.@: at @math{@var{end}-1}), if that +point is reached, is a tail call. + +If there are no characters in @var{s} (ie.@: @var{start} equals +@var{end}) then the return is @code{#f}. +@end deffn + +@deffn {Scheme Procedure} string-every char_pred s [start [end]] +@deffnx {C Function} scm_string_every (char_pred, s, start, end) +Check if @var{char_pred} is true for every character in string +@var{s}. + +@var{char_pred} can be a character to check for every character equal +to that, or a character set (@pxref{Character Sets}) to check for +every character being in that set, or a predicate procedure to call. + +For a procedure, calls @code{(@var{char_pred} c)} are made +successively on the characters from @var{start} to @var{end}. If +@var{char_pred} returns @code{#f}, @code{string-every} stops and +returns @code{#f}. The call on the last character (ie.@: at +@math{@var{end}-1}), if that point is reached, is a tail call and the +return from that call is the return from @code{string-every}. + +If there are no characters in @var{s} (ie.@: @var{start} equals +@var{end}) then the return is @code{#t}. +@end deffn + +@node String Constructors +@subsubsection String Constructors + +The string constructor procedures create new string objects, possibly +initializing them with some specified character data. See also +@xref{String Selection}, for ways to create strings from existing +strings. + +@c FIXME::martin: list->string belongs into `List/String Conversion' + +@deffn {Scheme Procedure} string char@dots{} +@rnindex string +Return a newly allocated string made from the given character +arguments. + +@example +(string #\x #\y #\z) @result{} "xyz" +(string) @result{} "" +@end example +@end deffn + +@deffn {Scheme Procedure} list->string lst +@deffnx {C Function} scm_string (lst) +@rnindex list->string +Return a newly allocated string made from a list of characters. + +@example +(list->string '(#\a #\b #\c)) @result{} "abc" +@end example +@end deffn + +@deffn {Scheme Procedure} reverse-list->string lst +@deffnx {C Function} scm_reverse_list_to_string (lst) +Return a newly allocated string made from a list of characters, in +reverse order. + +@example +(reverse-list->string '(#\a #\B #\c)) @result{} "cBa" +@end example +@end deffn + +@rnindex make-string +@deffn {Scheme Procedure} make-string k [chr] +@deffnx {C Function} scm_make_string (k, chr) +Return a newly allocated string of +length @var{k}. If @var{chr} is given, then all elements of +the string are initialized to @var{chr}, otherwise the contents +of the string are unspecified. +@end deffn + +@deftypefn {C Function} SCM scm_c_make_string (size_t len, SCM chr) +Like @code{scm_make_string}, but expects the length as a +@code{size_t}. +@end deftypefn + +@deffn {Scheme Procedure} string-tabulate proc len +@deffnx {C Function} scm_string_tabulate (proc, len) +@var{proc} is an integer->char procedure. Construct a string +of size @var{len} by applying @var{proc} to each index to +produce the corresponding string element. The order in which +@var{proc} is applied to the indices is not specified. +@end deffn + +@deffn {Scheme Procedure} string-join ls [delimiter [grammar]] +@deffnx {C Function} scm_string_join (ls, delimiter, grammar) +Append the string in the string list @var{ls}, using the string +@var{delimiter} as a delimiter between the elements of @var{ls}. +@var{grammar} is a symbol which specifies how the delimiter is +placed between the strings, and defaults to the symbol +@code{infix}. + +@table @code +@item infix +Insert the separator between list elements. An empty string +will produce an empty list. +@item strict-infix +Like @code{infix}, but will raise an error if given the empty +list. +@item suffix +Insert the separator after every list element. +@item prefix +Insert the separator before each list element. +@end table +@end deffn + +@node List/String Conversion +@subsubsection List/String conversion + +When processing strings, it is often convenient to first convert them +into a list representation by using the procedure @code{string->list}, +work with the resulting list, and then convert it back into a string. +These procedures are useful for similar tasks. + +@rnindex string->list +@deffn {Scheme Procedure} string->list str [start [end]] +@deffnx {C Function} scm_substring_to_list (str, start, end) +@deffnx {C Function} scm_string_to_list (str) +Convert the string @var{str} into a list of characters. +@end deffn + +@deffn {Scheme Procedure} string-split str char_pred +@deffnx {C Function} scm_string_split (str, char_pred) +Split the string @var{str} into a list of substrings delimited +by appearances of characters that + +@itemize @bullet +@item +equal @var{char_pred}, if it is a character, + +@item +satisfy the predicate @var{char_pred}, if it is a procedure, + +@item +are in the set @var{char_pred}, if it is a character set. +@end itemize + +Note that an empty substring between separator characters will result in +an empty string in the result list. + +@lisp +(string-split "root:x:0:0:root:/root:/bin/bash" #\:) +@result{} +("root" "x" "0" "0" "root" "/root" "/bin/bash") + +(string-split "::" #\:) +@result{} +("" "" "") + +(string-split "" #\:) +@result{} +("") +@end lisp +@end deffn + + +@node String Selection +@subsubsection String Selection + +Portions of strings can be extracted by these procedures. +@code{string-ref} delivers individual characters whereas +@code{substring} can be used to extract substrings from longer strings. + +@rnindex string-length +@deffn {Scheme Procedure} string-length string +@deffnx {C Function} scm_string_length (string) +Return the number of characters in @var{string}. +@end deffn + +@deftypefn {C Function} size_t scm_c_string_length (SCM str) +Return the number of characters in @var{str} as a @code{size_t}. +@end deftypefn + +@rnindex string-ref +@deffn {Scheme Procedure} string-ref str k +@deffnx {C Function} scm_string_ref (str, k) +Return character @var{k} of @var{str} using zero-origin +indexing. @var{k} must be a valid index of @var{str}. +@end deffn + +@deftypefn {C Function} SCM scm_c_string_ref (SCM str, size_t k) +Return character @var{k} of @var{str} using zero-origin +indexing. @var{k} must be a valid index of @var{str}. +@end deftypefn + +@rnindex string-copy +@deffn {Scheme Procedure} string-copy str [start [end]] +@deffnx {C Function} scm_substring_copy (str, start, end) +@deffnx {C Function} scm_string_copy (str) +Return a copy of the given string @var{str}. + +The returned string shares storage with @var{str} initially, but it is +copied as soon as one of the two strings is modified. +@end deffn + +@rnindex substring +@deffn {Scheme Procedure} substring str start [end] +@deffnx {C Function} scm_substring (str, start, end) +Return a new string formed from the characters +of @var{str} beginning with index @var{start} (inclusive) and +ending with index @var{end} (exclusive). +@var{str} must be a string, @var{start} and @var{end} must be +exact integers satisfying: + +0 <= @var{start} <= @var{end} <= @code{(string-length @var{str})}. + +The returned string shares storage with @var{str} initially, but it is +copied as soon as one of the two strings is modified. +@end deffn + +@deffn {Scheme Procedure} substring/shared str start [end] +@deffnx {C Function} scm_substring_shared (str, start, end) +Like @code{substring}, but the strings continue to share their storage +even if they are modified. Thus, modifications to @var{str} show up +in the new string, and vice versa. +@end deffn + +@deffn {Scheme Procedure} substring/copy str start [end] +@deffnx {C Function} scm_substring_copy (str, start, end) +Like @code{substring}, but the storage for the new string is copied +immediately. +@end deffn + +@deffn {Scheme Procedure} substring/read-only str start [end] +@deffnx {C Function} scm_substring_read_only (str, start, end) +Like @code{substring}, but the resulting string can not be modified. +@end deffn + +@deftypefn {C Function} SCM scm_c_substring (SCM str, size_t start, size_t end) +@deftypefnx {C Function} SCM scm_c_substring_shared (SCM str, size_t start, size_t end) +@deftypefnx {C Function} SCM scm_c_substring_copy (SCM str, size_t start, size_t end) +@deftypefnx {C Function} SCM scm_c_substring_read_only (SCM str, size_t start, size_t end) +Like @code{scm_substring}, etc. but the bounds are given as a @code{size_t}. +@end deftypefn + +@deffn {Scheme Procedure} string-take s n +@deffnx {C Function} scm_string_take (s, n) +Return the @var{n} first characters of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-drop s n +@deffnx {C Function} scm_string_drop (s, n) +Return all but the first @var{n} characters of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-take-right s n +@deffnx {C Function} scm_string_take_right (s, n) +Return the @var{n} last characters of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-drop-right s n +@deffnx {C Function} scm_string_drop_right (s, n) +Return all but the last @var{n} characters of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-pad s len [chr [start [end]]] +@deffnx {Scheme Procedure} string-pad-right s len [chr [start [end]]] +@deffnx {C Function} scm_string_pad (s, len, chr, start, end) +@deffnx {C Function} scm_string_pad_right (s, len, chr, start, end) +Take characters @var{start} to @var{end} from the string @var{s} and +either pad with @var{chr} or truncate them to give @var{len} +characters. + +@code{string-pad} pads or truncates on the left, so for example + +@example +(string-pad "x" 3) @result{} " x" +(string-pad "abcde" 3) @result{} "cde" +@end example + +@code{string-pad-right} pads or truncates on the right, so for example + +@example +(string-pad-right "x" 3) @result{} "x " +(string-pad-right "abcde" 3) @result{} "abc" +@end example +@end deffn + +@deffn {Scheme Procedure} string-trim s [char_pred [start [end]]] +@deffnx {Scheme Procedure} string-trim-right s [char_pred [start [end]]] +@deffnx {Scheme Procedure} string-trim-both s [char_pred [start [end]]] +@deffnx {C Function} scm_string_trim (s, char_pred, start, end) +@deffnx {C Function} scm_string_trim_right (s, char_pred, start, end) +@deffnx {C Function} scm_string_trim_both (s, char_pred, start, end) +Trim occurrences of @var{char_pred} from the ends of @var{s}. + +@code{string-trim} trims @var{char_pred} characters from the left +(start) of the string, @code{string-trim-right} trims them from the +right (end) of the string, @code{string-trim-both} trims from both +ends. + +@var{char_pred} can be a character, a character set, or a predicate +procedure to call on each character. If @var{char_pred} is not given +the default is whitespace as per @code{char-set:whitespace} +(@pxref{Standard Character Sets}). + +@example +(string-trim " x ") @result{} "x " +(string-trim-right "banana" #\a) @result{} "banan" +(string-trim-both ".,xy:;" char-set:punctuation) + @result{} "xy" +(string-trim-both "xyzzy" (lambda (c) + (or (eqv? c #\x) + (eqv? c #\y)))) + @result{} "zz" +@end example +@end deffn + +@node String Modification +@subsubsection String Modification + +These procedures are for modifying strings in-place. This means that the +result of the operation is not a new string; instead, the original string's +memory representation is modified. + +@rnindex string-set! +@deffn {Scheme Procedure} string-set! str k chr +@deffnx {C Function} scm_string_set_x (str, k, chr) +Store @var{chr} in element @var{k} of @var{str} and return +an unspecified value. @var{k} must be a valid index of +@var{str}. +@end deffn + +@deftypefn {C Function} void scm_c_string_set_x (SCM str, size_t k, SCM chr) +Like @code{scm_string_set_x}, but the index is given as a @code{size_t}. +@end deftypefn + +@rnindex string-fill! +@deffn {Scheme Procedure} string-fill! str chr [start [end]] +@deffnx {C Function} scm_substring_fill_x (str, chr, start, end) +@deffnx {C Function} scm_string_fill_x (str, chr) +Stores @var{chr} in every element of the given @var{str} and +returns an unspecified value. +@end deffn + +@deffn {Scheme Procedure} substring-fill! str start end fill +@deffnx {C Function} scm_substring_fill_x (str, start, end, fill) +Change every character in @var{str} between @var{start} and +@var{end} to @var{fill}. + +@lisp +(define y (string-copy "abcdefg")) +(substring-fill! y 1 3 #\r) +y +@result{} "arrdefg" +@end lisp +@end deffn + +@deffn {Scheme Procedure} substring-move! str1 start1 end1 str2 start2 +@deffnx {C Function} scm_substring_move_x (str1, start1, end1, str2, start2) +Copy the substring of @var{str1} bounded by @var{start1} and @var{end1} +into @var{str2} beginning at position @var{start2}. +@var{str1} and @var{str2} can be the same string. +@end deffn + +@deffn {Scheme Procedure} string-copy! target tstart s [start [end]] +@deffnx {C Function} scm_string_copy_x (target, tstart, s, start, end) +Copy the sequence of characters from index range [@var{start}, +@var{end}) in string @var{s} to string @var{target}, beginning +at index @var{tstart}. The characters are copied left-to-right +or right-to-left as needed -- the copy is guaranteed to work, +even if @var{target} and @var{s} are the same string. It is an +error if the copy operation runs off the end of the target +string. +@end deffn + + +@node String Comparison +@subsubsection String Comparison + +The procedures in this section are similar to the character ordering +predicates (@pxref{Characters}), but are defined on character sequences. + +The first set is specified in R5RS and has names that end in @code{?}. +The second set is specified in SRFI-13 and the names have not ending +@code{?}. + +The predicates ending in @code{-ci} ignore the character case +when comparing strings. For now, case-insensitive comparison is done +using the R5RS rules, where every lower-case character that has a +single character upper-case form is converted to uppercase before +comparison. See @xref{Text Collation, the @code{(ice-9 +i18n)} module}, for locale-dependent string comparison. + +@rnindex string=? +@deffn {Scheme Procedure} string=? s1 s2 s3 @dots{} +Lexicographic equality predicate; return @code{#t} if all strings are +the same length and contain the same characters in the same positions, +otherwise return @code{#f}. + +The procedure @code{string-ci=?} treats upper and lower case +letters as though they were the same character, but +@code{string=?} treats upper and lower case as distinct +characters. +@end deffn + +@rnindex string<? +@deffn {Scheme Procedure} string<? s1 s2 s3 @dots{} +Lexicographic ordering predicate; return @code{#t} if, for every pair of +consecutive string arguments @var{str_i} and @var{str_i+1}, @var{str_i} is +lexicographically less than @var{str_i+1}. +@end deffn + +@rnindex string<=? +@deffn {Scheme Procedure} string<=? s1 s2 s3 @dots{} +Lexicographic ordering predicate; return @code{#t} if, for every pair of +consecutive string arguments @var{str_i} and @var{str_i+1}, @var{str_i} is +lexicographically less than or equal to @var{str_i+1}. +@end deffn + +@rnindex string>? +@deffn {Scheme Procedure} string>? s1 s2 s3 @dots{} +Lexicographic ordering predicate; return @code{#t} if, for every pair of +consecutive string arguments @var{str_i} and @var{str_i+1}, @var{str_i} is +lexicographically greater than @var{str_i+1}. +@end deffn + +@rnindex string>=? +@deffn {Scheme Procedure} string>=? s1 s2 s3 @dots{} +Lexicographic ordering predicate; return @code{#t} if, for every pair of +consecutive string arguments @var{str_i} and @var{str_i+1}, @var{str_i} is +lexicographically greater than or equal to @var{str_i+1}. +@end deffn + +@rnindex string-ci=? +@deffn {Scheme Procedure} string-ci=? s1 s2 s3 @dots{} +Case-insensitive string equality predicate; return @code{#t} if +all strings are the same length and their component +characters match (ignoring case) at each position; otherwise +return @code{#f}. +@end deffn + +@rnindex string-ci<? +@deffn {Scheme Procedure} string-ci<? s1 s2 s3 @dots{} +Case insensitive lexicographic ordering predicate; return @code{#t} if, +for every pair of consecutive string arguments @var{str_i} and +@var{str_i+1}, @var{str_i} is lexicographically less than @var{str_i+1} +regardless of case. +@end deffn + +@rnindex string<=? +@deffn {Scheme Procedure} string-ci<=? s1 s2 s3 @dots{} +Case insensitive lexicographic ordering predicate; return @code{#t} if, +for every pair of consecutive string arguments @var{str_i} and +@var{str_i+1}, @var{str_i} is lexicographically less than or equal to +@var{str_i+1} regardless of case. +@end deffn + +@rnindex string-ci>? +@deffn {Scheme Procedure} string-ci>? s1 s2 s3 @dots{} +Case insensitive lexicographic ordering predicate; return @code{#t} if, +for every pair of consecutive string arguments @var{str_i} and +@var{str_i+1}, @var{str_i} is lexicographically greater than +@var{str_i+1} regardless of case. +@end deffn + +@rnindex string-ci>=? +@deffn {Scheme Procedure} string-ci>=? s1 s2 s3 @dots{} +Case insensitive lexicographic ordering predicate; return @code{#t} if, +for every pair of consecutive string arguments @var{str_i} and +@var{str_i+1}, @var{str_i} is lexicographically greater than or equal to +@var{str_i+1} regardless of case. +@end deffn + +@deffn {Scheme Procedure} string-compare s1 s2 proc_lt proc_eq proc_gt [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_compare (s1, s2, proc_lt, proc_eq, proc_gt, start1, end1, start2, end2) +Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the +mismatch index, depending upon whether @var{s1} is less than, +equal to, or greater than @var{s2}. The mismatch index is the +largest index @var{i} such that for every 0 <= @var{j} < +@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is, +@var{i} is the first position that does not match. +@end deffn + +@deffn {Scheme Procedure} string-compare-ci s1 s2 proc_lt proc_eq proc_gt [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_compare_ci (s1, s2, proc_lt, proc_eq, proc_gt, start1, end1, start2, end2) +Apply @var{proc_lt}, @var{proc_eq}, @var{proc_gt} to the +mismatch index, depending upon whether @var{s1} is less than, +equal to, or greater than @var{s2}. The mismatch index is the +largest index @var{i} such that for every 0 <= @var{j} < +@var{i}, @var{s1}[@var{j}] = @var{s2}[@var{j}] -- that is, +@var{i} is the first position where the lowercased letters +do not match. + +@end deffn + +@deffn {Scheme Procedure} string= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_eq (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} and @var{s2} are not equal, a true +value otherwise. +@end deffn + +@deffn {Scheme Procedure} string<> s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_neq (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} and @var{s2} are equal, a true +value otherwise. +@end deffn + +@deffn {Scheme Procedure} string< s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_lt (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a +true value otherwise. +@end deffn + +@deffn {Scheme Procedure} string> s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_gt (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is less or equal to @var{s2}, a +true value otherwise. +@end deffn + +@deffn {Scheme Procedure} string<= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_le (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is greater to @var{s2}, a true +value otherwise. +@end deffn + +@deffn {Scheme Procedure} string>= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ge (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is less to @var{s2}, a true value +otherwise. +@end deffn + +@deffn {Scheme Procedure} string-ci= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_eq (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} and @var{s2} are not equal, a true +value otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-ci<> s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_neq (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} and @var{s2} are equal, a true +value otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-ci< s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_lt (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is greater or equal to @var{s2}, a +true value otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-ci> s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_gt (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is less or equal to @var{s2}, a +true value otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-ci<= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_le (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is greater to @var{s2}, a true +value otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-ci>= s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_ci_ge (s1, s2, start1, end1, start2, end2) +Return @code{#f} if @var{s1} is less to @var{s2}, a true value +otherwise. The character comparison is done +case-insensitively. +@end deffn + +@deffn {Scheme Procedure} string-hash s [bound [start [end]]] +@deffnx {C Function} scm_substring_hash (s, bound, start, end) +Compute a hash value for @var{s}. The optional argument @var{bound} is a non-negative exact integer specifying the range of the hash function. A positive value restricts the return value to the range [0,bound). +@end deffn + +@deffn {Scheme Procedure} string-hash-ci s [bound [start [end]]] +@deffnx {C Function} scm_substring_hash_ci (s, bound, start, end) +Compute a hash value for @var{s}. The optional argument @var{bound} is a non-negative exact integer specifying the range of the hash function. A positive value restricts the return value to the range [0,bound). +@end deffn + +Because the same visual appearance of an abstract Unicode character can +be obtained via multiple sequences of Unicode characters, even the +case-insensitive string comparison functions described above may return +@code{#f} when presented with strings containing different +representations of the same character. For example, the Unicode +character ``LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE'' can be +represented with a single character (U+1E69) or by the character ``LATIN +SMALL LETTER S'' (U+0073) followed by the combining marks ``COMBINING +DOT BELOW'' (U+0323) and ``COMBINING DOT ABOVE'' (U+0307). + +For this reason, it is often desirable to ensure that the strings +to be compared are using a mutually consistent representation for every +character. The Unicode standard defines two methods of normalizing the +contents of strings: Decomposition, which breaks composite characters +into a set of constituent characters with an ordering defined by the +Unicode Standard; and composition, which performs the converse. + +There are two decomposition operations. ``Canonical decomposition'' +produces character sequences that share the same visual appearance as +the original characters, while ``compatibility decomposition'' produces +ones whose visual appearances may differ from the originals but which +represent the same abstract character. + +These operations are encapsulated in the following set of normalization +forms: + +@table @dfn +@item NFD +Characters are decomposed to their canonical forms. + +@item NFKD +Characters are decomposed to their compatibility forms. + +@item NFC +Characters are decomposed to their canonical forms, then composed. + +@item NFKC +Characters are decomposed to their compatibility forms, then composed. + +@end table + +The functions below put their arguments into one of the forms described +above. + +@deffn {Scheme Procedure} string-normalize-nfd s +@deffnx {C Function} scm_string_normalize_nfd (s) +Return the @code{NFD} normalized form of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-normalize-nfkd s +@deffnx {C Function} scm_string_normalize_nfkd (s) +Return the @code{NFKD} normalized form of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-normalize-nfc s +@deffnx {C Function} scm_string_normalize_nfc (s) +Return the @code{NFC} normalized form of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-normalize-nfkc s +@deffnx {C Function} scm_string_normalize_nfkc (s) +Return the @code{NFKC} normalized form of @var{s}. +@end deffn + +@node String Searching +@subsubsection String Searching + +@deffn {Scheme Procedure} string-index s char_pred [start [end]] +@deffnx {C Function} scm_string_index (s, char_pred, start, end) +Search through the string @var{s} from left to right, returning +the index of the first occurrence of a character which + +@itemize @bullet +@item +equals @var{char_pred}, if it is character, + +@item +satisfies the predicate @var{char_pred}, if it is a procedure, + +@item +is in the set @var{char_pred}, if it is a character set. +@end itemize + +Return @code{#f} if no match is found. +@end deffn + +@deffn {Scheme Procedure} string-rindex s char_pred [start [end]] +@deffnx {C Function} scm_string_rindex (s, char_pred, start, end) +Search through the string @var{s} from right to left, returning +the index of the last occurrence of a character which + +@itemize @bullet +@item +equals @var{char_pred}, if it is character, + +@item +satisfies the predicate @var{char_pred}, if it is a procedure, + +@item +is in the set if @var{char_pred} is a character set. +@end itemize + +Return @code{#f} if no match is found. +@end deffn + +@deffn {Scheme Procedure} string-prefix-length s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_prefix_length (s1, s2, start1, end1, start2, end2) +Return the length of the longest common prefix of the two +strings. +@end deffn + +@deffn {Scheme Procedure} string-prefix-length-ci s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_prefix_length_ci (s1, s2, start1, end1, start2, end2) +Return the length of the longest common prefix of the two +strings, ignoring character case. +@end deffn + +@deffn {Scheme Procedure} string-suffix-length s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_suffix_length (s1, s2, start1, end1, start2, end2) +Return the length of the longest common suffix of the two +strings. +@end deffn + +@deffn {Scheme Procedure} string-suffix-length-ci s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_suffix_length_ci (s1, s2, start1, end1, start2, end2) +Return the length of the longest common suffix of the two +strings, ignoring character case. +@end deffn + +@deffn {Scheme Procedure} string-prefix? s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_prefix_p (s1, s2, start1, end1, start2, end2) +Is @var{s1} a prefix of @var{s2}? +@end deffn + +@deffn {Scheme Procedure} string-prefix-ci? s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_prefix_ci_p (s1, s2, start1, end1, start2, end2) +Is @var{s1} a prefix of @var{s2}, ignoring character case? +@end deffn + +@deffn {Scheme Procedure} string-suffix? s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_suffix_p (s1, s2, start1, end1, start2, end2) +Is @var{s1} a suffix of @var{s2}? +@end deffn + +@deffn {Scheme Procedure} string-suffix-ci? s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_suffix_ci_p (s1, s2, start1, end1, start2, end2) +Is @var{s1} a suffix of @var{s2}, ignoring character case? +@end deffn + +@deffn {Scheme Procedure} string-index-right s char_pred [start [end]] +@deffnx {C Function} scm_string_index_right (s, char_pred, start, end) +Search through the string @var{s} from right to left, returning +the index of the last occurrence of a character which + +@itemize @bullet +@item +equals @var{char_pred}, if it is character, + +@item +satisfies the predicate @var{char_pred}, if it is a procedure, + +@item +is in the set if @var{char_pred} is a character set. +@end itemize + +Return @code{#f} if no match is found. +@end deffn + +@deffn {Scheme Procedure} string-skip s char_pred [start [end]] +@deffnx {C Function} scm_string_skip (s, char_pred, start, end) +Search through the string @var{s} from left to right, returning +the index of the first occurrence of a character which + +@itemize @bullet +@item +does not equal @var{char_pred}, if it is character, + +@item +does not satisfy the predicate @var{char_pred}, if it is a +procedure, + +@item +is not in the set if @var{char_pred} is a character set. +@end itemize +@end deffn + +@deffn {Scheme Procedure} string-skip-right s char_pred [start [end]] +@deffnx {C Function} scm_string_skip_right (s, char_pred, start, end) +Search through the string @var{s} from right to left, returning +the index of the last occurrence of a character which + +@itemize @bullet +@item +does not equal @var{char_pred}, if it is character, + +@item +does not satisfy the predicate @var{char_pred}, if it is a +procedure, + +@item +is not in the set if @var{char_pred} is a character set. +@end itemize +@end deffn + +@deffn {Scheme Procedure} string-count s char_pred [start [end]] +@deffnx {C Function} scm_string_count (s, char_pred, start, end) +Return the count of the number of characters in the string +@var{s} which + +@itemize @bullet +@item +equals @var{char_pred}, if it is character, + +@item +satisfies the predicate @var{char_pred}, if it is a procedure. + +@item +is in the set @var{char_pred}, if it is a character set. +@end itemize +@end deffn + +@deffn {Scheme Procedure} string-contains s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_contains (s1, s2, start1, end1, start2, end2) +Does string @var{s1} contain string @var{s2}? Return the index +in @var{s1} where @var{s2} occurs as a substring, or false. +The optional start/end indices restrict the operation to the +indicated substrings. +@end deffn + +@deffn {Scheme Procedure} string-contains-ci s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_contains_ci (s1, s2, start1, end1, start2, end2) +Does string @var{s1} contain string @var{s2}? Return the index +in @var{s1} where @var{s2} occurs as a substring, or false. +The optional start/end indices restrict the operation to the +indicated substrings. Character comparison is done +case-insensitively. +@end deffn + +@node Alphabetic Case Mapping +@subsubsection Alphabetic Case Mapping + +These are procedures for mapping strings to their upper- or lower-case +equivalents, respectively, or for capitalizing strings. + +They use the basic case mapping rules for Unicode characters. No +special language or context rules are considered. The resulting strings +are guaranteed to be the same length as the input strings. + +@xref{Character Case Mapping, the @code{(ice-9 +i18n)} module}, for locale-dependent case conversions. + +@deffn {Scheme Procedure} string-upcase str [start [end]] +@deffnx {C Function} scm_substring_upcase (str, start, end) +@deffnx {C Function} scm_string_upcase (str) +Upcase every character in @code{str}. +@end deffn + +@deffn {Scheme Procedure} string-upcase! str [start [end]] +@deffnx {C Function} scm_substring_upcase_x (str, start, end) +@deffnx {C Function} scm_string_upcase_x (str) +Destructively upcase every character in @code{str}. + +@lisp +(string-upcase! y) +@result{} "ARRDEFG" +y +@result{} "ARRDEFG" +@end lisp +@end deffn + +@deffn {Scheme Procedure} string-downcase str [start [end]] +@deffnx {C Function} scm_substring_downcase (str, start, end) +@deffnx {C Function} scm_string_downcase (str) +Downcase every character in @var{str}. +@end deffn + +@deffn {Scheme Procedure} string-downcase! str [start [end]] +@deffnx {C Function} scm_substring_downcase_x (str, start, end) +@deffnx {C Function} scm_string_downcase_x (str) +Destructively downcase every character in @var{str}. + +@lisp +y +@result{} "ARRDEFG" +(string-downcase! y) +@result{} "arrdefg" +y +@result{} "arrdefg" +@end lisp +@end deffn + +@deffn {Scheme Procedure} string-capitalize str +@deffnx {C Function} scm_string_capitalize (str) +Return a freshly allocated string with the characters in +@var{str}, where the first character of every word is +capitalized. +@end deffn + +@deffn {Scheme Procedure} string-capitalize! str +@deffnx {C Function} scm_string_capitalize_x (str) +Upcase the first character of every word in @var{str} +destructively and return @var{str}. + +@lisp +y @result{} "hello world" +(string-capitalize! y) @result{} "Hello World" +y @result{} "Hello World" +@end lisp +@end deffn + +@deffn {Scheme Procedure} string-titlecase str [start [end]] +@deffnx {C Function} scm_string_titlecase (str, start, end) +Titlecase every first character in a word in @var{str}. +@end deffn + +@deffn {Scheme Procedure} string-titlecase! str [start [end]] +@deffnx {C Function} scm_string_titlecase_x (str, start, end) +Destructively titlecase every first character in a word in +@var{str}. +@end deffn + +@node Reversing and Appending Strings +@subsubsection Reversing and Appending Strings + +@deffn {Scheme Procedure} string-reverse str [start [end]] +@deffnx {C Function} scm_string_reverse (str, start, end) +Reverse the string @var{str}. The optional arguments +@var{start} and @var{end} delimit the region of @var{str} to +operate on. +@end deffn + +@deffn {Scheme Procedure} string-reverse! str [start [end]] +@deffnx {C Function} scm_string_reverse_x (str, start, end) +Reverse the string @var{str} in-place. The optional arguments +@var{start} and @var{end} delimit the region of @var{str} to +operate on. The return value is unspecified. +@end deffn + +@rnindex string-append +@deffn {Scheme Procedure} string-append arg @dots{} +@deffnx {C Function} scm_string_append (args) +Return a newly allocated string whose characters form the +concatenation of the given strings, @var{arg} @enddots{}. + +@example +(let ((h "hello ")) + (string-append h "world")) +@result{} "hello world" +@end example +@end deffn + +@deffn {Scheme Procedure} string-append/shared arg @dots{} +@deffnx {C Function} scm_string_append_shared (args) +Like @code{string-append}, but the result may share memory +with the argument strings. +@end deffn + +@deffn {Scheme Procedure} string-concatenate ls +@deffnx {C Function} scm_string_concatenate (ls) +Append the elements (which must be strings) of @var{ls} together into a +single string. Guaranteed to return a freshly allocated string. +@end deffn + +@deffn {Scheme Procedure} string-concatenate-reverse ls [final_string [end]] +@deffnx {C Function} scm_string_concatenate_reverse (ls, final_string, end) +Without optional arguments, this procedure is equivalent to + +@lisp +(string-concatenate (reverse ls)) +@end lisp + +If the optional argument @var{final_string} is specified, it is +consed onto the beginning to @var{ls} before performing the +list-reverse and string-concatenate operations. If @var{end} +is given, only the characters of @var{final_string} up to index +@var{end} are used. + +Guaranteed to return a freshly allocated string. +@end deffn + +@deffn {Scheme Procedure} string-concatenate/shared ls +@deffnx {C Function} scm_string_concatenate_shared (ls) +Like @code{string-concatenate}, but the result may share memory +with the strings in the list @var{ls}. +@end deffn + +@deffn {Scheme Procedure} string-concatenate-reverse/shared ls [final_string [end]] +@deffnx {C Function} scm_string_concatenate_reverse_shared (ls, final_string, end) +Like @code{string-concatenate-reverse}, but the result may +share memory with the strings in the @var{ls} arguments. +@end deffn + +@node Mapping Folding and Unfolding +@subsubsection Mapping, Folding, and Unfolding + +@deffn {Scheme Procedure} string-map proc s [start [end]] +@deffnx {C Function} scm_string_map (proc, s, start, end) +@var{proc} is a char->char procedure, it is mapped over +@var{s}. The order in which the procedure is applied to the +string elements is not specified. +@end deffn + +@deffn {Scheme Procedure} string-map! proc s [start [end]] +@deffnx {C Function} scm_string_map_x (proc, s, start, end) +@var{proc} is a char->char procedure, it is mapped over +@var{s}. The order in which the procedure is applied to the +string elements is not specified. The string @var{s} is +modified in-place, the return value is not specified. +@end deffn + +@deffn {Scheme Procedure} string-for-each proc s [start [end]] +@deffnx {C Function} scm_string_for_each (proc, s, start, end) +@var{proc} is mapped over @var{s} in left-to-right order. The +return value is not specified. +@end deffn + +@deffn {Scheme Procedure} string-for-each-index proc s [start [end]] +@deffnx {C Function} scm_string_for_each_index (proc, s, start, end) +Call @code{(@var{proc} i)} for each index i in @var{s}, from left to +right. + +For example, to change characters to alternately upper and lower case, + +@example +(define str (string-copy "studly")) +(string-for-each-index + (lambda (i) + (string-set! str i + ((if (even? i) char-upcase char-downcase) + (string-ref str i)))) + str) +str @result{} "StUdLy" +@end example +@end deffn + +@deffn {Scheme Procedure} string-fold kons knil s [start [end]] +@deffnx {C Function} scm_string_fold (kons, knil, s, start, end) +Fold @var{kons} over the characters of @var{s}, with @var{knil} +as the terminating element, from left to right. @var{kons} +must expect two arguments: The actual character and the last +result of @var{kons}' application. +@end deffn + +@deffn {Scheme Procedure} string-fold-right kons knil s [start [end]] +@deffnx {C Function} scm_string_fold_right (kons, knil, s, start, end) +Fold @var{kons} over the characters of @var{s}, with @var{knil} +as the terminating element, from right to left. @var{kons} +must expect two arguments: The actual character and the last +result of @var{kons}' application. +@end deffn + +@deffn {Scheme Procedure} string-unfold p f g seed [base [make_final]] +@deffnx {C Function} scm_string_unfold (p, f, g, seed, base, make_final) +@itemize @bullet +@item @var{g} is used to generate a series of @emph{seed} +values from the initial @var{seed}: @var{seed}, (@var{g} +@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), +@dots{} +@item @var{p} tells us when to stop -- when it returns true +when applied to one of these seed values. +@item @var{f} maps each seed value to the corresponding +character in the result string. These chars are assembled +into the string in a left-to-right order. +@item @var{base} is the optional initial/leftmost portion +of the constructed string; it default to the empty +string. +@item @var{make_final} is applied to the terminal seed +value (on which @var{p} returns true) to produce +the final/rightmost portion of the constructed string. +The default is nothing extra. +@end itemize +@end deffn + +@deffn {Scheme Procedure} string-unfold-right p f g seed [base [make_final]] +@deffnx {C Function} scm_string_unfold_right (p, f, g, seed, base, make_final) +@itemize @bullet +@item @var{g} is used to generate a series of @emph{seed} +values from the initial @var{seed}: @var{seed}, (@var{g} +@var{seed}), (@var{g}^2 @var{seed}), (@var{g}^3 @var{seed}), +@dots{} +@item @var{p} tells us when to stop -- when it returns true +when applied to one of these seed values. +@item @var{f} maps each seed value to the corresponding +character in the result string. These chars are assembled +into the string in a right-to-left order. +@item @var{base} is the optional initial/rightmost portion +of the constructed string; it default to the empty +string. +@item @var{make_final} is applied to the terminal seed +value (on which @var{p} returns true) to produce +the final/leftmost portion of the constructed string. +It defaults to @code{(lambda (x) )}. +@end itemize +@end deffn + +@node Miscellaneous String Operations +@subsubsection Miscellaneous String Operations + +@deffn {Scheme Procedure} xsubstring s from [to [start [end]]] +@deffnx {C Function} scm_xsubstring (s, from, to, start, end) +This is the @emph{extended substring} procedure that implements +replicated copying of a substring of some string. + +@var{s} is a string, @var{start} and @var{end} are optional +arguments that demarcate a substring of @var{s}, defaulting to +0 and the length of @var{s}. Replicate this substring up and +down index space, in both the positive and negative directions. +@code{xsubstring} returns the substring of this string +beginning at index @var{from}, and ending at @var{to}, which +defaults to @var{from} + (@var{end} - @var{start}). +@end deffn + +@deffn {Scheme Procedure} string-xcopy! target tstart s sfrom [sto [start [end]]] +@deffnx {C Function} scm_string_xcopy_x (target, tstart, s, sfrom, sto, start, end) +Exactly the same as @code{xsubstring}, but the extracted text +is written into the string @var{target} starting at index +@var{tstart}. The operation is not defined if @code{(eq? +@var{target} @var{s})} or these arguments share storage -- you +cannot copy a string on top of itself. +@end deffn + +@deffn {Scheme Procedure} string-replace s1 s2 [start1 [end1 [start2 [end2]]]] +@deffnx {C Function} scm_string_replace (s1, s2, start1, end1, start2, end2) +Return the string @var{s1}, but with the characters +@var{start1} @dots{} @var{end1} replaced by the characters +@var{start2} @dots{} @var{end2} from @var{s2}. +@end deffn + +@deffn {Scheme Procedure} string-tokenize s [token_set [start [end]]] +@deffnx {C Function} scm_string_tokenize (s, token_set, start, end) +Split the string @var{s} into a list of substrings, where each +substring is a maximal non-empty contiguous sequence of +characters from the character set @var{token_set}, which +defaults to @code{char-set:graphic}. +If @var{start} or @var{end} indices are provided, they restrict +@code{string-tokenize} to operating on the indicated substring +of @var{s}. +@end deffn + +@deffn {Scheme Procedure} string-filter char_pred s [start [end]] +@deffnx {C Function} scm_string_filter (char_pred, s, start, end) +Filter the string @var{s}, retaining only those characters which +satisfy @var{char_pred}. + +If @var{char_pred} is a procedure, it is applied to each character as +a predicate, if it is a character, it is tested for equality and if it +is a character set, it is tested for membership. +@end deffn + +@deffn {Scheme Procedure} string-delete char_pred s [start [end]] +@deffnx {C Function} scm_string_delete (char_pred, s, start, end) +Delete characters satisfying @var{char_pred} from @var{s}. + +If @var{char_pred} is a procedure, it is applied to each character as +a predicate, if it is a character, it is tested for equality and if it +is a character set, it is tested for membership. +@end deffn + +@node Representing Strings as Bytes +@subsubsection Representing Strings as Bytes + +Out in the cold world outside of Guile, not all strings are treated in +the same way. Out there there are only bytes, and there are many ways +of representing a strings (sequences of characters) as binary data +(sequences of bytes). + +As a user, usually you don't have to think about this very much. When +you type on your keyboard, your system encodes your keystrokes as bytes +according to the locale that you have configured on your computer. +Guile uses the locale to decode those bytes back into characters -- +hopefully the same characters that you typed in. + +All is not so clear when dealing with a system with multiple users, such +as a web server. Your web server might get a request from one user for +data encoded in the ISO-8859-1 character set, and then another request +from a different user for UTF-8 data. + +@cindex iconv +@cindex character encoding +Guile provides an @dfn{iconv} module for converting between strings and +sequences of bytes. @xref{Bytevectors}, for more on how Guile +represents raw byte sequences. This module gets its name from the +common @sc{unix} command of the same name. + +Note that often it is sufficient to just read and write strings from +ports instead of using these functions. To do this, specify the port +encoding using @code{set-port-encoding!}. @xref{Ports}, for more on +ports and character encodings. + +Unlike the rest of the procedures in this section, you have to load the +@code{iconv} module before having access to these procedures: + +@example +(use-modules (ice-9 iconv)) +@end example + +@deffn {Scheme Procedure} string->bytevector string encoding [conversion-strategy] +Encode @var{string} as a sequence of bytes. + +The string will be encoded in the character set specified by the +@var{encoding} string. If the string has characters that cannot be +represented in the encoding, by default this procedure raises an +@code{encoding-error}. Pass a @var{conversion-strategy} argument to +specify other behaviors. + +The return value is a bytevector. @xref{Bytevectors}, for more on +bytevectors. @xref{Ports}, for more on character encodings and +conversion strategies. +@end deffn + +@deffn {Scheme Procedure} bytevector->string bytevector encoding [conversion-strategy] +Decode @var{bytevector} into a string. + +The bytes will be decoded from the character set by the @var{encoding} +string. If the bytes do not form a valid encoding, by default this +procedure raises an @code{decoding-error}. As with +@code{string->bytevector}, pass the optional @var{conversion-strategy} +argument to modify this behavior. @xref{Ports}, for more on character +encodings and conversion strategies. +@end deffn + +@deffn {Scheme Procedure} call-with-output-encoded-string encoding proc [conversion-strategy] +Like @code{call-with-output-string}, but instead of returning a string, +returns a encoding of the string according to @var{encoding}, as a +bytevector. This procedure can be more efficient than collecting a +string and then converting it via @code{string->bytevector}. +@end deffn + +@node Conversion to/from C +@subsubsection Conversion to/from C + +When creating a Scheme string from a C string or when converting a +Scheme string to a C string, the concept of character encoding becomes +important. + +In C, a string is just a sequence of bytes, and the character encoding +describes the relation between these bytes and the actual characters +that make up the string. For Scheme strings, character encoding is not +an issue (most of the time), since in Scheme you usually treat strings +as character sequences, not byte sequences. + +Converting to C and converting from C each have their own challenges. + +When converting from C to Scheme, it is important that the sequence of +bytes in the C string be valid with respect to its encoding. ASCII +strings, for example, can't have any bytes greater than 127. An ASCII +byte greater than 127 is considered @emph{ill-formed} and cannot be +converted into a Scheme character. + +Problems can occur in the reverse operation as well. Not all character +encodings can hold all possible Scheme characters. Some encodings, like +ASCII for example, can only describe a small subset of all possible +characters. So, when converting to C, one must first decide what to do +with Scheme characters that can't be represented in the C string. + +Converting a Scheme string to a C string will often allocate fresh +memory to hold the result. You must take care that this memory is +properly freed eventually. In many cases, this can be achieved by +using @code{scm_dynwind_free} inside an appropriate dynwind context, +@xref{Dynamic Wind}. + +@deftypefn {C Function} SCM scm_from_locale_string (const char *str) +@deftypefnx {C Function} SCM scm_from_locale_stringn (const char *str, size_t len) +Creates a new Scheme string that has the same contents as @var{str} when +interpreted in the character encoding of the current locale. + +For @code{scm_from_locale_string}, @var{str} must be null-terminated. + +For @code{scm_from_locale_stringn}, @var{len} specifies the length of +@var{str} in bytes, and @var{str} does not need to be null-terminated. +If @var{len} is @code{(size_t)-1}, then @var{str} does need to be +null-terminated and the real length will be found with @code{strlen}. + +If the C string is ill-formed, an error will be raised. + +Note that these functions should @emph{not} be used to convert C string +constants, because there is no guarantee that the current locale will +match that of the execution character set, used for string and character +constants. Most modern C compilers use UTF-8 by default, so to convert +C string constants we recommend @code{scm_from_utf8_string}. +@end deftypefn + +@deftypefn {C Function} SCM scm_take_locale_string (char *str) +@deftypefnx {C Function} SCM scm_take_locale_stringn (char *str, size_t len) +Like @code{scm_from_locale_string} and @code{scm_from_locale_stringn}, +respectively, but also frees @var{str} with @code{free} eventually. +Thus, you can use this function when you would free @var{str} anyway +immediately after creating the Scheme string. In certain cases, Guile +can then use @var{str} directly as its internal representation. +@end deftypefn + +@deftypefn {C Function} {char *} scm_to_locale_string (SCM str) +@deftypefnx {C Function} {char *} scm_to_locale_stringn (SCM str, size_t *lenp) +Returns a C string with the same contents as @var{str} in the character +encoding of the current locale. The C string must be freed with +@code{free} eventually, maybe by using @code{scm_dynwind_free}, +@xref{Dynamic Wind}. + +For @code{scm_to_locale_string}, the returned string is +null-terminated and an error is signalled when @var{str} contains +@code{#\nul} characters. + +For @code{scm_to_locale_stringn} and @var{lenp} not @code{NULL}, +@var{str} might contain @code{#\nul} characters and the length of the +returned string in bytes is stored in @code{*@var{lenp}}. The +returned string will not be null-terminated in this case. If +@var{lenp} is @code{NULL}, @code{scm_to_locale_stringn} behaves like +@code{scm_to_locale_string}. + +If a character in @var{str} cannot be represented in the character +encoding of the current locale, the default port conversion strategy is +used. @xref{Ports}, for more on conversion strategies. + +If the conversion strategy is @code{error}, an error will be raised. If +it is @code{substitute}, a replacement character, such as a question +mark, will be inserted in its place. If it is @code{escape}, a hex +escape will be inserted in its place. +@end deftypefn + +@deftypefn {C Function} size_t scm_to_locale_stringbuf (SCM str, char *buf, size_t max_len) +Puts @var{str} as a C string in the current locale encoding into the +memory pointed to by @var{buf}. The buffer at @var{buf} has room for +@var{max_len} bytes and @code{scm_to_local_stringbuf} will never store +more than that. No terminating @code{'\0'} will be stored. + +The return value of @code{scm_to_locale_stringbuf} is the number of +bytes that are needed for all of @var{str}, regardless of whether +@var{buf} was large enough to hold them. Thus, when the return value +is larger than @var{max_len}, only @var{max_len} bytes have been +stored and you probably need to try again with a larger buffer. +@end deftypefn + +For most situations, string conversion should occur using the current +locale, such as with the functions above. But there may be cases where +one wants to convert strings from a character encoding other than the +locale's character encoding. For these cases, the lower-level functions +@code{scm_to_stringn} and @code{scm_from_stringn} are provided. These +functions should seldom be necessary if one is properly using locales. + +@deftp {C Type} scm_t_string_failed_conversion_handler +This is an enumerated type that can take one of three values: +@code{SCM_FAILED_CONVERSION_ERROR}, +@code{SCM_FAILED_CONVERSION_QUESTION_MARK}, and +@code{SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE}. They are used to indicate +a strategy for handling characters that cannot be converted to or from a +given character encoding. @code{SCM_FAILED_CONVERSION_ERROR} indicates +that a conversion should throw an error if some characters cannot be +converted. @code{SCM_FAILED_CONVERSION_QUESTION_MARK} indicates that a +conversion should replace unconvertable characters with the question +mark character. And, @code{SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE} +requests that a conversion should replace an unconvertable character +with an escape sequence. + +While all three strategies apply when converting Scheme strings to C, +only @code{SCM_FAILED_CONVERSION_ERROR} and +@code{SCM_FAILED_CONVERSION_QUESTION_MARK} can be used when converting C +strings to Scheme. +@end deftp + +@deftypefn {C Function} char *scm_to_stringn (SCM str, size_t *lenp, const char *encoding, scm_t_string_failed_conversion_handler handler) +This function returns a newly allocated C string from the Guile string +@var{str}. The length of the returned string in bytes will be returned in +@var{lenp}. The character encoding of the C string is passed as the ASCII, +null-terminated C string @var{encoding}. The @var{handler} parameter +gives a strategy for dealing with characters that cannot be converted +into @var{encoding}. + +If @var{lenp} is @code{NULL}, this function will return a null-terminated C +string. It will throw an error if the string contains a null +character. + +The Scheme interface to this function is @code{string->bytevector}, from the +@code{ice-9 iconv} module. @xref{Representing Strings as Bytes}. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_stringn (const char *str, size_t len, const char *encoding, scm_t_string_failed_conversion_handler handler) +This function returns a scheme string from the C string @var{str}. The +length in bytes of the C string is input as @var{len}. The encoding of the C +string is passed as the ASCII, null-terminated C string @code{encoding}. +The @var{handler} parameters suggests a strategy for dealing with +unconvertable characters. + +The Scheme interface to this function is @code{bytevector->string}. +@xref{Representing Strings as Bytes}. +@end deftypefn + +The following conversion functions are provided as a convenience for the +most commonly used encodings. + +@deftypefn {C Function} SCM scm_from_latin1_string (const char *str) +@deftypefnx {C Function} SCM scm_from_utf8_string (const char *str) +@deftypefnx {C Function} SCM scm_from_utf32_string (const scm_t_wchar *str) +Return a scheme string from the null-terminated C string @var{str}, +which is ISO-8859-1-, UTF-8-, or UTF-32-encoded. These functions should +be used to convert hard-coded C string constants into Scheme strings. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_latin1_stringn (const char *str, size_t len) +@deftypefnx {C Function} SCM scm_from_utf8_stringn (const char *str, size_t len) +@deftypefnx {C Function} SCM scm_from_utf32_stringn (const scm_t_wchar *str, size_t len) +Return a scheme string from C string @var{str}, which is ISO-8859-1-, +UTF-8-, or UTF-32-encoded, of length @var{len}. @var{len} is the number +of bytes pointed to by @var{str} for @code{scm_from_latin1_stringn} and +@code{scm_from_utf8_stringn}; it is the number of elements (code points) +in @var{str} in the case of @code{scm_from_utf32_stringn}. +@end deftypefn + +@deftypefn {C function} char *scm_to_latin1_stringn (SCM str, size_t *lenp) +@deftypefnx {C function} char *scm_to_utf8_stringn (SCM str, size_t *lenp) +@deftypefnx {C function} scm_t_wchar *scm_to_utf32_stringn (SCM str, size_t *lenp) +Return a newly allocated, ISO-8859-1-, UTF-8-, or UTF-32-encoded C string +from Scheme string @var{str}. An error is thrown when @var{str} +cannot be converted to the specified encoding. If @var{lenp} is +@code{NULL}, the returned C string will be null terminated, and an error +will be thrown if the C string would otherwise contain null +characters. If @var{lenp} is not @code{NULL}, the string is not null terminated, +and the length of the returned string is returned in @var{lenp}. The length +returned is the number of bytes for @code{scm_to_latin1_stringn} and +@code{scm_to_utf8_stringn}; it is the number of elements (code points) +for @code{scm_to_utf32_stringn}. +@end deftypefn + +It is not often the case, but sometimes when you are dealing with the +implementation details of a port, you need to encode and decode strings +according to the encoding and conversion strategy of the port. There +are some convenience functions for that purpose as well. + +@deftypefn {C Function} SCM scm_from_port_string (const char *str, SCM port) +@deftypefnx {C Function} SCM scm_from_port_stringn (const char *str, size_t len, SCM port) +@deftypefnx {C Function} char* scm_to_port_string (SCM str, SCM port) +@deftypefnx {C Function} char* scm_to_port_stringn (SCM str, size_t *lenp, SCM port) +Like @code{scm_from_stringn} and friends, except they take their +encoding and conversion strategy from a given port object. +@end deftypefn + +@node String Internals +@subsubsection String Internals + +Guile stores each string in memory as a contiguous array of Unicode code +points along with an associated set of attributes. If all of the code +points of a string have an integer range between 0 and 255 inclusive, +the code point array is stored as one byte per code point: it is stored +as an ISO-8859-1 (aka Latin-1) string. If any of the code points of the +string has an integer value greater that 255, the code point array is +stored as four bytes per code point: it is stored as a UTF-32 string. + +Conversion between the one-byte-per-code-point and +four-bytes-per-code-point representations happens automatically as +necessary. + +No API is provided to set the internal representation of strings; +however, there are pair of procedures available to query it. These are +debugging procedures. Using them in production code is discouraged, +since the details of Guile's internal representation of strings may +change from release to release. + +@deffn {Scheme Procedure} string-bytes-per-char str +@deffnx {C Function} scm_string_bytes_per_char (str) +Return the number of bytes used to encode a Unicode code point in string +@var{str}. The result is one or four. +@end deffn + +@deffn {Scheme Procedure} %string-dump str +@deffnx {C Function} scm_sys_string_dump (str) +Returns an association list containing debugging information for +@var{str}. The association list has the following entries. +@table @code + +@item string +The string itself. + +@item start +The start index of the string into its stringbuf + +@item length +The length of the string + +@item shared +If this string is a substring, it returns its +parent string. Otherwise, it returns @code{#f} + +@item read-only +@code{#t} if the string is read-only + +@item stringbuf-chars +A new string containing this string's stringbuf's characters + +@item stringbuf-length +The number of characters in this stringbuf + +@item stringbuf-shared +@code{#t} if this stringbuf is shared + +@item stringbuf-wide +@code{#t} if this stringbuf's characters are stored in a 32-bit buffer, +or @code{#f} if they are stored in an 8-bit buffer +@end table +@end deffn + + +@node Symbols +@subsection Symbols +@tpindex Symbols + +Symbols in Scheme are widely used in three ways: as items of discrete +data, as lookup keys for alists and hash tables, and to denote variable +references. + +A @dfn{symbol} is similar to a string in that it is defined by a +sequence of characters. The sequence of characters is known as the +symbol's @dfn{name}. In the usual case --- that is, where the symbol's +name doesn't include any characters that could be confused with other +elements of Scheme syntax --- a symbol is written in a Scheme program by +writing the sequence of characters that make up the name, @emph{without} +any quotation marks or other special syntax. For example, the symbol +whose name is ``multiply-by-2'' is written, simply: + +@lisp +multiply-by-2 +@end lisp + +Notice how this differs from a @emph{string} with contents +``multiply-by-2'', which is written with double quotation marks, like +this: + +@lisp +"multiply-by-2" +@end lisp + +Looking beyond how they are written, symbols are different from strings +in two important respects. + +The first important difference is uniqueness. If the same-looking +string is read twice from two different places in a program, the result +is two @emph{different} string objects whose contents just happen to be +the same. If, on the other hand, the same-looking symbol is read twice +from two different places in a program, the result is the @emph{same} +symbol object both times. + +Given two read symbols, you can use @code{eq?} to test whether they are +the same (that is, have the same name). @code{eq?} is the most +efficient comparison operator in Scheme, and comparing two symbols like +this is as fast as comparing, for example, two numbers. Given two +strings, on the other hand, you must use @code{equal?} or +@code{string=?}, which are much slower comparison operators, to +determine whether the strings have the same contents. + +@lisp +(define sym1 (quote hello)) +(define sym2 (quote hello)) +(eq? sym1 sym2) @result{} #t + +(define str1 "hello") +(define str2 "hello") +(eq? str1 str2) @result{} #f +(equal? str1 str2) @result{} #t +@end lisp + +The second important difference is that symbols, unlike strings, are not +self-evaluating. This is why we need the @code{(quote @dots{})}s in the +example above: @code{(quote hello)} evaluates to the symbol named +"hello" itself, whereas an unquoted @code{hello} is @emph{read} as the +symbol named "hello" and evaluated as a variable reference @dots{} about +which more below (@pxref{Symbol Variables}). + +@menu +* Symbol Data:: Symbols as discrete data. +* Symbol Keys:: Symbols as lookup keys. +* Symbol Variables:: Symbols as denoting variables. +* Symbol Primitives:: Operations related to symbols. +* Symbol Props:: Function slots and property lists. +* Symbol Read Syntax:: Extended read syntax for symbols. +* Symbol Uninterned:: Uninterned symbols. +@end menu + + +@node Symbol Data +@subsubsection Symbols as Discrete Data + +Numbers and symbols are similar to the extent that they both lend +themselves to @code{eq?} comparison. But symbols are more descriptive +than numbers, because a symbol's name can be used directly to describe +the concept for which that symbol stands. + +For example, imagine that you need to represent some colours in a +computer program. Using numbers, you would have to choose arbitrarily +some mapping between numbers and colours, and then take care to use that +mapping consistently: + +@lisp +;; 1=red, 2=green, 3=purple + +(if (eq? (colour-of vehicle) 1) + ...) +@end lisp + +@noindent +You can make the mapping more explicit and the code more readable by +defining constants: + +@lisp +(define red 1) +(define green 2) +(define purple 3) + +(if (eq? (colour-of vehicle) red) + ...) +@end lisp + +@noindent +But the simplest and clearest approach is not to use numbers at all, but +symbols whose names specify the colours that they refer to: + +@lisp +(if (eq? (colour-of vehicle) 'red) + ...) +@end lisp + +The descriptive advantages of symbols over numbers increase as the set +of concepts that you want to describe grows. Suppose that a car object +can have other properties as well, such as whether it has or uses: + +@itemize @bullet +@item +automatic or manual transmission +@item +leaded or unleaded fuel +@item +power steering (or not). +@end itemize + +@noindent +Then a car's combined property set could be naturally represented and +manipulated as a list of symbols: + +@lisp +(properties-of vehicle1) +@result{} +(red manual unleaded power-steering) + +(if (memq 'power-steering (properties-of vehicle1)) + (display "Unfit people can drive this vehicle.\n") + (display "You'll need strong arms to drive this vehicle!\n")) +@print{} +Unfit people can drive this vehicle. +@end lisp + +Remember, the fundamental property of symbols that we are relying on +here is that an occurrence of @code{'red} in one part of a program is an +@emph{indistinguishable} symbol from an occurrence of @code{'red} in +another part of a program; this means that symbols can usefully be +compared using @code{eq?}. At the same time, symbols have naturally +descriptive names. This combination of efficiency and descriptive power +makes them ideal for use as discrete data. + + +@node Symbol Keys +@subsubsection Symbols as Lookup Keys + +Given their efficiency and descriptive power, it is natural to use +symbols as the keys in an association list or hash table. + +To illustrate this, consider a more structured representation of the car +properties example from the preceding subsection. Rather than +mixing all the properties up together in a flat list, we could use an +association list like this: + +@lisp +(define car1-properties '((colour . red) + (transmission . manual) + (fuel . unleaded) + (steering . power-assisted))) +@end lisp + +Notice how this structure is more explicit and extensible than the flat +list. For example it makes clear that @code{manual} refers to the +transmission rather than, say, the windows or the locking of the car. +It also allows further properties to use the same symbols among their +possible values without becoming ambiguous: + +@lisp +(define car1-properties '((colour . red) + (transmission . manual) + (fuel . unleaded) + (steering . power-assisted) + (seat-colour . red) + (locking . manual))) +@end lisp + +With a representation like this, it is easy to use the efficient +@code{assq-XXX} family of procedures (@pxref{Association Lists}) to +extract or change individual pieces of information: + +@lisp +(assq-ref car1-properties 'fuel) @result{} unleaded +(assq-ref car1-properties 'transmission) @result{} manual + +(assq-set! car1-properties 'seat-colour 'black) +@result{} +((colour . red) + (transmission . manual) + (fuel . unleaded) + (steering . power-assisted) + (seat-colour . black) + (locking . manual))) +@end lisp + +Hash tables also have keys, and exactly the same arguments apply to the +use of symbols in hash tables as in association lists. The hash value +that Guile uses to decide where to add a symbol-keyed entry to a hash +table can be obtained by calling the @code{symbol-hash} procedure: + +@deffn {Scheme Procedure} symbol-hash symbol +@deffnx {C Function} scm_symbol_hash (symbol) +Return a hash value for @var{symbol}. +@end deffn + +See @ref{Hash Tables} for information about hash tables in general, and +for why you might choose to use a hash table rather than an association +list. + + +@node Symbol Variables +@subsubsection Symbols as Denoting Variables + +When an unquoted symbol in a Scheme program is evaluated, it is +interpreted as a variable reference, and the result of the evaluation is +the appropriate variable's value. + +For example, when the expression @code{(string-length "abcd")} is read +and evaluated, the sequence of characters @code{string-length} is read +as the symbol whose name is "string-length". This symbol is associated +with a variable whose value is the procedure that implements string +length calculation. Therefore evaluation of the @code{string-length} +symbol results in that procedure. + +The details of the connection between an unquoted symbol and the +variable to which it refers are explained elsewhere. See @ref{Binding +Constructs}, for how associations between symbols and variables are +created, and @ref{Modules}, for how those associations are affected by +Guile's module system. + + +@node Symbol Primitives +@subsubsection Operations Related to Symbols + +Given any Scheme value, you can determine whether it is a symbol using +the @code{symbol?} primitive: + +@rnindex symbol? +@deffn {Scheme Procedure} symbol? obj +@deffnx {C Function} scm_symbol_p (obj) +Return @code{#t} if @var{obj} is a symbol, otherwise return +@code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_symbol (SCM val) +Equivalent to @code{scm_is_true (scm_symbol_p (val))}. +@end deftypefn + +Once you know that you have a symbol, you can obtain its name as a +string by calling @code{symbol->string}. Note that Guile differs by +default from R5RS on the details of @code{symbol->string} as regards +case-sensitivity: + +@rnindex symbol->string +@deffn {Scheme Procedure} symbol->string s +@deffnx {C Function} scm_symbol_to_string (s) +Return the name of symbol @var{s} as a string. By default, Guile reads +symbols case-sensitively, so the string returned will have the same case +variation as the sequence of characters that caused @var{s} to be +created. + +If Guile is set to read symbols case-insensitively (as specified by +R5RS), and @var{s} comes into being as part of a literal expression +(@pxref{Literal expressions,,,r5rs, The Revised^5 Report on Scheme}) or +by a call to the @code{read} or @code{string-ci->symbol} procedures, +Guile converts any alphabetic characters in the symbol's name to +lower case before creating the symbol object, so the string returned +here will be in lower case. + +If @var{s} was created by @code{string->symbol}, the case of characters +in the string returned will be the same as that in the string that was +passed to @code{string->symbol}, regardless of Guile's case-sensitivity +setting at the time @var{s} was created. + +It is an error to apply mutation procedures like @code{string-set!} to +strings returned by this procedure. +@end deffn + +Most symbols are created by writing them literally in code. However it +is also possible to create symbols programmatically using the following +procedures: + +@deffn {Scheme Procedure} symbol char@dots{} +@rnindex symbol +Return a newly allocated symbol made from the given character arguments. + +@example +(symbol #\x #\y #\z) @result{} xyz +@end example +@end deffn + +@deffn {Scheme Procedure} list->symbol lst +@rnindex list->symbol +Return a newly allocated symbol made from a list of characters. + +@example +(list->symbol '(#\a #\b #\c)) @result{} abc +@end example +@end deffn + +@rnindex symbol-append +@deffn {Scheme Procedure} symbol-append arg @dots{} +Return a newly allocated symbol whose characters form the +concatenation of the given symbols, @var{arg} @enddots{}. + +@example +(let ((h 'hello)) + (symbol-append h 'world)) +@result{} helloworld +@end example +@end deffn + +@rnindex string->symbol +@deffn {Scheme Procedure} string->symbol string +@deffnx {C Function} scm_string_to_symbol (string) +Return the symbol whose name is @var{string}. This procedure can create +symbols with names containing special characters or letters in the +non-standard case, but it is usually a bad idea to create such symbols +because in some implementations of Scheme they cannot be read as +themselves. +@end deffn + +@deffn {Scheme Procedure} string-ci->symbol str +@deffnx {C Function} scm_string_ci_to_symbol (str) +Return the symbol whose name is @var{str}. If Guile is currently +reading symbols case-insensitively, @var{str} is converted to lowercase +before the returned symbol is looked up or created. +@end deffn + +The following examples illustrate Guile's detailed behaviour as regards +the case-sensitivity of symbols: + +@lisp +(read-enable 'case-insensitive) ; R5RS compliant behaviour + +(symbol->string 'flying-fish) @result{} "flying-fish" +(symbol->string 'Martin) @result{} "martin" +(symbol->string + (string->symbol "Malvina")) @result{} "Malvina" + +(eq? 'mISSISSIppi 'mississippi) @result{} #t +(string->symbol "mISSISSIppi") @result{} mISSISSIppi +(eq? 'bitBlt (string->symbol "bitBlt")) @result{} #f +(eq? 'LolliPop + (string->symbol (symbol->string 'LolliPop))) @result{} #t +(string=? "K. Harper, M.D." + (symbol->string + (string->symbol "K. Harper, M.D."))) @result{} #t + +(read-disable 'case-insensitive) ; Guile default behaviour + +(symbol->string 'flying-fish) @result{} "flying-fish" +(symbol->string 'Martin) @result{} "Martin" +(symbol->string + (string->symbol "Malvina")) @result{} "Malvina" + +(eq? 'mISSISSIppi 'mississippi) @result{} #f +(string->symbol "mISSISSIppi") @result{} mISSISSIppi +(eq? 'bitBlt (string->symbol "bitBlt")) @result{} #t +(eq? 'LolliPop + (string->symbol (symbol->string 'LolliPop))) @result{} #t +(string=? "K. Harper, M.D." + (symbol->string + (string->symbol "K. Harper, M.D."))) @result{} #t +@end lisp + +From C, there are lower level functions that construct a Scheme symbol +from a C string in the current locale encoding. + +When you want to do more from C, you should convert between symbols +and strings using @code{scm_symbol_to_string} and +@code{scm_string_to_symbol} and work with the strings. + +@deftypefn {C Function} SCM scm_from_latin1_symbol (const char *name) +@deftypefnx {C Function} SCM scm_from_utf8_symbol (const char *name) +Construct and return a Scheme symbol whose name is specified by the +null-terminated C string @var{name}. These are appropriate when +the C string is hard-coded in the source code. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_locale_symbol (const char *name) +@deftypefnx {C Function} SCM scm_from_locale_symboln (const char *name, size_t len) +Construct and return a Scheme symbol whose name is specified by +@var{name}. For @code{scm_from_locale_symbol}, @var{name} must be null +terminated; for @code{scm_from_locale_symboln} the length of @var{name} is +specified explicitly by @var{len}. + +Note that these functions should @emph{not} be used when @var{name} is a +C string constant, because there is no guarantee that the current locale +will match that of the execution character set, used for string and +character constants. Most modern C compilers use UTF-8 by default, so +in such cases we recommend @code{scm_from_utf8_symbol}. +@end deftypefn + +@deftypefn {C Function} SCM scm_take_locale_symbol (char *str) +@deftypefnx {C Function} SCM scm_take_locale_symboln (char *str, size_t len) +Like @code{scm_from_locale_symbol} and @code{scm_from_locale_symboln}, +respectively, but also frees @var{str} with @code{free} eventually. +Thus, you can use this function when you would free @var{str} anyway +immediately after creating the Scheme string. In certain cases, Guile +can then use @var{str} directly as its internal representation. +@end deftypefn + +The size of a symbol can also be obtained from C: + +@deftypefn {C Function} size_t scm_c_symbol_length (SCM sym) +Return the number of characters in @var{sym}. +@end deftypefn + +Finally, some applications, especially those that generate new Scheme +code dynamically, need to generate symbols for use in the generated +code. The @code{gensym} primitive meets this need: + +@deffn {Scheme Procedure} gensym [prefix] +@deffnx {C Function} scm_gensym (prefix) +Create a new symbol with a name constructed from a prefix and a counter +value. The string @var{prefix} can be specified as an optional +argument. Default prefix is @samp{@w{ g}}. The counter is increased by 1 +at each call. There is no provision for resetting the counter. +@end deffn + +The symbols generated by @code{gensym} are @emph{likely} to be unique, +since their names begin with a space and it is only otherwise possible +to generate such symbols if a programmer goes out of their way to do +so. Uniqueness can be guaranteed by instead using uninterned symbols +(@pxref{Symbol Uninterned}), though they can't be usefully written out +and read back in. + + +@node Symbol Props +@subsubsection Function Slots and Property Lists + +In traditional Lisp dialects, symbols are often understood as having +three kinds of value at once: + +@itemize @bullet +@item +a @dfn{variable} value, which is used when the symbol appears in +code in a variable reference context + +@item +a @dfn{function} value, which is used when the symbol appears in +code in a function name position (i.e.@: as the first element in an +unquoted list) + +@item +a @dfn{property list} value, which is used when the symbol is given as +the first argument to Lisp's @code{put} or @code{get} functions. +@end itemize + +Although Scheme (as one of its simplifications with respect to Lisp) +does away with the distinction between variable and function namespaces, +Guile currently retains some elements of the traditional structure in +case they turn out to be useful when implementing translators for other +languages, in particular Emacs Lisp. + +Specifically, Guile symbols have two extra slots, one for a symbol's +property list, and one for its ``function value.'' The following procedures +are provided to access these slots. + +@deffn {Scheme Procedure} symbol-fref symbol +@deffnx {C Function} scm_symbol_fref (symbol) +Return the contents of @var{symbol}'s @dfn{function slot}. +@end deffn + +@deffn {Scheme Procedure} symbol-fset! symbol value +@deffnx {C Function} scm_symbol_fset_x (symbol, value) +Set the contents of @var{symbol}'s function slot to @var{value}. +@end deffn + +@deffn {Scheme Procedure} symbol-pref symbol +@deffnx {C Function} scm_symbol_pref (symbol) +Return the @dfn{property list} currently associated with @var{symbol}. +@end deffn + +@deffn {Scheme Procedure} symbol-pset! symbol value +@deffnx {C Function} scm_symbol_pset_x (symbol, value) +Set @var{symbol}'s property list to @var{value}. +@end deffn + +@deffn {Scheme Procedure} symbol-property sym prop +From @var{sym}'s property list, return the value for property +@var{prop}. The assumption is that @var{sym}'s property list is an +association list whose keys are distinguished from each other using +@code{equal?}; @var{prop} should be one of the keys in that list. If +the property list has no entry for @var{prop}, @code{symbol-property} +returns @code{#f}. +@end deffn + +@deffn {Scheme Procedure} set-symbol-property! sym prop val +In @var{sym}'s property list, set the value for property @var{prop} to +@var{val}, or add a new entry for @var{prop}, with value @var{val}, if +none already exists. For the structure of the property list, see +@code{symbol-property}. +@end deffn + +@deffn {Scheme Procedure} symbol-property-remove! sym prop +From @var{sym}'s property list, remove the entry for property +@var{prop}, if there is one. For the structure of the property list, +see @code{symbol-property}. +@end deffn + +Support for these extra slots may be removed in a future release, and it +is probably better to avoid using them. For a more modern and Schemely +approach to properties, see @ref{Object Properties}. + + +@node Symbol Read Syntax +@subsubsection Extended Read Syntax for Symbols + +@cindex r7rs-symbols + +The read syntax for a symbol is a sequence of letters, digits, and +@dfn{extended alphabetic characters}, beginning with a character that +cannot begin a number. In addition, the special cases of @code{+}, +@code{-}, and @code{...} are read as symbols even though numbers can +begin with @code{+}, @code{-} or @code{.}. + +Extended alphabetic characters may be used within identifiers as if +they were letters. The set of extended alphabetic characters is: + +@example +! $ % & * + - . / : < = > ? @@ ^ _ ~ +@end example + +In addition to the standard read syntax defined above (which is taken +from R5RS (@pxref{Formal syntax,,,r5rs,The Revised^5 Report on +Scheme})), Guile provides an extended symbol read syntax that allows the +inclusion of unusual characters such as space characters, newlines and +parentheses. If (for whatever reason) you need to write a symbol +containing characters not mentioned above, you can do so as follows. + +@itemize @bullet +@item +Begin the symbol with the characters @code{#@{}, + +@item +write the characters of the symbol and + +@item +finish the symbol with the characters @code{@}#}. +@end itemize + +Here are a few examples of this form of read syntax. The first symbol +needs to use extended syntax because it contains a space character, the +second because it contains a line break, and the last because it looks +like a number. + +@lisp +#@{foo bar@}# + +#@{what +ever@}# + +#@{4242@}# +@end lisp + +Although Guile provides this extended read syntax for symbols, +widespread usage of it is discouraged because it is not portable and not +very readable. + +Alternatively, if you enable the @code{r7rs-symbols} read option (see +@pxref{Scheme Read}), you can write arbitrary symbols using the same +notation used for strings, except delimited by vertical bars instead of +double quotes. + +@example +|foo bar| +|\x3BB; is a greek lambda| +|\| is a vertical bar| +@end example + +Note that there's also an @code{r7rs-symbols} print option +(@pxref{Scheme Write}). To enable the use of this notation, evaluate +one or both of the following expressions: + +@example +(read-enable 'r7rs-symbols) +(print-enable 'r7rs-symbols) +@end example + + +@node Symbol Uninterned +@subsubsection Uninterned Symbols + +What makes symbols useful is that they are automatically kept unique. +There are no two symbols that are distinct objects but have the same +name. But of course, there is no rule without exception. In addition +to the normal symbols that have been discussed up to now, you can also +create special @dfn{uninterned} symbols that behave slightly +differently. + +To understand what is different about them and why they might be useful, +we look at how normal symbols are actually kept unique. + +Whenever Guile wants to find the symbol with a specific name, for +example during @code{read} or when executing @code{string->symbol}, it +first looks into a table of all existing symbols to find out whether a +symbol with the given name already exists. When this is the case, Guile +just returns that symbol. When not, a new symbol with the name is +created and entered into the table so that it can be found later. + +Sometimes you might want to create a symbol that is guaranteed `fresh', +i.e.@: a symbol that did not exist previously. You might also want to +somehow guarantee that no one else will ever unintentionally stumble +across your symbol in the future. These properties of a symbol are +often needed when generating code during macro expansion. When +introducing new temporary variables, you want to guarantee that they +don't conflict with variables in other people's code. + +The simplest way to arrange for this is to create a new symbol but +not enter it into the global table of all symbols. That way, no one +will ever get access to your symbol by chance. Symbols that are not in +the table are called @dfn{uninterned}. Of course, symbols that +@emph{are} in the table are called @dfn{interned}. + +You create new uninterned symbols with the function @code{make-symbol}. +You can test whether a symbol is interned or not with +@code{symbol-interned?}. + +Uninterned symbols break the rule that the name of a symbol uniquely +identifies the symbol object. Because of this, they can not be written +out and read back in like interned symbols. Currently, Guile has no +support for reading uninterned symbols. Note that the function +@code{gensym} does not return uninterned symbols for this reason. + +@deffn {Scheme Procedure} make-symbol name +@deffnx {C Function} scm_make_symbol (name) +Return a new uninterned symbol with the name @var{name}. The returned +symbol is guaranteed to be unique and future calls to +@code{string->symbol} will not return it. +@end deffn + +@deffn {Scheme Procedure} symbol-interned? symbol +@deffnx {C Function} scm_symbol_interned_p (symbol) +Return @code{#t} if @var{symbol} is interned, otherwise return +@code{#f}. +@end deffn + +For example: + +@lisp +(define foo-1 (string->symbol "foo")) +(define foo-2 (string->symbol "foo")) +(define foo-3 (make-symbol "foo")) +(define foo-4 (make-symbol "foo")) + +(eq? foo-1 foo-2) +@result{} #t +; Two interned symbols with the same name are the same object, + +(eq? foo-1 foo-3) +@result{} #f +; but a call to make-symbol with the same name returns a +; distinct object. + +(eq? foo-3 foo-4) +@result{} #f +; A call to make-symbol always returns a new object, even for +; the same name. + +foo-3 +@result{} #<uninterned-symbol foo 8085290> +; Uninterned symbols print differently from interned symbols, + +(symbol? foo-3) +@result{} #t +; but they are still symbols, + +(symbol-interned? foo-3) +@result{} #f +; just not interned. +@end lisp + + +@node Keywords +@subsection Keywords +@tpindex Keywords + +Keywords are self-evaluating objects with a convenient read syntax that +makes them easy to type. + +Guile's keyword support conforms to R5RS, and adds a (switchable) read +syntax extension to permit keywords to begin with @code{:} as well as +@code{#:}, or to end with @code{:}. + +@menu +* Why Use Keywords?:: Motivation for keyword usage. +* Coding With Keywords:: How to use keywords. +* Keyword Read Syntax:: Read syntax for keywords. +* Keyword Procedures:: Procedures for dealing with keywords. +@end menu + +@node Why Use Keywords? +@subsubsection Why Use Keywords? + +Keywords are useful in contexts where a program or procedure wants to be +able to accept a large number of optional arguments without making its +interface unmanageable. + +To illustrate this, consider a hypothetical @code{make-window} +procedure, which creates a new window on the screen for drawing into +using some graphical toolkit. There are many parameters that the caller +might like to specify, but which could also be sensibly defaulted, for +example: + +@itemize @bullet +@item +color depth -- Default: the color depth for the screen + +@item +background color -- Default: white + +@item +width -- Default: 600 + +@item +height -- Default: 400 +@end itemize + +If @code{make-window} did not use keywords, the caller would have to +pass in a value for each possible argument, remembering the correct +argument order and using a special value to indicate the default value +for that argument: + +@lisp +(make-window 'default ;; Color depth + 'default ;; Background color + 800 ;; Width + 100 ;; Height + @dots{}) ;; More make-window arguments +@end lisp + +With keywords, on the other hand, defaulted arguments are omitted, and +non-default arguments are clearly tagged by the appropriate keyword. As +a result, the invocation becomes much clearer: + +@lisp +(make-window #:width 800 #:height 100) +@end lisp + +On the other hand, for a simpler procedure with few arguments, the use +of keywords would be a hindrance rather than a help. The primitive +procedure @code{cons}, for example, would not be improved if it had to +be invoked as + +@lisp +(cons #:car x #:cdr y) +@end lisp + +So the decision whether to use keywords or not is purely pragmatic: use +them if they will clarify the procedure invocation at point of call. + +@node Coding With Keywords +@subsubsection Coding With Keywords + +If a procedure wants to support keywords, it should take a rest argument +and then use whatever means is convenient to extract keywords and their +corresponding arguments from the contents of that rest argument. + +The following example illustrates the principle: the code for +@code{make-window} uses a helper procedure called +@code{get-keyword-value} to extract individual keyword arguments from +the rest argument. + +@lisp +(define (get-keyword-value args keyword default) + (let ((kv (memq keyword args))) + (if (and kv (>= (length kv) 2)) + (cadr kv) + default))) + +(define (make-window . args) + (let ((depth (get-keyword-value args #:depth screen-depth)) + (bg (get-keyword-value args #:bg "white")) + (width (get-keyword-value args #:width 800)) + (height (get-keyword-value args #:height 100)) + @dots{}) + @dots{})) +@end lisp + +But you don't need to write @code{get-keyword-value}. The @code{(ice-9 +optargs)} module provides a set of powerful macros that you can use to +implement keyword-supporting procedures like this: + +@lisp +(use-modules (ice-9 optargs)) + +(define (make-window . args) + (let-keywords args #f ((depth screen-depth) + (bg "white") + (width 800) + (height 100)) + ...)) +@end lisp + +@noindent +Or, even more economically, like this: + +@lisp +(use-modules (ice-9 optargs)) + +(define* (make-window #:key (depth screen-depth) + (bg "white") + (width 800) + (height 100)) + ...) +@end lisp + +For further details on @code{let-keywords}, @code{define*} and other +facilities provided by the @code{(ice-9 optargs)} module, see +@ref{Optional Arguments}. + +To handle keyword arguments from procedures implemented in C, +use @code{scm_c_bind_keyword_arguments} (@pxref{Keyword Procedures}). + +@node Keyword Read Syntax +@subsubsection Keyword Read Syntax + +Guile, by default, only recognizes a keyword syntax that is compatible +with R5RS. A token of the form @code{#:NAME}, where @code{NAME} has the +same syntax as a Scheme symbol (@pxref{Symbol Read Syntax}), is the +external representation of the keyword named @code{NAME}. Keyword +objects print using this syntax as well, so values containing keyword +objects can be read back into Guile. When used in an expression, +keywords are self-quoting objects. + +If the @code{keywords} read option is set to @code{'prefix}, Guile also +recognizes the alternative read syntax @code{:NAME}. Otherwise, tokens +of the form @code{:NAME} are read as symbols, as required by R5RS. + +@cindex SRFI-88 keyword syntax + +If the @code{keywords} read option is set to @code{'postfix}, Guile +recognizes the SRFI-88 read syntax @code{NAME:} (@pxref{SRFI-88}). +Otherwise, tokens of this form are read as symbols. + +To enable and disable the alternative non-R5RS keyword syntax, you use +the @code{read-set!} procedure documented @ref{Scheme Read}. Note that +the @code{prefix} and @code{postfix} syntax are mutually exclusive. + +@lisp +(read-set! keywords 'prefix) + +#:type +@result{} +#:type + +:type +@result{} +#:type + +(read-set! keywords 'postfix) + +type: +@result{} +#:type + +:type +@result{} +:type + +(read-set! keywords #f) + +#:type +@result{} +#:type + +:type +@print{} +ERROR: In expression :type: +ERROR: Unbound variable: :type +ABORT: (unbound-variable) +@end lisp + +@node Keyword Procedures +@subsubsection Keyword Procedures + +@deffn {Scheme Procedure} keyword? obj +@deffnx {C Function} scm_keyword_p (obj) +Return @code{#t} if the argument @var{obj} is a keyword, else +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} keyword->symbol keyword +@deffnx {C Function} scm_keyword_to_symbol (keyword) +Return the symbol with the same name as @var{keyword}. +@end deffn + +@deffn {Scheme Procedure} symbol->keyword symbol +@deffnx {C Function} scm_symbol_to_keyword (symbol) +Return the keyword with the same name as @var{symbol}. +@end deffn + +@deftypefn {C Function} int scm_is_keyword (SCM obj) +Equivalent to @code{scm_is_true (scm_keyword_p (@var{obj}))}. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_locale_keyword (const char *name) +@deftypefnx {C Function} SCM scm_from_locale_keywordn (const char *name, size_t len) +Equivalent to @code{scm_symbol_to_keyword (scm_from_locale_symbol +(@var{name}))} and @code{scm_symbol_to_keyword (scm_from_locale_symboln +(@var{name}, @var{len}))}, respectively. + +Note that these functions should @emph{not} be used when @var{name} is a +C string constant, because there is no guarantee that the current locale +will match that of the execution character set, used for string and +character constants. Most modern C compilers use UTF-8 by default, so +in such cases we recommend @code{scm_from_utf8_keyword}. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_latin1_keyword (const char *name) +@deftypefnx {C Function} SCM scm_from_utf8_keyword (const char *name) +Equivalent to @code{scm_symbol_to_keyword (scm_from_latin1_symbol +(@var{name}))} and @code{scm_symbol_to_keyword (scm_from_utf8_symbol +(@var{name}))}, respectively. +@end deftypefn + +@deftypefn {C Function} void scm_c_bind_keyword_arguments (const char *subr, @ + SCM rest, scm_t_keyword_arguments_flags flags, @ + SCM keyword1, SCM *argp1, @ + @dots{}, @ + SCM keywordN, SCM *argpN, @ + @nicode{SCM_UNDEFINED}) + +Extract the specified keyword arguments from @var{rest}, which is not +modified. If the keyword argument @var{keyword1} is present in +@var{rest} with an associated value, that value is stored in the +variable pointed to by @var{argp1}, otherwise the variable is left +unchanged. Similarly for the other keywords and argument pointers up to +@var{keywordN} and @var{argpN}. The argument list to +@code{scm_c_bind_keyword_arguments} must be terminated by +@code{SCM_UNDEFINED}. + +Note that since the variables pointed to by @var{argp1} through +@var{argpN} are left unchanged if the associated keyword argument is not +present, they should be initialized to their default values before +calling @code{scm_c_bind_keyword_arguments}. Alternatively, you can +initialize them to @code{SCM_UNDEFINED} before the call, and then use +@code{SCM_UNBNDP} after the call to see which ones were provided. + +If an unrecognized keyword argument is present in @var{rest} and +@var{flags} does not contain @code{SCM_ALLOW_OTHER_KEYS}, or if +non-keyword arguments are present and @var{flags} does not contain +@code{SCM_ALLOW_NON_KEYWORD_ARGUMENTS}, an exception is raised. +@var{subr} should be the name of the procedure receiving the keyword +arguments, for purposes of error reporting. + +For example: + +@example +SCM k_delimiter; +SCM k_grammar; +SCM sym_infix; + +SCM my_string_join (SCM strings, SCM rest) +@{ + SCM delimiter = SCM_UNDEFINED; + SCM grammar = sym_infix; + + scm_c_bind_keyword_arguments ("my-string-join", rest, 0, + k_delimiter, &delimiter, + k_grammar, &grammar, + SCM_UNDEFINED); + + if (SCM_UNBNDP (delimiter)) + delimiter = scm_from_utf8_string (" "); + + return scm_string_join (strings, delimiter, grammar); +@} + +void my_init () +@{ + k_delimiter = scm_from_utf8_keyword ("delimiter"); + k_grammar = scm_from_utf8_keyword ("grammar"); + sym_infix = scm_from_utf8_symbol ("infix"); + scm_c_define_gsubr ("my-string-join", 1, 0, 1, my_string_join); +@} +@end example +@end deftypefn + + +@node Pairs +@subsection Pairs +@tpindex Pairs + +Pairs are used to combine two Scheme objects into one compound object. +Hence the name: A pair stores a pair of objects. + +The data type @dfn{pair} is extremely important in Scheme, just like in +any other Lisp dialect. The reason is that pairs are not only used to +make two values available as one object, but that pairs are used for +constructing lists of values. Because lists are so important in Scheme, +they are described in a section of their own (@pxref{Lists}). + +Pairs can literally get entered in source code or at the REPL, in the +so-called @dfn{dotted list} syntax. This syntax consists of an opening +parentheses, the first element of the pair, a dot, the second element +and a closing parentheses. The following example shows how a pair +consisting of the two numbers 1 and 2, and a pair containing the symbols +@code{foo} and @code{bar} can be entered. It is very important to write +the whitespace before and after the dot, because otherwise the Scheme +parser would not be able to figure out where to split the tokens. + +@lisp +(1 . 2) +(foo . bar) +@end lisp + +But beware, if you want to try out these examples, you have to +@dfn{quote} the expressions. More information about quotation is +available in the section @ref{Expression Syntax}. The correct way +to try these examples is as follows. + +@lisp +'(1 . 2) +@result{} +(1 . 2) +'(foo . bar) +@result{} +(foo . bar) +@end lisp + +A new pair is made by calling the procedure @code{cons} with two +arguments. Then the argument values are stored into a newly allocated +pair, and the pair is returned. The name @code{cons} stands for +"construct". Use the procedure @code{pair?} to test whether a +given Scheme object is a pair or not. + +@rnindex cons +@deffn {Scheme Procedure} cons x y +@deffnx {C Function} scm_cons (x, y) +Return a newly allocated pair whose car is @var{x} and whose +cdr is @var{y}. The pair is guaranteed to be different (in the +sense of @code{eq?}) from every previously existing object. +@end deffn + +@rnindex pair? +@deffn {Scheme Procedure} pair? x +@deffnx {C Function} scm_pair_p (x) +Return @code{#t} if @var{x} is a pair; otherwise return +@code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_pair (SCM x) +Return 1 when @var{x} is a pair; otherwise return 0. +@end deftypefn + +The two parts of a pair are traditionally called @dfn{car} and +@dfn{cdr}. They can be retrieved with procedures of the same name +(@code{car} and @code{cdr}), and can be modified with the procedures +@code{set-car!} and @code{set-cdr!}. + +Since a very common operation in Scheme programs is to access the car of +a car of a pair, or the car of the cdr of a pair, etc., the procedures +called @code{caar}, @code{cadr} and so on are also predefined. However, +using these procedures is often detrimental to readability, and +error-prone. Thus, accessing the contents of a list is usually better +achieved using pattern matching techniques (@pxref{Pattern Matching}). + +@rnindex car +@rnindex cdr +@deffn {Scheme Procedure} car pair +@deffnx {Scheme Procedure} cdr pair +@deffnx {C Function} scm_car (pair) +@deffnx {C Function} scm_cdr (pair) +Return the car or the cdr of @var{pair}, respectively. +@end deffn + +@deftypefn {C Macro} SCM SCM_CAR (SCM pair) +@deftypefnx {C Macro} SCM SCM_CDR (SCM pair) +These two macros are the fastest way to access the car or cdr of a +pair; they can be thought of as compiling into a single memory +reference. + +These macros do no checking at all. The argument @var{pair} must be a +valid pair. +@end deftypefn + +@deffn {Scheme Procedure} cddr pair +@deffnx {Scheme Procedure} cdar pair +@deffnx {Scheme Procedure} cadr pair +@deffnx {Scheme Procedure} caar pair +@deffnx {Scheme Procedure} cdddr pair +@deffnx {Scheme Procedure} cddar pair +@deffnx {Scheme Procedure} cdadr pair +@deffnx {Scheme Procedure} cdaar pair +@deffnx {Scheme Procedure} caddr pair +@deffnx {Scheme Procedure} cadar pair +@deffnx {Scheme Procedure} caadr pair +@deffnx {Scheme Procedure} caaar pair +@deffnx {Scheme Procedure} cddddr pair +@deffnx {Scheme Procedure} cdddar pair +@deffnx {Scheme Procedure} cddadr pair +@deffnx {Scheme Procedure} cddaar pair +@deffnx {Scheme Procedure} cdaddr pair +@deffnx {Scheme Procedure} cdadar pair +@deffnx {Scheme Procedure} cdaadr pair +@deffnx {Scheme Procedure} cdaaar pair +@deffnx {Scheme Procedure} cadddr pair +@deffnx {Scheme Procedure} caddar pair +@deffnx {Scheme Procedure} cadadr pair +@deffnx {Scheme Procedure} cadaar pair +@deffnx {Scheme Procedure} caaddr pair +@deffnx {Scheme Procedure} caadar pair +@deffnx {Scheme Procedure} caaadr pair +@deffnx {Scheme Procedure} caaaar pair +@deffnx {C Function} scm_cddr (pair) +@deffnx {C Function} scm_cdar (pair) +@deffnx {C Function} scm_cadr (pair) +@deffnx {C Function} scm_caar (pair) +@deffnx {C Function} scm_cdddr (pair) +@deffnx {C Function} scm_cddar (pair) +@deffnx {C Function} scm_cdadr (pair) +@deffnx {C Function} scm_cdaar (pair) +@deffnx {C Function} scm_caddr (pair) +@deffnx {C Function} scm_cadar (pair) +@deffnx {C Function} scm_caadr (pair) +@deffnx {C Function} scm_caaar (pair) +@deffnx {C Function} scm_cddddr (pair) +@deffnx {C Function} scm_cdddar (pair) +@deffnx {C Function} scm_cddadr (pair) +@deffnx {C Function} scm_cddaar (pair) +@deffnx {C Function} scm_cdaddr (pair) +@deffnx {C Function} scm_cdadar (pair) +@deffnx {C Function} scm_cdaadr (pair) +@deffnx {C Function} scm_cdaaar (pair) +@deffnx {C Function} scm_cadddr (pair) +@deffnx {C Function} scm_caddar (pair) +@deffnx {C Function} scm_cadadr (pair) +@deffnx {C Function} scm_cadaar (pair) +@deffnx {C Function} scm_caaddr (pair) +@deffnx {C Function} scm_caadar (pair) +@deffnx {C Function} scm_caaadr (pair) +@deffnx {C Function} scm_caaaar (pair) +These procedures are compositions of @code{car} and @code{cdr}, where +for example @code{caddr} could be defined by + +@lisp +(define caddr (lambda (x) (car (cdr (cdr x))))) +@end lisp + +@code{cadr}, @code{caddr} and @code{cadddr} pick out the second, third +or fourth elements of a list, respectively. SRFI-1 provides the same +under the names @code{second}, @code{third} and @code{fourth} +(@pxref{SRFI-1 Selectors}). +@end deffn + +@rnindex set-car! +@deffn {Scheme Procedure} set-car! pair value +@deffnx {C Function} scm_set_car_x (pair, value) +Stores @var{value} in the car field of @var{pair}. The value returned +by @code{set-car!} is unspecified. +@end deffn + +@rnindex set-cdr! +@deffn {Scheme Procedure} set-cdr! pair value +@deffnx {C Function} scm_set_cdr_x (pair, value) +Stores @var{value} in the cdr field of @var{pair}. The value returned +by @code{set-cdr!} is unspecified. +@end deffn + + +@node Lists +@subsection Lists +@tpindex Lists + +A very important data type in Scheme---as well as in all other Lisp +dialects---is the data type @dfn{list}.@footnote{Strictly speaking, +Scheme does not have a real datatype @dfn{list}. Lists are made up of +@dfn{chained pairs}, and only exist by definition---a list is a chain +of pairs which looks like a list.} + +This is the short definition of what a list is: + +@itemize @bullet +@item +Either the empty list @code{()}, + +@item +or a pair which has a list in its cdr. +@end itemize + +@c FIXME::martin: Describe the pair chaining in more detail. + +@c FIXME::martin: What is a proper, what an improper list? +@c What is a circular list? + +@c FIXME::martin: Maybe steal some graphics from the Elisp reference +@c manual? + +@menu +* List Syntax:: Writing literal lists. +* List Predicates:: Testing lists. +* List Constructors:: Creating new lists. +* List Selection:: Selecting from lists, getting their length. +* Append/Reverse:: Appending and reversing lists. +* List Modification:: Modifying existing lists. +* List Searching:: Searching for list elements +* List Mapping:: Applying procedures to lists. +@end menu + +@node List Syntax +@subsubsection List Read Syntax + +The syntax for lists is an opening parentheses, then all the elements of +the list (separated by whitespace) and finally a closing +parentheses.@footnote{Note that there is no separation character between +the list elements, like a comma or a semicolon.}. + +@lisp +(1 2 3) ; @r{a list of the numbers 1, 2 and 3} +("foo" bar 3.1415) ; @r{a string, a symbol and a real number} +() ; @r{the empty list} +@end lisp + +The last example needs a bit more explanation. A list with no elements, +called the @dfn{empty list}, is special in some ways. It is used for +terminating lists by storing it into the cdr of the last pair that makes +up a list. An example will clear that up: + +@lisp +(car '(1)) +@result{} +1 +(cdr '(1)) +@result{} +() +@end lisp + +This example also shows that lists have to be quoted when written +(@pxref{Expression Syntax}), because they would otherwise be +mistakingly taken as procedure applications (@pxref{Simple +Invocation}). + + +@node List Predicates +@subsubsection List Predicates + +Often it is useful to test whether a given Scheme object is a list or +not. List-processing procedures could use this information to test +whether their input is valid, or they could do different things +depending on the datatype of their arguments. + +@rnindex list? +@deffn {Scheme Procedure} list? x +@deffnx {C Function} scm_list_p (x) +Return @code{#t} if @var{x} is a proper list, else @code{#f}. +@end deffn + +The predicate @code{null?} is often used in list-processing code to +tell whether a given list has run out of elements. That is, a loop +somehow deals with the elements of a list until the list satisfies +@code{null?}. Then, the algorithm terminates. + +@rnindex null? +@deffn {Scheme Procedure} null? x +@deffnx {C Function} scm_null_p (x) +Return @code{#t} if @var{x} is the empty list, else @code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_null (SCM x) +Return 1 when @var{x} is the empty list; otherwise return 0. +@end deftypefn + + +@node List Constructors +@subsubsection List Constructors + +This section describes the procedures for constructing new lists. +@code{list} simply returns a list where the elements are the arguments, +@code{cons*} is similar, but the last argument is stored in the cdr of +the last pair of the list. + +@c C Function scm_list(rest) used to be documented here, but it's a +@c no-op since it does nothing but return the list the caller must +@c have already created. +@c +@deffn {Scheme Procedure} list elem @dots{} +@deffnx {C Function} scm_list_1 (elem1) +@deffnx {C Function} scm_list_2 (elem1, elem2) +@deffnx {C Function} scm_list_3 (elem1, elem2, elem3) +@deffnx {C Function} scm_list_4 (elem1, elem2, elem3, elem4) +@deffnx {C Function} scm_list_5 (elem1, elem2, elem3, elem4, elem5) +@deffnx {C Function} scm_list_n (elem1, @dots{}, elemN, @nicode{SCM_UNDEFINED}) +@rnindex list +Return a new list containing elements @var{elem} @enddots{}. + +@code{scm_list_n} takes a variable number of arguments, terminated by +the special @code{SCM_UNDEFINED}. That final @code{SCM_UNDEFINED} is +not included in the list. None of @var{elem} @dots{} can +themselves be @code{SCM_UNDEFINED}, or @code{scm_list_n} will +terminate at that point. +@end deffn + +@c C Function scm_cons_star(arg1,rest) used to be documented here, +@c but it's not really a useful interface, since it expects the +@c caller to have already consed up all but the first argument +@c already. +@c +@deffn {Scheme Procedure} cons* arg1 arg2 @dots{} +Like @code{list}, but the last arg provides the tail of the +constructed list, returning @code{(cons @var{arg1} (cons +@var{arg2} (cons @dots{} @var{argn})))}. Requires at least one +argument. If given one argument, that argument is returned as +result. This function is called @code{list*} in some other +Schemes and in Common LISP. +@end deffn + +@deffn {Scheme Procedure} list-copy lst +@deffnx {C Function} scm_list_copy (lst) +Return a (newly-created) copy of @var{lst}. +@end deffn + +@deffn {Scheme Procedure} make-list n [init] +Create a list containing of @var{n} elements, where each element is +initialized to @var{init}. @var{init} defaults to the empty list +@code{()} if not given. +@end deffn + +Note that @code{list-copy} only makes a copy of the pairs which make up +the spine of the lists. The list elements are not copied, which means +that modifying the elements of the new list also modifies the elements +of the old list. On the other hand, applying procedures like +@code{set-cdr!} or @code{delv!} to the new list will not alter the old +list. If you also need to copy the list elements (making a deep copy), +use the procedure @code{copy-tree} (@pxref{Copying}). + +@node List Selection +@subsubsection List Selection + +These procedures are used to get some information about a list, or to +retrieve one or more elements of a list. + +@rnindex length +@deffn {Scheme Procedure} length lst +@deffnx {C Function} scm_length (lst) +Return the number of elements in list @var{lst}. +@end deffn + +@deffn {Scheme Procedure} last-pair lst +@deffnx {C Function} scm_last_pair (lst) +Return the last pair in @var{lst}, signalling an error if +@var{lst} is circular. +@end deffn + +@rnindex list-ref +@deffn {Scheme Procedure} list-ref list k +@deffnx {C Function} scm_list_ref (list, k) +Return the @var{k}th element from @var{list}. +@end deffn + +@rnindex list-tail +@deffn {Scheme Procedure} list-tail lst k +@deffnx {Scheme Procedure} list-cdr-ref lst k +@deffnx {C Function} scm_list_tail (lst, k) +Return the "tail" of @var{lst} beginning with its @var{k}th element. +The first element of the list is considered to be element 0. + +@code{list-tail} and @code{list-cdr-ref} are identical. It may help to +think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list, +or returning the results of cdring @var{k} times down @var{lst}. +@end deffn + +@deffn {Scheme Procedure} list-head lst k +@deffnx {C Function} scm_list_head (lst, k) +Copy the first @var{k} elements from @var{lst} into a new list, and +return it. +@end deffn + +@node Append/Reverse +@subsubsection Append and Reverse + +@code{append} and @code{append!} are used to concatenate two or more +lists in order to form a new list. @code{reverse} and @code{reverse!} +return lists with the same elements as their arguments, but in reverse +order. The procedure variants with an @code{!} directly modify the +pairs which form the list, whereas the other procedures create new +pairs. This is why you should be careful when using the side-effecting +variants. + +@rnindex append +@deffn {Scheme Procedure} append lst @dots{} obj +@deffnx {Scheme Procedure} append +@deffnx {Scheme Procedure} append! lst @dots{} obj +@deffnx {Scheme Procedure} append! +@deffnx {C Function} scm_append (lstlst) +@deffnx {C Function} scm_append_x (lstlst) +Return a list comprising all the elements of lists @var{lst} @dots{} +@var{obj}. If called with no arguments, return the empty list. + +@lisp +(append '(x) '(y)) @result{} (x y) +(append '(a) '(b c d)) @result{} (a b c d) +(append '(a (b)) '((c))) @result{} (a (b) (c)) +@end lisp + +The last argument @var{obj} may actually be any object; an improper +list results if the last argument is not a proper list. + +@lisp +(append '(a b) '(c . d)) @result{} (a b c . d) +(append '() 'a) @result{} a +@end lisp + +@code{append} doesn't modify the given lists, but the return may share +structure with the final @var{obj}. @code{append!} is permitted, but +not required, to modify the given lists to form its return. + +For @code{scm_append} and @code{scm_append_x}, @var{lstlst} is a list +of the list operands @var{lst} @dots{} @var{obj}. That @var{lstlst} +itself is not modified or used in the return. +@end deffn + +@rnindex reverse +@deffn {Scheme Procedure} reverse lst +@deffnx {Scheme Procedure} reverse! lst [newtail] +@deffnx {C Function} scm_reverse (lst) +@deffnx {C Function} scm_reverse_x (lst, newtail) +Return a list comprising the elements of @var{lst}, in reverse order. + +@code{reverse} constructs a new list. @code{reverse!} is permitted, but +not required, to modify @var{lst} in constructing its return. + +For @code{reverse!}, the optional @var{newtail} is appended to the +result. @var{newtail} isn't reversed, it simply becomes the list +tail. For @code{scm_reverse_x}, the @var{newtail} parameter is +mandatory, but can be @code{SCM_EOL} if no further tail is required. +@end deffn + +@node List Modification +@subsubsection List Modification + +The following procedures modify an existing list, either by changing +elements of the list, or by changing the list structure itself. + +@deffn {Scheme Procedure} list-set! list k val +@deffnx {C Function} scm_list_set_x (list, k, val) +Set the @var{k}th element of @var{list} to @var{val}. +@end deffn + +@deffn {Scheme Procedure} list-cdr-set! list k val +@deffnx {C Function} scm_list_cdr_set_x (list, k, val) +Set the @var{k}th cdr of @var{list} to @var{val}. +@end deffn + +@deffn {Scheme Procedure} delq item lst +@deffnx {C Function} scm_delq (item, lst) +Return a newly-created copy of @var{lst} with elements +@code{eq?} to @var{item} removed. This procedure mirrors +@code{memq}: @code{delq} compares elements of @var{lst} against +@var{item} with @code{eq?}. +@end deffn + +@deffn {Scheme Procedure} delv item lst +@deffnx {C Function} scm_delv (item, lst) +Return a newly-created copy of @var{lst} with elements +@code{eqv?} to @var{item} removed. This procedure mirrors +@code{memv}: @code{delv} compares elements of @var{lst} against +@var{item} with @code{eqv?}. +@end deffn + +@deffn {Scheme Procedure} delete item lst +@deffnx {C Function} scm_delete (item, lst) +Return a newly-created copy of @var{lst} with elements +@code{equal?} to @var{item} removed. This procedure mirrors +@code{member}: @code{delete} compares elements of @var{lst} +against @var{item} with @code{equal?}. + +See also SRFI-1 which has an extended @code{delete} (@ref{SRFI-1 +Deleting}), and also an @code{lset-difference} which can delete +multiple @var{item}s in one call (@ref{SRFI-1 Set Operations}). +@end deffn + +@deffn {Scheme Procedure} delq! item lst +@deffnx {Scheme Procedure} delv! item lst +@deffnx {Scheme Procedure} delete! item lst +@deffnx {C Function} scm_delq_x (item, lst) +@deffnx {C Function} scm_delv_x (item, lst) +@deffnx {C Function} scm_delete_x (item, lst) +These procedures are destructive versions of @code{delq}, @code{delv} +and @code{delete}: they modify the pointers in the existing @var{lst} +rather than creating a new list. Caveat evaluator: Like other +destructive list functions, these functions cannot modify the binding of +@var{lst}, and so cannot be used to delete the first element of +@var{lst} destructively. +@end deffn + +@deffn {Scheme Procedure} delq1! item lst +@deffnx {C Function} scm_delq1_x (item, lst) +Like @code{delq!}, but only deletes the first occurrence of +@var{item} from @var{lst}. Tests for equality using +@code{eq?}. See also @code{delv1!} and @code{delete1!}. +@end deffn + +@deffn {Scheme Procedure} delv1! item lst +@deffnx {C Function} scm_delv1_x (item, lst) +Like @code{delv!}, but only deletes the first occurrence of +@var{item} from @var{lst}. Tests for equality using +@code{eqv?}. See also @code{delq1!} and @code{delete1!}. +@end deffn + +@deffn {Scheme Procedure} delete1! item lst +@deffnx {C Function} scm_delete1_x (item, lst) +Like @code{delete!}, but only deletes the first occurrence of +@var{item} from @var{lst}. Tests for equality using +@code{equal?}. See also @code{delq1!} and @code{delv1!}. +@end deffn + +@deffn {Scheme Procedure} filter pred lst +@deffnx {Scheme Procedure} filter! pred lst +Return a list containing all elements from @var{lst} which satisfy the +predicate @var{pred}. The elements in the result list have the same +order as in @var{lst}. The order in which @var{pred} is applied to +the list elements is not specified. + +@code{filter} does not change @var{lst}, but the result may share a +tail with it. @code{filter!} may modify @var{lst} to construct its +return. +@end deffn + +@node List Searching +@subsubsection List Searching + +The following procedures search lists for particular elements. They use +different comparison predicates for comparing list elements with the +object to be searched. When they fail, they return @code{#f}, otherwise +they return the sublist whose car is equal to the search object, where +equality depends on the equality predicate used. + +@rnindex memq +@deffn {Scheme Procedure} memq x lst +@deffnx {C Function} scm_memq (x, lst) +Return the first sublist of @var{lst} whose car is @code{eq?} +to @var{x} where the sublists of @var{lst} are the non-empty +lists returned by @code{(list-tail @var{lst} @var{k})} for +@var{k} less than the length of @var{lst}. If @var{x} does not +occur in @var{lst}, then @code{#f} (not the empty list) is +returned. +@end deffn + +@rnindex memv +@deffn {Scheme Procedure} memv x lst +@deffnx {C Function} scm_memv (x, lst) +Return the first sublist of @var{lst} whose car is @code{eqv?} +to @var{x} where the sublists of @var{lst} are the non-empty +lists returned by @code{(list-tail @var{lst} @var{k})} for +@var{k} less than the length of @var{lst}. If @var{x} does not +occur in @var{lst}, then @code{#f} (not the empty list) is +returned. +@end deffn + +@rnindex member +@deffn {Scheme Procedure} member x lst +@deffnx {C Function} scm_member (x, lst) +Return the first sublist of @var{lst} whose car is +@code{equal?} to @var{x} where the sublists of @var{lst} are +the non-empty lists returned by @code{(list-tail @var{lst} +@var{k})} for @var{k} less than the length of @var{lst}. If +@var{x} does not occur in @var{lst}, then @code{#f} (not the +empty list) is returned. + +See also SRFI-1 which has an extended @code{member} function +(@ref{SRFI-1 Searching}). +@end deffn + + +@node List Mapping +@subsubsection List Mapping + +List processing is very convenient in Scheme because the process of +iterating over the elements of a list can be highly abstracted. The +procedures in this section are the most basic iterating procedures for +lists. They take a procedure and one or more lists as arguments, and +apply the procedure to each element of the list. They differ in their +return value. + +@rnindex map +@c begin (texi-doc-string "guile" "map") +@deffn {Scheme Procedure} map proc arg1 arg2 @dots{} +@deffnx {Scheme Procedure} map-in-order proc arg1 arg2 @dots{} +@deffnx {C Function} scm_map (proc, arg1, args) +Apply @var{proc} to each element of the list @var{arg1} (if only two +arguments are given), or to the corresponding elements of the argument +lists (if more than two arguments are given). The result(s) of the +procedure applications are saved and returned in a list. For +@code{map}, the order of procedure applications is not specified, +@code{map-in-order} applies the procedure from left to right to the list +elements. +@end deffn + +@rnindex for-each +@c begin (texi-doc-string "guile" "for-each") +@deffn {Scheme Procedure} for-each proc arg1 arg2 @dots{} +Like @code{map}, but the procedure is always applied from left to right, +and the result(s) of the procedure applications are thrown away. The +return value is not specified. +@end deffn + +See also SRFI-1 which extends these functions to take lists of unequal +lengths (@ref{SRFI-1 Fold and Map}). + +@node Vectors +@subsection Vectors +@tpindex Vectors + +Vectors are sequences of Scheme objects. Unlike lists, the length of a +vector, once the vector is created, cannot be changed. The advantage of +vectors over lists is that the time required to access one element of a vector +given its @dfn{position} (synonymous with @dfn{index}), a zero-origin number, +is constant, whereas lists have an access time linear to the position of the +accessed element in the list. + +Vectors can contain any kind of Scheme object; it is even possible to +have different types of objects in the same vector. For vectors +containing vectors, you may wish to use arrays, instead. Note, too, +that vectors are the special case of one dimensional non-uniform arrays +and that most array procedures operate happily on vectors +(@pxref{Arrays}). + +Also see @ref{SRFI-43}, for a comprehensive vector library. + +@menu +* Vector Syntax:: Read syntax for vectors. +* Vector Creation:: Dynamic vector creation and validation. +* Vector Accessors:: Accessing and modifying vector contents. +* Vector Accessing from C:: Ways to work with vectors from C. +* Uniform Numeric Vectors:: Vectors of unboxed numeric values. +@end menu + + +@node Vector Syntax +@subsubsection Read Syntax for Vectors + +Vectors can literally be entered in source code, just like strings, +characters or some of the other data types. The read syntax for vectors +is as follows: A sharp sign (@code{#}), followed by an opening +parentheses, all elements of the vector in their respective read syntax, +and finally a closing parentheses. Like strings, vectors do not have to +be quoted. + +The following are examples of the read syntax for vectors; where the +first vector only contains numbers and the second three different object +types: a string, a symbol and a number in hexadecimal notation. + +@lisp +#(1 2 3) +#("Hello" foo #xdeadbeef) +@end lisp + +@node Vector Creation +@subsubsection Dynamic Vector Creation and Validation + +Instead of creating a vector implicitly by using the read syntax just +described, you can create a vector dynamically by calling one of the +@code{vector} and @code{list->vector} primitives with the list of Scheme +values that you want to place into a vector. The size of the vector +thus created is determined implicitly by the number of arguments given. + +@rnindex vector +@rnindex list->vector +@deffn {Scheme Procedure} vector arg @dots{} +@deffnx {Scheme Procedure} list->vector l +@deffnx {C Function} scm_vector (l) +Return a newly allocated vector composed of the +given arguments. Analogous to @code{list}. + +@lisp +(vector 'a 'b 'c) @result{} #(a b c) +@end lisp +@end deffn + +The inverse operation is @code{vector->list}: + +@rnindex vector->list +@deffn {Scheme Procedure} vector->list v +@deffnx {C Function} scm_vector_to_list (v) +Return a newly allocated list composed of the elements of @var{v}. + +@lisp +(vector->list #(dah dah didah)) @result{} (dah dah didah) +(list->vector '(dididit dah)) @result{} #(dididit dah) +@end lisp +@end deffn + +To allocate a vector with an explicitly specified size, use +@code{make-vector}. With this primitive you can also specify an initial +value for the vector elements (the same value for all elements, that +is): + +@rnindex make-vector +@deffn {Scheme Procedure} make-vector len [fill] +@deffnx {C Function} scm_make_vector (len, fill) +Return a newly allocated vector of @var{len} elements. If a +second argument is given, then each position is initialized to +@var{fill}. Otherwise the initial contents of each position is +unspecified. +@end deffn + +@deftypefn {C Function} SCM scm_c_make_vector (size_t k, SCM fill) +Like @code{scm_make_vector}, but the length is given as a @code{size_t}. +@end deftypefn + +To check whether an arbitrary Scheme value @emph{is} a vector, use the +@code{vector?} primitive: + +@rnindex vector? +@deffn {Scheme Procedure} vector? obj +@deffnx {C Function} scm_vector_p (obj) +Return @code{#t} if @var{obj} is a vector, otherwise return +@code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_vector (SCM obj) +Return non-zero when @var{obj} is a vector, otherwise return +@code{zero}. +@end deftypefn + +@node Vector Accessors +@subsubsection Accessing and Modifying Vector Contents + +@code{vector-length} and @code{vector-ref} return information about a +given vector, respectively its size and the elements that are contained +in the vector. + +@rnindex vector-length +@deffn {Scheme Procedure} vector-length vector +@deffnx {C Function} scm_vector_length (vector) +Return the number of elements in @var{vector} as an exact integer. +@end deffn + +@deftypefn {C Function} size_t scm_c_vector_length (SCM vec) +Return the number of elements in @var{vec} as a @code{size_t}. +@end deftypefn + +@rnindex vector-ref +@deffn {Scheme Procedure} vector-ref vec k +@deffnx {C Function} scm_vector_ref (vec, k) +Return the contents of position @var{k} of @var{vec}. +@var{k} must be a valid index of @var{vec}. +@lisp +(vector-ref #(1 1 2 3 5 8 13 21) 5) @result{} 8 +(vector-ref #(1 1 2 3 5 8 13 21) + (let ((i (round (* 2 (acos -1))))) + (if (inexact? i) + (inexact->exact i) + i))) @result{} 13 +@end lisp +@end deffn + +@deftypefn {C Function} SCM scm_c_vector_ref (SCM vec, size_t k) +Return the contents of position @var{k} (a @code{size_t}) of +@var{vec}. +@end deftypefn + +A vector created by one of the dynamic vector constructor procedures +(@pxref{Vector Creation}) can be modified using the following +procedures. + +@emph{NOTE:} According to R5RS, it is an error to use any of these +procedures on a literally read vector, because such vectors should be +considered as constants. Currently, however, Guile does not detect this +error. + +@rnindex vector-set! +@deffn {Scheme Procedure} vector-set! vec k obj +@deffnx {C Function} scm_vector_set_x (vec, k, obj) +Store @var{obj} in position @var{k} of @var{vec}. +@var{k} must be a valid index of @var{vec}. +The value returned by @samp{vector-set!} is unspecified. +@lisp +(let ((vec (vector 0 '(2 2 2 2) "Anna"))) + (vector-set! vec 1 '("Sue" "Sue")) + vec) @result{} #(0 ("Sue" "Sue") "Anna") +@end lisp +@end deffn + +@deftypefn {C Function} void scm_c_vector_set_x (SCM vec, size_t k, SCM obj) +Store @var{obj} in position @var{k} (a @code{size_t}) of @var{vec}. +@end deftypefn + +@rnindex vector-fill! +@deffn {Scheme Procedure} vector-fill! vec fill +@deffnx {C Function} scm_vector_fill_x (vec, fill) +Store @var{fill} in every position of @var{vec}. The value +returned by @code{vector-fill!} is unspecified. +@end deffn + +@deffn {Scheme Procedure} vector-copy vec +@deffnx {C Function} scm_vector_copy (vec) +Return a copy of @var{vec}. +@end deffn + +@deffn {Scheme Procedure} vector-move-left! vec1 start1 end1 vec2 start2 +@deffnx {C Function} scm_vector_move_left_x (vec1, start1, end1, vec2, start2) +Copy elements from @var{vec1}, positions @var{start1} to @var{end1}, +to @var{vec2} starting at position @var{start2}. @var{start1} and +@var{start2} are inclusive indices; @var{end1} is exclusive. + +@code{vector-move-left!} copies elements in leftmost order. +Therefore, in the case where @var{vec1} and @var{vec2} refer to the +same vector, @code{vector-move-left!} is usually appropriate when +@var{start1} is greater than @var{start2}. +@end deffn + +@deffn {Scheme Procedure} vector-move-right! vec1 start1 end1 vec2 start2 +@deffnx {C Function} scm_vector_move_right_x (vec1, start1, end1, vec2, start2) +Copy elements from @var{vec1}, positions @var{start1} to @var{end1}, +to @var{vec2} starting at position @var{start2}. @var{start1} and +@var{start2} are inclusive indices; @var{end1} is exclusive. + +@code{vector-move-right!} copies elements in rightmost order. +Therefore, in the case where @var{vec1} and @var{vec2} refer to the +same vector, @code{vector-move-right!} is usually appropriate when +@var{start1} is less than @var{start2}. +@end deffn + +@node Vector Accessing from C +@subsubsection Vector Accessing from C + +A vector can be read and modified from C with the functions +@code{scm_c_vector_ref} and @code{scm_c_vector_set_x}, for example. In +addition to these functions, there are two more ways to access vectors +from C that might be more efficient in certain situations: you can +restrict yourself to @dfn{simple vectors} and then use the very fast +@emph{simple vector macros}; or you can use the very general framework +for accessing all kinds of arrays (@pxref{Accessing Arrays from C}), +which is more verbose, but can deal efficiently with all kinds of +vectors (and arrays). For vectors, you can use the +@code{scm_vector_elements} and @code{scm_vector_writable_elements} +functions as shortcuts. + +@deftypefn {C Function} int scm_is_simple_vector (SCM obj) +Return non-zero if @var{obj} is a simple vector, else return zero. A +simple vector is a vector that can be used with the @code{SCM_SIMPLE_*} +macros below. + +The following functions are guaranteed to return simple vectors: +@code{scm_make_vector}, @code{scm_c_make_vector}, @code{scm_vector}, +@code{scm_list_to_vector}. +@end deftypefn + +@deftypefn {C Macro} size_t SCM_SIMPLE_VECTOR_LENGTH (SCM vec) +Evaluates to the length of the simple vector @var{vec}. No type +checking is done. +@end deftypefn + +@deftypefn {C Macro} SCM SCM_SIMPLE_VECTOR_REF (SCM vec, size_t idx) +Evaluates to the element at position @var{idx} in the simple vector +@var{vec}. No type or range checking is done. +@end deftypefn + +@deftypefn {C Macro} void SCM_SIMPLE_VECTOR_SET (SCM vec, size_t idx, SCM val) +Sets the element at position @var{idx} in the simple vector +@var{vec} to @var{val}. No type or range checking is done. +@end deftypefn + +@deftypefn {C Function} {const SCM *} scm_vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +Acquire a handle for the vector @var{vec} and return a pointer to the +elements of it. This pointer can only be used to read the elements of +@var{vec}. When @var{vec} is not a vector, an error is signaled. The +handle must eventually be released with +@code{scm_array_handle_release}. + +The variables pointed to by @var{lenp} and @var{incp} are filled with +the number of elements of the vector and the increment (number of +elements) between successive elements, respectively. Successive +elements of @var{vec} need not be contiguous in their underlying +``root vector'' returned here; hence the increment is not necessarily +equal to 1 and may well be negative too (@pxref{Shared Arrays}). + +The following example shows the typical way to use this function. It +creates a list of all elements of @var{vec} (in reverse order). + +@example +scm_t_array_handle handle; +size_t i, len; +ssize_t inc; +const SCM *elt; +SCM list; + +elt = scm_vector_elements (vec, &handle, &len, &inc); +list = SCM_EOL; +for (i = 0; i < len; i++, elt += inc) + list = scm_cons (*elt, list); +scm_array_handle_release (&handle); +@end example + +@end deftypefn + +@deftypefn {C Function} {SCM *} scm_vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +Like @code{scm_vector_elements} but the pointer can be used to modify +the vector. + +The following example shows the typical way to use this function. It +fills a vector with @code{#t}. + +@example +scm_t_array_handle handle; +size_t i, len; +ssize_t inc; +SCM *elt; + +elt = scm_vector_writable_elements (vec, &handle, &len, &inc); +for (i = 0; i < len; i++, elt += inc) + *elt = SCM_BOOL_T; +scm_array_handle_release (&handle); +@end example + +@end deftypefn + +@node Uniform Numeric Vectors +@subsubsection Uniform Numeric Vectors + +A uniform numeric vector is a vector whose elements are all of a single +numeric type. Guile offers uniform numeric vectors for signed and +unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of +floating point values, and complex floating-point numbers of these two +sizes. @xref{SRFI-4}, for more information. + +For many purposes, bytevectors work just as well as uniform vectors, and have +the advantage that they integrate well with binary input and output. +@xref{Bytevectors}, for more information on bytevectors. + +@node Bit Vectors +@subsection Bit Vectors + +@noindent +Bit vectors are zero-origin, one-dimensional arrays of booleans. They +are displayed as a sequence of @code{0}s and @code{1}s prefixed by +@code{#*}, e.g., + +@example +(make-bitvector 8 #f) @result{} +#*00000000 +@end example + +Bit vectors are the special case of one dimensional bit arrays, and can +thus be used with the array procedures, @xref{Arrays}. + +@deffn {Scheme Procedure} bitvector? obj +@deffnx {C Function} scm_bitvector_p (obj) +Return @code{#t} when @var{obj} is a bitvector, else +return @code{#f}. +@end deffn + +@deftypefn {C Function} int scm_is_bitvector (SCM obj) +Return @code{1} when @var{obj} is a bitvector, else return @code{0}. +@end deftypefn + +@deffn {Scheme Procedure} make-bitvector len [fill] +@deffnx {C Function} scm_make_bitvector (len, fill) +Create a new bitvector of length @var{len} and +optionally initialize all elements to @var{fill}. +@end deffn + +@deftypefn {C Function} SCM scm_c_make_bitvector (size_t len, SCM fill) +Like @code{scm_make_bitvector}, but the length is given as a +@code{size_t}. +@end deftypefn + +@deffn {Scheme Procedure} bitvector bit @dots{} +@deffnx {C Function} scm_bitvector (bits) +Create a new bitvector with the arguments as elements. +@end deffn + +@deffn {Scheme Procedure} bitvector-length vec +@deffnx {C Function} scm_bitvector_length (vec) +Return the length of the bitvector @var{vec}. +@end deffn + +@deftypefn {C Function} size_t scm_c_bitvector_length (SCM vec) +Like @code{scm_bitvector_length}, but the length is returned as a +@code{size_t}. +@end deftypefn + +@deffn {Scheme Procedure} bitvector-ref vec idx +@deffnx {C Function} scm_bitvector_ref (vec, idx) +Return the element at index @var{idx} of the bitvector +@var{vec}. +@end deffn + +@deftypefn {C Function} SCM scm_c_bitvector_ref (SCM vec, size_t idx) +Return the element at index @var{idx} of the bitvector +@var{vec}. +@end deftypefn + +@deffn {Scheme Procedure} bitvector-set! vec idx val +@deffnx {C Function} scm_bitvector_set_x (vec, idx, val) +Set the element at index @var{idx} of the bitvector +@var{vec} when @var{val} is true, else clear it. +@end deffn + +@deftypefn {C Function} SCM scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val) +Set the element at index @var{idx} of the bitvector +@var{vec} when @var{val} is true, else clear it. +@end deftypefn + +@deffn {Scheme Procedure} bitvector-fill! vec val +@deffnx {C Function} scm_bitvector_fill_x (vec, val) +Set all elements of the bitvector +@var{vec} when @var{val} is true, else clear them. +@end deffn + +@deffn {Scheme Procedure} list->bitvector list +@deffnx {C Function} scm_list_to_bitvector (list) +Return a new bitvector initialized with the elements +of @var{list}. +@end deffn + +@deffn {Scheme Procedure} bitvector->list vec +@deffnx {C Function} scm_bitvector_to_list (vec) +Return a new list initialized with the elements +of the bitvector @var{vec}. +@end deffn + +@deffn {Scheme Procedure} bit-count bool bitvector +@deffnx {C Function} scm_bit_count (bool, bitvector) +Return a count of how many entries in @var{bitvector} are equal to +@var{bool}. For example, + +@example +(bit-count #f #*000111000) @result{} 6 +@end example +@end deffn + +@deffn {Scheme Procedure} bit-position bool bitvector start +@deffnx {C Function} scm_bit_position (bool, bitvector, start) +Return the index of the first occurrence of @var{bool} in +@var{bitvector}, starting from @var{start}. If there is no @var{bool} +entry between @var{start} and the end of @var{bitvector}, then return +@code{#f}. For example, + +@example +(bit-position #t #*000101 0) @result{} 3 +(bit-position #f #*0001111 3) @result{} #f +@end example +@end deffn + +@deffn {Scheme Procedure} bit-invert! bitvector +@deffnx {C Function} scm_bit_invert_x (bitvector) +Modify @var{bitvector} by replacing each element with its negation. +@end deffn + +@deffn {Scheme Procedure} bit-set*! bitvector uvec bool +@deffnx {C Function} scm_bit_set_star_x (bitvector, uvec, bool) +Set entries of @var{bitvector} to @var{bool}, with @var{uvec} +selecting the entries to change. The return value is unspecified. + +If @var{uvec} is a bit vector, then those entries where it has +@code{#t} are the ones in @var{bitvector} which are set to @var{bool}. +@var{uvec} and @var{bitvector} must be the same length. When +@var{bool} is @code{#t} it's like @var{uvec} is OR'ed into +@var{bitvector}. Or when @var{bool} is @code{#f} it can be seen as an +ANDNOT. + +@example +(define bv #*01000010) +(bit-set*! bv #*10010001 #t) +bv +@result{} #*11010011 +@end example + +If @var{uvec} is a uniform vector of unsigned long integers, then +they're indexes into @var{bitvector} which are set to @var{bool}. + +@example +(define bv #*01000010) +(bit-set*! bv #u(5 2 7) #t) +bv +@result{} #*01100111 +@end example +@end deffn + +@deffn {Scheme Procedure} bit-count* bitvector uvec bool +@deffnx {C Function} scm_bit_count_star (bitvector, uvec, bool) +Return a count of how many entries in @var{bitvector} are equal to +@var{bool}, with @var{uvec} selecting the entries to consider. + +@var{uvec} is interpreted in the same way as for @code{bit-set*!} +above. Namely, if @var{uvec} is a bit vector then entries which have +@code{#t} there are considered in @var{bitvector}. Or if @var{uvec} +is a uniform vector of unsigned long integers then it's the indexes in +@var{bitvector} to consider. + +For example, + +@example +(bit-count* #*01110111 #*11001101 #t) @result{} 3 +(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2 +@end example +@end deffn + +@deftypefn {C Function} {const scm_t_uint32 *} scm_bitvector_elements (SCM vec, scm_t_array_handle *handle, size_t *offp, size_t *lenp, ssize_t *incp) +Like @code{scm_vector_elements} (@pxref{Vector Accessing from C}), but +for bitvectors. The variable pointed to by @var{offp} is set to the +value returned by @code{scm_array_handle_bit_elements_offset}. See +@code{scm_array_handle_bit_elements} for how to use the returned +pointer and the offset. +@end deftypefn + +@deftypefn {C Function} {scm_t_uint32 *} scm_bitvector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *offp, size_t *lenp, ssize_t *incp) +Like @code{scm_bitvector_elements}, but the pointer is good for reading +and writing. +@end deftypefn + +@node Bytevectors +@subsection Bytevectors + +@cindex bytevector +@cindex R6RS + +A @dfn{bytevector} is a raw bit string. The @code{(rnrs bytevectors)} +module provides the programming interface specified by the +@uref{http://www.r6rs.org/, Revised^6 Report on the Algorithmic Language +Scheme (R6RS)}. It contains procedures to manipulate bytevectors and +interpret their contents in a number of ways: bytevector contents can be +accessed as signed or unsigned integer of various sizes and endianness, +as IEEE-754 floating point numbers, or as strings. It is a useful tool +to encode and decode binary data. + +The R6RS (Section 4.3.4) specifies an external representation for +bytevectors, whereby the octets (integers in the range 0--255) contained +in the bytevector are represented as a list prefixed by @code{#vu8}: + +@lisp +#vu8(1 53 204) +@end lisp + +denotes a 3-byte bytevector containing the octets 1, 53, and 204. Like +string literals, booleans, etc., bytevectors are ``self-quoting'', i.e., +they do not need to be quoted: + +@lisp +#vu8(1 53 204) +@result{} #vu8(1 53 204) +@end lisp + +Bytevectors can be used with the binary input/output primitives +(@pxref{Binary I/O}). + +@menu +* Bytevector Endianness:: Dealing with byte order. +* Bytevector Manipulation:: Creating, copying, manipulating bytevectors. +* Bytevectors as Integers:: Interpreting bytes as integers. +* Bytevectors and Integer Lists:: Converting to/from an integer list. +* Bytevectors as Floats:: Interpreting bytes as real numbers. +* Bytevectors as Strings:: Interpreting bytes as Unicode strings. +* Bytevectors as Arrays:: Guile extension to the bytevector API. +* Bytevectors as Uniform Vectors:: Bytevectors and SRFI-4. +@end menu + +@node Bytevector Endianness +@subsubsection Endianness + +@cindex endianness +@cindex byte order +@cindex word order + +Some of the following procedures take an @var{endianness} parameter. +The @dfn{endianness} is defined as the order of bytes in multi-byte +numbers: numbers encoded in @dfn{big endian} have their most +significant bytes written first, whereas numbers encoded in +@dfn{little endian} have their least significant bytes +first@footnote{Big-endian and little-endian are the most common +``endiannesses'', but others do exist. For instance, the GNU MP +library allows @dfn{word order} to be specified independently of +@dfn{byte order} (@pxref{Integer Import and Export,,, gmp, The GNU +Multiple Precision Arithmetic Library Manual}).}. + +Little-endian is the native endianness of the IA32 architecture and +its derivatives, while big-endian is native to SPARC and PowerPC, +among others. The @code{native-endianness} procedure returns the +native endianness of the machine it runs on. + +@deffn {Scheme Procedure} native-endianness +@deffnx {C Function} scm_native_endianness () +Return a value denoting the native endianness of the host machine. +@end deffn + +@deffn {Scheme Macro} endianness symbol +Return an object denoting the endianness specified by @var{symbol}. If +@var{symbol} is neither @code{big} nor @code{little} then an error is +raised at expand-time. +@end deffn + +@defvr {C Variable} scm_endianness_big +@defvrx {C Variable} scm_endianness_little +The objects denoting big- and little-endianness, respectively. +@end defvr + + +@node Bytevector Manipulation +@subsubsection Manipulating Bytevectors + +Bytevectors can be created, copied, and analyzed with the following +procedures and C functions. + +@deffn {Scheme Procedure} make-bytevector len [fill] +@deffnx {C Function} scm_make_bytevector (len, fill) +@deffnx {C Function} scm_c_make_bytevector (size_t len) +Return a new bytevector of @var{len} bytes. Optionally, if @var{fill} +is given, fill it with @var{fill}; @var{fill} must be in the range +[-128,255]. +@end deffn + +@deffn {Scheme Procedure} bytevector? obj +@deffnx {C Function} scm_bytevector_p (obj) +Return true if @var{obj} is a bytevector. +@end deffn + +@deftypefn {C Function} int scm_is_bytevector (SCM obj) +Equivalent to @code{scm_is_true (scm_bytevector_p (obj))}. +@end deftypefn + +@deffn {Scheme Procedure} bytevector-length bv +@deffnx {C Function} scm_bytevector_length (bv) +Return the length in bytes of bytevector @var{bv}. +@end deffn + +@deftypefn {C Function} size_t scm_c_bytevector_length (SCM bv) +Likewise, return the length in bytes of bytevector @var{bv}. +@end deftypefn + +@deffn {Scheme Procedure} bytevector=? bv1 bv2 +@deffnx {C Function} scm_bytevector_eq_p (bv1, bv2) +Return is @var{bv1} equals to @var{bv2}---i.e., if they have the same +length and contents. +@end deffn + +@deffn {Scheme Procedure} bytevector-fill! bv fill +@deffnx {C Function} scm_bytevector_fill_x (bv, fill) +Fill bytevector @var{bv} with @var{fill}, a byte. +@end deffn + +@deffn {Scheme Procedure} bytevector-copy! source source-start target target-start len +@deffnx {C Function} scm_bytevector_copy_x (source, source_start, target, target_start, len) +Copy @var{len} bytes from @var{source} into @var{target}, starting +reading from @var{source-start} (a positive index within @var{source}) +and start writing at @var{target-start}. It is permitted for the +@var{source} and @var{target} regions to overlap. +@end deffn + +@deffn {Scheme Procedure} bytevector-copy bv +@deffnx {C Function} scm_bytevector_copy (bv) +Return a newly allocated copy of @var{bv}. +@end deffn + +@deftypefn {C Function} scm_t_uint8 scm_c_bytevector_ref (SCM bv, size_t index) +Return the byte at @var{index} in bytevector @var{bv}. +@end deftypefn + +@deftypefn {C Function} void scm_c_bytevector_set_x (SCM bv, size_t index, scm_t_uint8 value) +Set the byte at @var{index} in @var{bv} to @var{value}. +@end deftypefn + +Low-level C macros are available. They do not perform any +type-checking; as such they should be used with care. + +@deftypefn {C Macro} size_t SCM_BYTEVECTOR_LENGTH (bv) +Return the length in bytes of bytevector @var{bv}. +@end deftypefn + +@deftypefn {C Macro} {signed char *} SCM_BYTEVECTOR_CONTENTS (bv) +Return a pointer to the contents of bytevector @var{bv}. +@end deftypefn + + +@node Bytevectors as Integers +@subsubsection Interpreting Bytevector Contents as Integers + +The contents of a bytevector can be interpreted as a sequence of +integers of any given size, sign, and endianness. + +@lisp +(let ((bv (make-bytevector 4))) + (bytevector-u8-set! bv 0 #x12) + (bytevector-u8-set! bv 1 #x34) + (bytevector-u8-set! bv 2 #x56) + (bytevector-u8-set! bv 3 #x78) + + (map (lambda (number) + (number->string number 16)) + (list (bytevector-u8-ref bv 0) + (bytevector-u16-ref bv 0 (endianness big)) + (bytevector-u32-ref bv 0 (endianness little))))) + +@result{} ("12" "1234" "78563412") +@end lisp + +The most generic procedures to interpret bytevector contents as integers +are described below. + +@deffn {Scheme Procedure} bytevector-uint-ref bv index endianness size +@deffnx {C Function} scm_bytevector_uint_ref (bv, index, endianness, size) +Return the @var{size}-byte long unsigned integer at index @var{index} in +@var{bv}, decoded according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector-sint-ref bv index endianness size +@deffnx {C Function} scm_bytevector_sint_ref (bv, index, endianness, size) +Return the @var{size}-byte long signed integer at index @var{index} in +@var{bv}, decoded according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector-uint-set! bv index value endianness size +@deffnx {C Function} scm_bytevector_uint_set_x (bv, index, value, endianness, size) +Set the @var{size}-byte long unsigned integer at @var{index} to +@var{value}, encoded according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector-sint-set! bv index value endianness size +@deffnx {C Function} scm_bytevector_sint_set_x (bv, index, value, endianness, size) +Set the @var{size}-byte long signed integer at @var{index} to +@var{value}, encoded according to @var{endianness}. +@end deffn + +The following procedures are similar to the ones above, but specialized +to a given integer size: + +@deffn {Scheme Procedure} bytevector-u8-ref bv index +@deffnx {Scheme Procedure} bytevector-s8-ref bv index +@deffnx {Scheme Procedure} bytevector-u16-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-s16-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-u32-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-s32-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-u64-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-s64-ref bv index endianness +@deffnx {C Function} scm_bytevector_u8_ref (bv, index) +@deffnx {C Function} scm_bytevector_s8_ref (bv, index) +@deffnx {C Function} scm_bytevector_u16_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_s16_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_u32_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_s32_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_u64_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_s64_ref (bv, index, endianness) +Return the unsigned @var{n}-bit (signed) integer (where @var{n} is 8, +16, 32 or 64) from @var{bv} at @var{index}, decoded according to +@var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector-u8-set! bv index value +@deffnx {Scheme Procedure} bytevector-s8-set! bv index value +@deffnx {Scheme Procedure} bytevector-u16-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-s16-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-u32-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-s32-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-u64-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-s64-set! bv index value endianness +@deffnx {C Function} scm_bytevector_u8_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_s8_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_u16_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_s16_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_u32_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_s32_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_u64_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_s64_set_x (bv, index, value, endianness) +Store @var{value} as an @var{n}-bit (signed) integer (where @var{n} is +8, 16, 32 or 64) in @var{bv} at @var{index}, encoded according to +@var{endianness}. +@end deffn + +Finally, a variant specialized for the host's endianness is available +for each of these functions (with the exception of the @code{u8} and +@code{s8} accessors, as endianness is about byte order and there is only +1 byte): + +@deffn {Scheme Procedure} bytevector-u16-native-ref bv index +@deffnx {Scheme Procedure} bytevector-s16-native-ref bv index +@deffnx {Scheme Procedure} bytevector-u32-native-ref bv index +@deffnx {Scheme Procedure} bytevector-s32-native-ref bv index +@deffnx {Scheme Procedure} bytevector-u64-native-ref bv index +@deffnx {Scheme Procedure} bytevector-s64-native-ref bv index +@deffnx {C Function} scm_bytevector_u16_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_s16_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_u32_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_s32_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_u64_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_s64_native_ref (bv, index) +Return the unsigned @var{n}-bit (signed) integer (where @var{n} is 8, +16, 32 or 64) from @var{bv} at @var{index}, decoded according to the +host's native endianness. +@end deffn + +@deffn {Scheme Procedure} bytevector-u16-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-s16-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-u32-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-s32-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-u64-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-s64-native-set! bv index value +@deffnx {C Function} scm_bytevector_u16_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_s16_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_u32_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_s32_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_u64_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_s64_native_set_x (bv, index, value) +Store @var{value} as an @var{n}-bit (signed) integer (where @var{n} is +8, 16, 32 or 64) in @var{bv} at @var{index}, encoded according to the +host's native endianness. +@end deffn + + +@node Bytevectors and Integer Lists +@subsubsection Converting Bytevectors to/from Integer Lists + +Bytevector contents can readily be converted to/from lists of signed or +unsigned integers: + +@lisp +(bytevector->sint-list (u8-list->bytevector (make-list 4 255)) + (endianness little) 2) +@result{} (-1 -1) +@end lisp + +@deffn {Scheme Procedure} bytevector->u8-list bv +@deffnx {C Function} scm_bytevector_to_u8_list (bv) +Return a newly allocated list of unsigned 8-bit integers from the +contents of @var{bv}. +@end deffn + +@deffn {Scheme Procedure} u8-list->bytevector lst +@deffnx {C Function} scm_u8_list_to_bytevector (lst) +Return a newly allocated bytevector consisting of the unsigned 8-bit +integers listed in @var{lst}. +@end deffn + +@deffn {Scheme Procedure} bytevector->uint-list bv endianness size +@deffnx {C Function} scm_bytevector_to_uint_list (bv, endianness, size) +Return a list of unsigned integers of @var{size} bytes representing the +contents of @var{bv}, decoded according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector->sint-list bv endianness size +@deffnx {C Function} scm_bytevector_to_sint_list (bv, endianness, size) +Return a list of signed integers of @var{size} bytes representing the +contents of @var{bv}, decoded according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} uint-list->bytevector lst endianness size +@deffnx {C Function} scm_uint_list_to_bytevector (lst, endianness, size) +Return a new bytevector containing the unsigned integers listed in +@var{lst} and encoded on @var{size} bytes according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} sint-list->bytevector lst endianness size +@deffnx {C Function} scm_sint_list_to_bytevector (lst, endianness, size) +Return a new bytevector containing the signed integers listed in +@var{lst} and encoded on @var{size} bytes according to @var{endianness}. +@end deffn + +@node Bytevectors as Floats +@subsubsection Interpreting Bytevector Contents as Floating Point Numbers + +@cindex IEEE-754 floating point numbers + +Bytevector contents can also be accessed as IEEE-754 single- or +double-precision floating point numbers (respectively 32 and 64-bit +long) using the procedures described here. + +@deffn {Scheme Procedure} bytevector-ieee-single-ref bv index endianness +@deffnx {Scheme Procedure} bytevector-ieee-double-ref bv index endianness +@deffnx {C Function} scm_bytevector_ieee_single_ref (bv, index, endianness) +@deffnx {C Function} scm_bytevector_ieee_double_ref (bv, index, endianness) +Return the IEEE-754 single-precision floating point number from @var{bv} +at @var{index} according to @var{endianness}. +@end deffn + +@deffn {Scheme Procedure} bytevector-ieee-single-set! bv index value endianness +@deffnx {Scheme Procedure} bytevector-ieee-double-set! bv index value endianness +@deffnx {C Function} scm_bytevector_ieee_single_set_x (bv, index, value, endianness) +@deffnx {C Function} scm_bytevector_ieee_double_set_x (bv, index, value, endianness) +Store real number @var{value} in @var{bv} at @var{index} according to +@var{endianness}. +@end deffn + +Specialized procedures are also available: + +@deffn {Scheme Procedure} bytevector-ieee-single-native-ref bv index +@deffnx {Scheme Procedure} bytevector-ieee-double-native-ref bv index +@deffnx {C Function} scm_bytevector_ieee_single_native_ref (bv, index) +@deffnx {C Function} scm_bytevector_ieee_double_native_ref (bv, index) +Return the IEEE-754 single-precision floating point number from @var{bv} +at @var{index} according to the host's native endianness. +@end deffn + +@deffn {Scheme Procedure} bytevector-ieee-single-native-set! bv index value +@deffnx {Scheme Procedure} bytevector-ieee-double-native-set! bv index value +@deffnx {C Function} scm_bytevector_ieee_single_native_set_x (bv, index, value) +@deffnx {C Function} scm_bytevector_ieee_double_native_set_x (bv, index, value) +Store real number @var{value} in @var{bv} at @var{index} according to +the host's native endianness. +@end deffn + + +@node Bytevectors as Strings +@subsubsection Interpreting Bytevector Contents as Unicode Strings + +@cindex Unicode string encoding + +Bytevector contents can also be interpreted as Unicode strings encoded +in one of the most commonly available encoding formats. +@xref{Representing Strings as Bytes}, for a more generic interface. + +@lisp +(utf8->string (u8-list->bytevector '(99 97 102 101))) +@result{} "cafe" + +(string->utf8 "caf@'e") ;; SMALL LATIN LETTER E WITH ACUTE ACCENT +@result{} #vu8(99 97 102 195 169) +@end lisp + +@deftypefn {Scheme Procedure} {} string-utf8-length str +@deftypefnx {C function} SCM scm_string_utf8_length (str) +@deftypefnx {C function} size_t scm_c_string_utf8_length (str) +Return the number of bytes in the UTF-8 representation of @var{str}. +@end deftypefn + +@deffn {Scheme Procedure} string->utf8 str +@deffnx {Scheme Procedure} string->utf16 str [endianness] +@deffnx {Scheme Procedure} string->utf32 str [endianness] +@deffnx {C Function} scm_string_to_utf8 (str) +@deffnx {C Function} scm_string_to_utf16 (str, endianness) +@deffnx {C Function} scm_string_to_utf32 (str, endianness) +Return a newly allocated bytevector that contains the UTF-8, UTF-16, or +UTF-32 (aka. UCS-4) encoding of @var{str}. For UTF-16 and UTF-32, +@var{endianness} should be the symbol @code{big} or @code{little}; when omitted, +it defaults to big endian. +@end deffn + +@deffn {Scheme Procedure} utf8->string utf +@deffnx {Scheme Procedure} utf16->string utf [endianness] +@deffnx {Scheme Procedure} utf32->string utf [endianness] +@deffnx {C Function} scm_utf8_to_string (utf) +@deffnx {C Function} scm_utf16_to_string (utf, endianness) +@deffnx {C Function} scm_utf32_to_string (utf, endianness) +Return a newly allocated string that contains from the UTF-8-, UTF-16-, +or UTF-32-decoded contents of bytevector @var{utf}. For UTF-16 and UTF-32, +@var{endianness} should be the symbol @code{big} or @code{little}; when omitted, +it defaults to big endian. +@end deffn + +@node Bytevectors as Arrays +@subsubsection Accessing Bytevectors with the Array API + +As an extension to the R6RS, Guile allows bytevectors to be manipulated +with the @dfn{array} procedures (@pxref{Arrays}). When using these +APIs, bytes are accessed one at a time as 8-bit unsigned integers: + +@example +(define bv #vu8(0 1 2 3)) + +(array? bv) +@result{} #t + +(array-rank bv) +@result{} 1 + +(array-ref bv 2) +@result{} 2 + +;; Note the different argument order on array-set!. +(array-set! bv 77 2) +(array-ref bv 2) +@result{} 77 + +(array-type bv) +@result{} vu8 +@end example + + +@node Bytevectors as Uniform Vectors +@subsubsection Accessing Bytevectors with the SRFI-4 API + +Bytevectors may also be accessed with the SRFI-4 API. @xref{SRFI-4 and +Bytevectors}, for more information. + + +@node Arrays +@subsection Arrays +@tpindex Arrays + +@dfn{Arrays} are a collection of cells organized into an arbitrary +number of dimensions. Each cell can be accessed in constant time by +supplying an index for each dimension. + +In the current implementation, an array uses a vector of some kind for +the actual storage of its elements. Any kind of vector will do, so you +can have arrays of uniform numeric values, arrays of characters, arrays +of bits, and of course, arrays of arbitrary Scheme values. For example, +arrays with an underlying @code{c64vector} might be nice for digital +signal processing, while arrays made from a @code{u8vector} might be +used to hold gray-scale images. + +The number of dimensions of an array is called its @dfn{rank}. Thus, +a matrix is an array of rank 2, while a vector has rank 1. When +accessing an array element, you have to specify one exact integer for +each dimension. These integers are called the @dfn{indices} of the +element. An array specifies the allowed range of indices for each +dimension via an inclusive lower and upper bound. These bounds can +well be negative, but the upper bound must be greater than or equal to +the lower bound minus one. When all lower bounds of an array are +zero, it is called a @dfn{zero-origin} array. + +Arrays can be of rank 0, which could be interpreted as a scalar. +Thus, a zero-rank array can store exactly one object and the list of +indices of this element is the empty list. + +Arrays contain zero elements when one of their dimensions has a zero +length. These empty arrays maintain information about their shape: a +matrix with zero columns and 3 rows is different from a matrix with 3 +columns and zero rows, which again is different from a vector of +length zero. + +The array procedures are all polymorphic, treating strings, uniform +numeric vectors, bytevectors, bit vectors and ordinary vectors as one +dimensional arrays. + +@menu +* Array Syntax:: +* Array Procedures:: +* Shared Arrays:: +* Arrays as arrays of arrays:: +* Accessing Arrays from C:: +@end menu + +@node Array Syntax +@subsubsection Array Syntax + +An array is displayed as @code{#} followed by its rank, followed by a +tag that describes the underlying vector, optionally followed by +information about its shape, and finally followed by the cells, +organized into dimensions using parentheses. + +In more words, the array tag is of the form + +@example + #<rank><vectag><@@lower><:len><@@lower><:len>... +@end example + +where @code{<rank>} is a positive integer in decimal giving the rank of +the array. It is omitted when the rank is 1 and the array is non-shared +and has zero-origin (see below). For shared arrays and for a non-zero +origin, the rank is always printed even when it is 1 to distinguish +them from ordinary vectors. + +The @code{<vectag>} part is the tag for a uniform numeric vector, like +@code{u8}, @code{s16}, etc, @code{b} for bitvectors, or @code{a} for +strings. It is empty for ordinary vectors. + +The @code{<@@lower>} part is a @samp{@@} character followed by a signed +integer in decimal giving the lower bound of a dimension. There is one +@code{<@@lower>} for each dimension. When all lower bounds are zero, +all @code{<@@lower>} parts are omitted. + +The @code{<:len>} part is a @samp{:} character followed by an unsigned +integer in decimal giving the length of a dimension. Like for the lower +bounds, there is one @code{<:len>} for each dimension, and the +@code{<:len>} part always follows the @code{<@@lower>} part for a +dimension. Lengths are only then printed when they can't be deduced +from the nested lists of elements of the array literal, which can happen +when at least one length is zero. + +As a special case, an array of rank 0 is printed as +@code{#0<vectag>(<scalar>)}, where @code{<scalar>} is the result of +printing the single element of the array. + +Thus, + +@table @code +@item #(1 2 3) +is an ordinary array of rank 1 with lower bound 0 in dimension 0. +(I.e., a regular vector.) + +@item #@@2(1 2 3) +is an ordinary array of rank 1 with lower bound 2 in dimension 0. + +@item #2((1 2 3) (4 5 6)) +is a non-uniform array of rank 2; a 2@cross{}3 matrix with index ranges 0..1 +and 0..2. + +@item #u8(0 1 2) +is a uniform u8 array of rank 1. + +@item #2u32@@2@@3((1 2) (2 3)) +is a uniform u32 array of rank 2 with index ranges 2..3 and 3..4. + +@item #2() +is a two-dimensional array with index ranges 0..-1 and 0..-1, i.e.@: +both dimensions have length zero. + +@item #2:0:2() +is a two-dimensional array with index ranges 0..-1 and 0..1, i.e.@: the +first dimension has length zero, but the second has length 2. + +@item #0(12) +is a rank-zero array with contents 12. + +@end table + +In addition, bytevectors are also arrays, but use a different syntax +(@pxref{Bytevectors}): + +@table @code + +@item #vu8(1 2 3) +is a 3-byte long bytevector, with contents 1, 2, 3. + +@end table + +@node Array Procedures +@subsubsection Array Procedures + +When an array is created, the range of each dimension must be +specified, e.g., to create a 2@cross{}3 array with a zero-based index: + +@example +(make-array 'ho 2 3) @result{} #2((ho ho ho) (ho ho ho)) +@end example + +The range of each dimension can also be given explicitly, e.g., another +way to create the same array: + +@example +(make-array 'ho '(0 1) '(0 2)) @result{} #2((ho ho ho) (ho ho ho)) +@end example + +The following procedures can be used with arrays (or vectors). An +argument shown as @var{idx}@dots{} means one parameter for each +dimension in the array. A @var{idxlist} argument means a list of such +values, one for each dimension. + + +@deffn {Scheme Procedure} array? obj +@deffnx {C Function} scm_array_p (obj, unused) +Return @code{#t} if the @var{obj} is an array, and @code{#f} if +not. + +The second argument to scm_array_p is there for historical reasons, +but it is not used. You should always pass @code{SCM_UNDEFINED} as +its value. +@end deffn + +@deffn {Scheme Procedure} typed-array? obj type +@deffnx {C Function} scm_typed_array_p (obj, type) +Return @code{#t} if the @var{obj} is an array of type @var{type}, and +@code{#f} if not. +@end deffn + +@deftypefn {C Function} int scm_is_array (SCM obj) +Return @code{1} if the @var{obj} is an array and @code{0} if not. +@end deftypefn + +@deftypefn {C Function} int scm_is_typed_array (SCM obj, SCM type) +Return @code{0} if the @var{obj} is an array of type @var{type}, and +@code{1} if not. +@end deftypefn + +@deffn {Scheme Procedure} make-array fill bound @dots{} +@deffnx {C Function} scm_make_array (fill, bounds) +Equivalent to @code{(make-typed-array #t @var{fill} @var{bound} ...)}. +@end deffn + +@deffn {Scheme Procedure} make-typed-array type fill bound @dots{} +@deffnx {C Function} scm_make_typed_array (type, fill, bounds) +Create and return an array that has as many dimensions as there are +@var{bound}s and (maybe) fill it with @var{fill}. + +The underlying storage vector is created according to @var{type}, +which must be a symbol whose name is the `vectag' of the array as +explained above, or @code{#t} for ordinary, non-specialized arrays. + +For example, using the symbol @code{f64} for @var{type} will create an +array that uses a @code{f64vector} for storing its elements, and +@code{a} will use a string. + +When @var{fill} is not the special @emph{unspecified} value, the new +array is filled with @var{fill}. Otherwise, the initial contents of +the array is unspecified. The special @emph{unspecified} value is +stored in the variable @code{*unspecified*} so that for example +@code{(make-typed-array 'u32 *unspecified* 4)} creates a uninitialized +@code{u32} vector of length 4. + +Each @var{bound} may be a positive non-zero integer @var{n}, in which +case the index for that dimension can range from 0 through @var{n}-1; or +an explicit index range specifier in the form @code{(LOWER UPPER)}, +where both @var{lower} and @var{upper} are integers, possibly less than +zero, and possibly the same number (however, @var{lower} cannot be +greater than @var{upper}). +@end deffn + +@deffn {Scheme Procedure} list->array dimspec list +Equivalent to @code{(list->typed-array #t @var{dimspec} +@var{list})}. +@end deffn + +@deffn {Scheme Procedure} list->typed-array type dimspec list +@deffnx {C Function} scm_list_to_typed_array (type, dimspec, list) +Return an array of the type indicated by @var{type} with elements the +same as those of @var{list}. + +The argument @var{dimspec} determines the number of dimensions of the +array and their lower bounds. When @var{dimspec} is an exact integer, +it gives the number of dimensions directly and all lower bounds are +zero. When it is a list of exact integers, then each element is the +lower index bound of a dimension, and there will be as many dimensions +as elements in the list. +@end deffn + +@deffn {Scheme Procedure} array-type array +@deffnx {C Function} scm_array_type (array) +Return the type of @var{array}. This is the `vectag' used for +printing @var{array} (or @code{#t} for ordinary arrays) and can be +used with @code{make-typed-array} to create an array of the same kind +as @var{array}. +@end deffn + +@deffn {Scheme Procedure} array-ref array idx @dots{} +@deffnx {C Function} scm_array_ref (array, idxlist) +Return the element at @code{(idx @dots{})} in @var{array}. + +@example +(define a (make-array 999 '(1 2) '(3 4))) +(array-ref a 2 4) @result{} 999 +@end example +@end deffn + +@deffn {Scheme Procedure} array-in-bounds? array idx @dots{} +@deffnx {C Function} scm_array_in_bounds_p (array, idxlist) +Return @code{#t} if the given indices would be acceptable to +@code{array-ref}. + +@example +(define a (make-array #f '(1 2) '(3 4))) +(array-in-bounds? a 2 3) @result{} #t +(array-in-bounds? a 0 0) @result{} #f +@end example +@end deffn + +@deffn {Scheme Procedure} array-set! array obj idx @dots{} +@deffnx {C Function} scm_array_set_x (array, obj, idxlist) +Set the element at @code{(idx @dots{})} in @var{array} to @var{obj}. +The return value is unspecified. + +@example +(define a (make-array #f '(0 1) '(0 1))) +(array-set! a #t 1 1) +a @result{} #2((#f #f) (#f #t)) +@end example +@end deffn + +@deffn {Scheme Procedure} array-shape array +@deffnx {Scheme Procedure} array-dimensions array +@deffnx {C Function} scm_array_dimensions (array) +Return a list of the bounds for each dimension of @var{array}. + +@code{array-shape} gives @code{(@var{lower} @var{upper})} for each +dimension. @code{array-dimensions} instead returns just +@math{@var{upper}+1} for dimensions with a 0 lower bound. Both are +suitable as input to @code{make-array}. + +For example, + +@example +(define a (make-array 'foo '(-1 3) 5)) +(array-shape a) @result{} ((-1 3) (0 4)) +(array-dimensions a) @result{} ((-1 3) 5) +@end example +@end deffn + +@deffn {Scheme Procedure} array-length array +@deffnx {C Function} scm_array_length (array) +@deffnx {C Function} size_t scm_c_array_length (array) +Return the length of an array: its first dimension. It is an error to +ask for the length of an array of rank 0. +@end deffn + +@deffn {Scheme Procedure} array-rank array +@deffnx {C Function} scm_array_rank (array) +Return the rank of @var{array}. +@end deffn + +@deftypefn {C Function} size_t scm_c_array_rank (SCM array) +Return the rank of @var{array} as a @code{size_t}. +@end deftypefn + +@deffn {Scheme Procedure} array->list array +@deffnx {C Function} scm_array_to_list (array) +Return a list consisting of all the elements, in order, of +@var{array}. +@end deffn + +@c FIXME: Describe how the order affects the copying (it matters for +@c shared arrays with the same underlying root vector, presumably). +@c +@deffn {Scheme Procedure} array-copy! src dst +@deffnx {Scheme Procedure} array-copy-in-order! src dst +@deffnx {C Function} scm_array_copy_x (src, dst) +Copy every element from vector or array @var{src} to the corresponding +element of @var{dst}. @var{dst} must have the same rank as @var{src}, +and be at least as large in each dimension. The return value is +unspecified. +@end deffn + +@deffn {Scheme Procedure} array-fill! array fill +@deffnx {C Function} scm_array_fill_x (array, fill) +Store @var{fill} in every element of @var{array}. The value returned +is unspecified. +@end deffn + +@c begin (texi-doc-string "guile" "array-equal?") +@deffn {Scheme Procedure} array-equal? array @dots{} +Return @code{#t} if all arguments are arrays with the same shape, the +same type, and have corresponding elements which are either +@code{equal?} or @code{array-equal?}. This function differs from +@code{equal?} (@pxref{Equality}) in that all arguments must be arrays. +@end deffn + +@c FIXME: array-for-each doesn't say what happens if the sources have +@c different index ranges. The code currently iterates over the +@c indices of the first and expects the others to cover those. That +@c at least vaguely matches array-map!, but is it meant to be a +@c documented feature? + +@deffn {Scheme Procedure} array-map! dst proc src @dots{} +@deffnx {Scheme Procedure} array-map-in-order! dst proc src @dots{} +@deffnx {C Function} scm_array_map_x (dst, proc, srclist) +Set each element of the @var{dst} array to values obtained from calls to +@var{proc}. The list of @var{src} arguments may be empty. The value +returned is unspecified. + +Each call is @code{(@var{proc} @var{elem} @dots{})}, where each +@var{elem} is from the corresponding @var{src} array, at the +@var{dst} index. @code{array-map-in-order!} makes the calls in +row-major order, @code{array-map!} makes them in an unspecified order. + +The @var{src} arrays must have the same number of dimensions as +@var{dst}, and must have a range for each dimension which covers the +range in @var{dst}. This ensures all @var{dst} indices are valid in +each @var{src}. +@end deffn + +@deffn {Scheme Procedure} array-for-each proc src1 src2 @dots{} +@deffnx {C Function} scm_array_for_each (proc, src1, srclist) +Apply @var{proc} to each tuple of elements of @var{src1} @var{src2} +@dots{}, in row-major order. The value returned is unspecified. +@end deffn + +@deffn {Scheme Procedure} array-index-map! dst proc +@deffnx {C Function} scm_array_index_map_x (dst, proc) +Set each element of the @var{dst} array to values returned by calls to +@var{proc}. The value returned is unspecified. + +Each call is @code{(@var{proc} @var{i1} @dots{} @var{iN})}, where +@var{i1}@dots{}@var{iN} is the destination index, one parameter for +each dimension. The order in which the calls are made is unspecified. + +For example, to create a @m{4\times4, 4x4} matrix representing a +cyclic group, + +@tex +\advance\leftskip by 2\lispnarrowing { +$\left(\matrix{% +0 & 1 & 2 & 3 \cr +1 & 2 & 3 & 0 \cr +2 & 3 & 0 & 1 \cr +3 & 0 & 1 & 2 \cr +}\right)$} \par +@end tex +@ifnottex +@example + / 0 1 2 3 \ + | 1 2 3 0 | + | 2 3 0 1 | + \ 3 0 1 2 / +@end example +@end ifnottex + +@example +(define a (make-array #f 4 4)) +(array-index-map! a (lambda (i j) + (modulo (+ i j) 4))) +@end example +@end deffn + +An additional array function is available in the module +@code{(ice-9 arrays)}. It can be used with: + +@example +(use-modules (ice-9 arrays)) +@end example + +@deffn {Scheme Procedure} array-copy src +Return a new array with the same elements, type and shape as +@var{src}. However, the array increments may not be the same as those of +@var{src}. In the current implementation, the returned array will be in +row-major order, but that might change in the future. Use +@code{array-copy!} on an array of known order if that is a concern. +@end deffn + +@node Shared Arrays +@subsubsection Shared Arrays + +@deffn {Scheme Procedure} make-shared-array oldarray mapfunc bound @dots{} +@deffnx {C Function} scm_make_shared_array (oldarray, mapfunc, boundlist) +Return a new array which shares the storage of @var{oldarray}. +Changes made through either affect the same underlying storage. The +@var{bound} @dots{} arguments are the shape of the new array, the same +as @code{make-array} (@pxref{Array Procedures}). + +@var{mapfunc} translates coordinates from the new array to the +@var{oldarray}. It's called as @code{(@var{mapfunc} newidx1 @dots{})} +with one parameter for each dimension of the new array, and should +return a list of indices for @var{oldarray}, one for each dimension of +@var{oldarray}. + +@var{mapfunc} must be affine linear, meaning that each @var{oldarray} +index must be formed by adding integer multiples (possibly negative) +of some or all of @var{newidx1} etc, plus a possible integer offset. +The multiples and offset must be the same in each call. + +@sp 1 +One good use for a shared array is to restrict the range of some +dimensions, so as to apply say @code{array-for-each} or +@code{array-fill!} to only part of an array. The plain @code{list} +function can be used for @var{mapfunc} in this case, making no changes +to the index values. For example, + +@example +(make-shared-array #2((a b c) (d e f) (g h i)) list 3 2) +@result{} #2((a b) (d e) (g h)) +@end example + +The new array can have fewer dimensions than @var{oldarray}, for +example to take a column from an array. + +@example +(make-shared-array #2((a b c) (d e f) (g h i)) + (lambda (i) (list i 2)) + '(0 2)) +@result{} #1(c f i) +@end example + +A diagonal can be taken by using the single new array index for both +row and column in the old array. For example, + +@example +(make-shared-array #2((a b c) (d e f) (g h i)) + (lambda (i) (list i i)) + '(0 2)) +@result{} #1(a e i) +@end example + +Dimensions can be increased by for instance considering portions of a +one dimensional array as rows in a two dimensional array. +(@code{array-contents} below can do the opposite, flattening an +array.) + +@example +(make-shared-array #1(a b c d e f g h i j k l) + (lambda (i j) (list (+ (* i 3) j))) + 4 3) +@result{} #2((a b c) (d e f) (g h i) (j k l)) +@end example + +By negating an index the order that elements appear can be reversed. +The following just reverses the column order, + +@example +(make-shared-array #2((a b c) (d e f) (g h i)) + (lambda (i j) (list i (- 2 j))) + 3 3) +@result{} #2((c b a) (f e d) (i h g)) +@end example + +A fixed offset on indexes allows for instance a change from a 0 based +to a 1 based array, + +@example +(define x #2((a b c) (d e f) (g h i))) +(define y (make-shared-array x + (lambda (i j) (list (1- i) (1- j))) + '(1 3) '(1 3))) +(array-ref x 0 0) @result{} a +(array-ref y 1 1) @result{} a +@end example + +A multiple on an index allows every Nth element of an array to be +taken. The following is every third element, + +@example +(make-shared-array #1(a b c d e f g h i j k l) + (lambda (i) (list (* i 3))) + 4) +@result{} #1(a d g j) +@end example + +The above examples can be combined to make weird and wonderful +selections from an array, but it's important to note that because +@var{mapfunc} must be affine linear, arbitrary permutations are not +possible. + +In the current implementation, @var{mapfunc} is not called for every +access to the new array but only on some sample points to establish a +base and stride for new array indices in @var{oldarray} data. A few +sample points are enough because @var{mapfunc} is linear. +@end deffn + +@deffn {Scheme Procedure} shared-array-increments array +@deffnx {C Function} scm_shared_array_increments (array) +For each dimension, return the distance between elements in the root vector. +@end deffn + +@deffn {Scheme Procedure} shared-array-offset array +@deffnx {C Function} scm_shared_array_offset (array) +Return the root vector index of the first element in the array. +@end deffn + +@deffn {Scheme Procedure} shared-array-root array +@deffnx {C Function} scm_shared_array_root (array) +Return the root vector of a shared array. +@end deffn + +@deffn {Scheme Procedure} array-contents array [strict] +@deffnx {C Function} scm_array_contents (array, strict) +If @var{array} may be @dfn{unrolled} into a one dimensional shared array +without changing their order (last subscript changing fastest), then +@code{array-contents} returns that shared array, otherwise it returns +@code{#f}. All arrays made by @code{make-array} and +@code{make-typed-array} may be unrolled, some arrays made by +@code{make-shared-array} may not be. + +If the optional argument @var{strict} is provided, a shared array will +be returned only if its elements are stored internally contiguous in +memory. +@end deffn + +@deffn {Scheme Procedure} transpose-array array dim1 dim2 @dots{} +@deffnx {C Function} scm_transpose_array (array, dimlist) +Return an array sharing contents with @var{array}, but with +dimensions arranged in a different order. There must be one +@var{dim} argument for each dimension of @var{array}. +@var{dim1}, @var{dim2}, @dots{} should be integers between 0 +and the rank of the array to be returned. Each integer in that +range must appear at least once in the argument list. + +The values of @var{dim1}, @var{dim2}, @dots{} correspond to +dimensions in the array to be returned, and their positions in the +argument list to dimensions of @var{array}. Several @var{dim}s +may have the same value, in which case the returned array will +have smaller rank than @var{array}. + +@lisp +(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d)) +(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d) +(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{} + #2((a 4) (b 5) (c 6)) +@end lisp +@end deffn + +@node Arrays as arrays of arrays +@subsubsection Arrays as arrays of arrays + +@cindex array cell + +Mathematically, one can see an array of rank @math{n} (an +@math{n}-array) as an array of lower rank where the elements are +themselves arrays (`cells'). + +@cindex array frame +@cindex frame rank + +We speak of the first @math{n-k} dimensions of the array as the +@math{n-k}-`frame' of the array, while the last @math{k} dimensions are +the dimensions of the @math{k}-`cells'. For example, a 3-array can be +seen as a 2-array of vectors (1-arrays) or as a 1-array of matrices +(2-arrays). In each case, the vectors or matrices are the 1-cells or +2-cells of the array. This terminology originates in the J language. + +@cindex array slice +@cindex prefix slice + +The more vague concept of a `slice' refers to a subset of the array +where some indices are fixed and others are left free. As a Guile data +object, a cell is the same as a `prefix slice' (the first @math{n-k} +indices into the original array are fixed), except that a 0-cell is not +a shared array of the original array, but a 0-slice (where all the +indices into the original array are fixed) is. + +@cindex enclosed array + +Before @w{version 2.0}, Guile had a feature called `enclosed arrays' to +create special `array of arrays' objects. The functions in this section +do not need special types; instead, the frame rank is stated in each +function call, either implicitly or explicitly. + +@deffn {Scheme Procedure} array-cell-ref array idx @dots{} +@deffnx {C Function} scm_array_cell_ref (array, idxlist) +If the length of @var{idxlist} equals the rank @math{n} of @var{array}, +return the element at @code{(idx @dots{})}, just like @code{(array-ref +array idx @dots{})}. If, however, the length @math{k} of @var{idxlist} +is smaller than @math{n}, then return the @math{(n-k)}-cell of +@var{array} given by @var{idxlist}, as a shared array. + +For example: + +@lisp +(array-cell-ref #2((a b) (c d)) 0) @result{} #(a b) +(array-cell-ref #2((a b) (c d)) 1) @result{} #(c d) +(array-cell-ref #2((a b) (c d)) 1 1) @result{} d +(array-cell-ref #2((a b) (c d))) @result{} #2((a b) (c d)) +@end lisp + +@code{(apply array-cell-ref array indices)} is equivalent to + +@lisp +(let ((len (length indices))) + (if (= (array-rank a) len) + (apply array-ref a indices) + (apply make-shared-array a + (lambda t (append indices t)) + (drop (array-dimensions a) len)))) +@end lisp + +@end deffn + +@deffn {Scheme Procedure} array-slice array idx @dots{} +@deffnx {C Function} scm_array_slice (array, idxlist) +Like @code{(array-cell-ref array idx @dots{})}, but return a 0-rank +shared array into @var{ARRAY} if the length of @var{idxlist} matches the +rank of @var{array}. This can be useful when using @var{ARRAY} as a +place to write to. + +Compare: + +@lisp +(array-cell-ref #2((a b) (c d)) 1 1) @result{} d +(array-slice #2((a b) (c d)) 1 1) @result{} #0(d) +(define a (make-array 'a 2 2)) +(array-fill! (array-slice a 1 1) 'b) +a @result{} #2((a a) (a b)). +(array-fill! (array-cell-ref a 1 1) 'b) @result{} error: not an array +@end lisp + +@code{(apply array-slice array indices)} is equivalent to + +@lisp +(apply make-shared-array a + (lambda t (append indices t)) + (drop (array-dimensions a) (length indices))) +@end lisp +@end deffn + + +@deffn {Scheme Procedure} array-cell-set! array x idx @dots{} +@deffnx {C Function} scm_array_cell_set_x (array, x, idxlist) +If the length of @var{idxlist} equals the rank @math{n} of +@var{array}, set the element at @code{(idx @dots{})} of @var{array} to +@var{x}, just like @code{(array-set! array x idx @dots{})}. If, +however, the length @math{k} of @var{idxlist} is smaller than +@math{n}, then copy the @math{(n-k)}-rank array @var{x} +into the @math{(n-k)}-cell of @var{array} given by +@var{idxlist}. In this case, the last @math{(n-k)} dimensions of +@var{array} and the dimensions of @var{x} must match exactly. + +This function returns the modified @var{array}. + +For example: + +@lisp +(array-cell-set! (make-array 'a 2 2) b 1 1) + @result{} #2((a a) (a b)) +(array-cell-set! (make-array 'a 2 2) #(x y) 1) + @result{} #2((a a) (x y)) +@end lisp + +Note that @code{array-cell-set!} will expect elements, not arrays, when +the destination has rank 0. Use @code{array-slice} for the opposite +behavior. + +@lisp +(array-cell-set! (make-array 'a 2 2) #0(b) 1 1) + @result{} #2((a a) (a #0(b))) +(let ((a (make-array 'a 2 2))) + (array-copy! #0(b) (array-slice a 1 1)) a) + @result{} #2((a a) (a b)) +@end lisp + +@code{(apply array-cell-set! array x indices)} is equivalent to + +@lisp +(let ((len (length indices))) + (if (= (array-rank array) len) + (apply array-set! array x indices) + (array-copy! x (apply array-cell-ref array indices))) + array) +@end lisp + +@end deffn + + +@deffn {Scheme Procedure} array-slice-for-each frame-rank op x @dots{} +@deffnx {C Function} scm_array_slice_for_each (array, frame_rank, op, xlist) +Each @var{x} must be an array of rank ≥ @var{frame-rank}, and +the first @var{frame-rank} dimensions of each @var{x} must all be the +same. @var{array-slice-for-each} calls @var{op} with each set of +(rank(@var{x}) - @var{frame-rank})-cells from @var{x}, in unspecified order. + +@var{array-slice-for-each} allows you to loop over cells of any rank +without having to carry an index list or construct shared arrays +manually. The slices passed to @var{op} are always shared arrays of +@var{X}, even if they are of rank 0, so it is possible to write to them. + +This function returns an unspecified value. + +For example, to sort the rows of rank-2 array @code{a}: + +@lisp +(array-slice-for-each 1 (lambda (x) (sort! x <)) a) +@end lisp + +As another example, let @code{a} be a rank-2 array where each row is a +2-element vector @math{(x,y)}. Let's compute the arguments of these +vectors and store them in rank-1 array @code{b}. +@lisp +(array-slice-for-each 1 + (lambda (a b) + (array-set! b (atan (array-ref a 1) (array-ref a 0)))) + a b) +@end lisp + +@code{(apply array-slice-for-each frame-rank op x)} is equivalent to + +@lisp +(let ((frame (take (array-dimensions (car x)) frank))) + (unless (every (lambda (x) + (equal? frame (take (array-dimensions x) frank))) + (cdr x)) + (error)) + (array-index-map! + (apply make-shared-array (make-array #t) (const '()) frame) + (lambda i (apply op (map (lambda (x) (apply array-slice x i)) x))))) +@end lisp + +@end deffn + +@deffn {Scheme Procedure} array-slice-for-each-in-order frame-rank op x @dots{} +@deffnx {C Function} scm_array_slice_for_each_in_order (array, frame_rank, op, xlist) +Same as @code{array-slice-for-each}, but the arguments are traversed +sequentially and in row-major order. +@end deffn + +@node Accessing Arrays from C +@subsubsection Accessing Arrays from C + +For interworking with external C code, Guile provides an API to allow C +code to access the elements of a Scheme array. In particular, for +uniform numeric arrays, the API exposes the underlying uniform data as a +C array of numbers of the relevant type. + +While pointers to the elements of an array are in use, the array itself +must be protected so that the pointer remains valid. Such a protected +array is said to be @dfn{reserved}. A reserved array can be read but +modifications to it that would cause the pointer to its elements to +become invalid are prevented. When you attempt such a modification, an +error is signalled. + +(This is similar to locking the array while it is in use, but without +the danger of a deadlock. In a multi-threaded program, you will need +additional synchronization to avoid modifying reserved arrays.) + +You must take care to always unreserve an array after reserving it, +even in the presence of non-local exits. If a non-local exit can +happen between these two calls, you should install a dynwind context +that releases the array when it is left (@pxref{Dynamic Wind}). + +In addition, array reserving and unreserving must be properly +paired. For instance, when reserving two or more arrays in a certain +order, you need to unreserve them in the opposite order. + +Once you have reserved an array and have retrieved the pointer to its +elements, you must figure out the layout of the elements in memory. +Guile allows slices to be taken out of arrays without actually making a +copy, such as making an alias for the diagonal of a matrix that can be +treated as a vector. Arrays that result from such an operation are not +stored contiguously in memory and when working with their elements +directly, you need to take this into account. + +The layout of array elements in memory can be defined via a +@emph{mapping function} that computes a scalar position from a vector of +indices. The scalar position then is the offset of the element with the +given indices from the start of the storage block of the array. + +In Guile, this mapping function is restricted to be @dfn{affine}: all +mapping functions of Guile arrays can be written as @code{p = b + +c[0]*i[0] + c[1]*i[1] + ... + c[n-1]*i[n-1]} where @code{i[k]} is the +@nicode{k}th index and @code{n} is the rank of the array. For +example, a matrix of size 3x3 would have @code{b == 0}, @code{c[0] == +3} and @code{c[1] == 1}. When you transpose this matrix (with +@code{transpose-array}, say), you will get an array whose mapping +function has @code{b == 0}, @code{c[0] == 1} and @code{c[1] == 3}. + +The function @code{scm_array_handle_dims} gives you (indirect) access to +the coefficients @code{c[k]}. + +@c XXX +Note that there are no functions for accessing the elements of a +character array yet. Once the string implementation of Guile has been +changed to use Unicode, we will provide them. + +@deftp {C Type} scm_t_array_handle +This is a structure type that holds all information necessary to manage +the reservation of arrays as explained above. Structures of this type +must be allocated on the stack and must only be accessed by the +functions listed below. +@end deftp + +@deftypefn {C Function} void scm_array_get_handle (SCM array, scm_t_array_handle *handle) +Reserve @var{array}, which must be an array, and prepare @var{handle} to +be used with the functions below. You must eventually call +@code{scm_array_handle_release} on @var{handle}, and do this in a +properly nested fashion, as explained above. The structure pointed to +by @var{handle} does not need to be initialized before calling this +function. +@end deftypefn + +@deftypefn {C Function} void scm_array_handle_release (scm_t_array_handle *handle) +End the array reservation represented by @var{handle}. After a call to +this function, @var{handle} might be used for another reservation. +@end deftypefn + +@deftypefn {C Function} size_t scm_array_handle_rank (scm_t_array_handle *handle) +Return the rank of the array represented by @var{handle}. +@end deftypefn + +@deftp {C Type} scm_t_array_dim +This structure type holds information about the layout of one dimension +of an array. It includes the following fields: + +@table @code +@item ssize_t lbnd +@itemx ssize_t ubnd +The lower and upper bounds (both inclusive) of the permissible index +range for the given dimension. Both values can be negative, but +@var{lbnd} is always less than or equal to @var{ubnd}. + +@item ssize_t inc +The distance from one element of this dimension to the next. Note, too, +that this can be negative. +@end table +@end deftp + +@deftypefn {C Function} {const scm_t_array_dim *} scm_array_handle_dims (scm_t_array_handle *handle) +Return a pointer to a C vector of information about the dimensions of +the array represented by @var{handle}. This pointer is valid as long as +the array remains reserved. As explained above, the +@code{scm_t_array_dim} structures returned by this function can be used +calculate the position of an element in the storage block of the array +from its indices. + +This position can then be used as an index into the C array pointer +returned by the various @code{scm_array_handle_<foo>_elements} +functions, or with @code{scm_array_handle_ref} and +@code{scm_array_handle_set}. + +Here is how one can compute the position @var{pos} of an element given +its indices in the vector @var{indices}: + +@example +ssize_t indices[RANK]; +scm_t_array_dim *dims; +ssize_t pos; +size_t i; + +pos = 0; +for (i = 0; i < RANK; i++) + @{ + if (indices[i] < dims[i].lbnd || indices[i] > dims[i].ubnd) + out_of_range (); + pos += (indices[i] - dims[i].lbnd) * dims[i].inc; + @} +@end example +@end deftypefn + +@deftypefn {C Function} ssize_t scm_array_handle_pos (scm_t_array_handle *handle, SCM indices) +Compute the position corresponding to @var{indices}, a list of +indices. The position is computed as described above for +@code{scm_array_handle_dims}. The number of the indices and their +range is checked and an appropriate error is signalled for invalid +indices. +@end deftypefn + +@deftypefn {C Function} SCM scm_array_handle_ref (scm_t_array_handle *handle, ssize_t pos) +Return the element at position @var{pos} in the storage block of the +array represented by @var{handle}. Any kind of array is acceptable. No +range checking is done on @var{pos}. +@end deftypefn + +@deftypefn {C Function} void scm_array_handle_set (scm_t_array_handle *handle, ssize_t pos, SCM val) +Set the element at position @var{pos} in the storage block of the array +represented by @var{handle} to @var{val}. Any kind of array is +acceptable. No range checking is done on @var{pos}. An error is +signalled when the array can not store @var{val}. +@end deftypefn + +@deftypefn {C Function} {const SCM *} scm_array_handle_elements (scm_t_array_handle *handle) +Return a pointer to the elements of a ordinary array of general Scheme +values (i.e., a non-uniform array) for reading. This pointer is valid +as long as the array remains reserved. +@end deftypefn + +@deftypefn {C Function} {SCM *} scm_array_handle_writable_elements (scm_t_array_handle *handle) +Like @code{scm_array_handle_elements}, but the pointer is good for +reading and writing. +@end deftypefn + +@deftypefn {C Function} {const void *} scm_array_handle_uniform_elements (scm_t_array_handle *handle) +Return a pointer to the elements of a uniform numeric array for reading. +This pointer is valid as long as the array remains reserved. The size +of each element is given by @code{scm_array_handle_uniform_element_size}. +@end deftypefn + +@deftypefn {C Function} {void *} scm_array_handle_uniform_writable_elements (scm_t_array_handle *handle) +Like @code{scm_array_handle_uniform_elements}, but the pointer is good +reading and writing. +@end deftypefn + +@deftypefn {C Function} size_t scm_array_handle_uniform_element_size (scm_t_array_handle *handle) +Return the size of one element of the uniform numeric array represented +by @var{handle}. +@end deftypefn + +@deftypefn {C Function} {const scm_t_uint8 *} scm_array_handle_u8_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_int8 *} scm_array_handle_s8_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_uint16 *} scm_array_handle_u16_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_int16 *} scm_array_handle_s16_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_uint32 *} scm_array_handle_u32_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_int32 *} scm_array_handle_s32_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_uint64 *} scm_array_handle_u64_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const scm_t_int64 *} scm_array_handle_s64_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const float *} scm_array_handle_f32_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const double *} scm_array_handle_f64_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const float *} scm_array_handle_c32_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {const double *} scm_array_handle_c64_elements (scm_t_array_handle *handle) +Return a pointer to the elements of a uniform numeric array of the +indicated kind for reading. This pointer is valid as long as the array +remains reserved. + +The pointers for @code{c32} and @code{c64} uniform numeric arrays point +to pairs of floating point numbers. The even index holds the real part, +the odd index the imaginary part of the complex number. +@end deftypefn + +@deftypefn {C Function} {scm_t_uint8 *} scm_array_handle_u8_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_int8 *} scm_array_handle_s8_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_uint16 *} scm_array_handle_u16_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_int16 *} scm_array_handle_s16_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_uint32 *} scm_array_handle_u32_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_int32 *} scm_array_handle_s32_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_uint64 *} scm_array_handle_u64_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {scm_t_int64 *} scm_array_handle_s64_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {float *} scm_array_handle_f32_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {double *} scm_array_handle_f64_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {float *} scm_array_handle_c32_writable_elements (scm_t_array_handle *handle) +@deftypefnx {C Function} {double *} scm_array_handle_c64_writable_elements (scm_t_array_handle *handle) +Like @code{scm_array_handle_<kind>_elements}, but the pointer is good +for reading and writing. +@end deftypefn + +@deftypefn {C Function} {const scm_t_uint32 *} scm_array_handle_bit_elements (scm_t_array_handle *handle) +Return a pointer to the words that store the bits of the represented +array, which must be a bit array. + +Unlike other arrays, bit arrays have an additional offset that must be +figured into index calculations. That offset is returned by +@code{scm_array_handle_bit_elements_offset}. + +To find a certain bit you first need to calculate its position as +explained above for @code{scm_array_handle_dims} and then add the +offset. This gives the absolute position of the bit, which is always a +non-negative integer. + +Each word of the bit array storage block contains exactly 32 bits, with +the least significant bit in that word having the lowest absolute +position number. The next word contains the next 32 bits. + +Thus, the following code can be used to access a bit whose position +according to @code{scm_array_handle_dims} is given in @var{pos}: + +@example +SCM bit_array; +scm_t_array_handle handle; +scm_t_uint32 *bits; +ssize_t pos; +size_t abs_pos; +size_t word_pos, mask; + +scm_array_get_handle (&bit_array, &handle); +bits = scm_array_handle_bit_elements (&handle); + +pos = ... +abs_pos = pos + scm_array_handle_bit_elements_offset (&handle); +word_pos = abs_pos / 32; +mask = 1L << (abs_pos % 32); + +if (bits[word_pos] & mask) + /* bit is set. */ + +scm_array_handle_release (&handle); +@end example + +@end deftypefn + +@deftypefn {C Function} {scm_t_uint32 *} scm_array_handle_bit_writable_elements (scm_t_array_handle *handle) +Like @code{scm_array_handle_bit_elements} but the pointer is good for +reading and writing. You must take care not to modify bits outside of +the allowed index range of the array, even for contiguous arrays. +@end deftypefn + +@node VLists +@subsection VLists + +@cindex vlist + +The @code{(ice-9 vlist)} module provides an implementation of the @dfn{VList} +data structure designed by Phil Bagwell in 2002. VLists are immutable lists, +which can contain any Scheme object. They improve on standard Scheme linked +lists in several areas: + +@itemize +@item +Random access has typically constant-time complexity. + +@item +Computing the length of a VList has time complexity logarithmic in the number of +elements. + +@item +VLists use less storage space than standard lists. + +@item +VList elements are stored in contiguous regions, which improves memory locality +and leads to more efficient use of hardware caches. +@end itemize + +The idea behind VLists is to store vlist elements in increasingly large +contiguous blocks (implemented as vectors here). These blocks are linked to one +another using a pointer to the next block and an offset within that block. The +size of these blocks form a geometric series with ratio +@code{block-growth-factor} (2 by default). + +The VList structure also serves as the basis for the @dfn{VList-based hash +lists} or ``vhashes'', an immutable dictionary type (@pxref{VHashes}). + +However, the current implementation in @code{(ice-9 vlist)} has several +noteworthy shortcomings: + +@itemize + +@item +It is @emph{not} thread-safe. Although operations on vlists are all +@dfn{referentially transparent} (i.e., purely functional), adding elements to a +vlist with @code{vlist-cons} mutates part of its internal structure, which makes +it non-thread-safe. This could be fixed, but it would slow down +@code{vlist-cons}. + +@item +@code{vlist-cons} always allocates at least as much memory as @code{cons}. +Again, Phil Bagwell describes how to fix it, but that would require tuning the +garbage collector in a way that may not be generally beneficial. + +@item +@code{vlist-cons} is a Scheme procedure compiled to bytecode, and it does not +compete with the straightforward C implementation of @code{cons}, and with the +fact that the VM has a special @code{cons} instruction. + +@end itemize + +We hope to address these in the future. + +The programming interface exported by @code{(ice-9 vlist)} is defined below. +Most of it is the same as SRFI-1 with an added @code{vlist-} prefix to function +names. + +@deffn {Scheme Procedure} vlist? obj +Return true if @var{obj} is a VList. +@end deffn + +@defvr {Scheme Variable} vlist-null +The empty VList. Note that it's possible to create an empty VList not +@code{eq?} to @code{vlist-null}; thus, callers should always use +@code{vlist-null?} when testing whether a VList is empty. +@end defvr + +@deffn {Scheme Procedure} vlist-null? vlist +Return true if @var{vlist} is empty. +@end deffn + +@deffn {Scheme Procedure} vlist-cons item vlist +Return a new vlist with @var{item} as its head and @var{vlist} as its tail. +@end deffn + +@deffn {Scheme Procedure} vlist-head vlist +Return the head of @var{vlist}. +@end deffn + +@deffn {Scheme Procedure} vlist-tail vlist +Return the tail of @var{vlist}. +@end deffn + +@defvr {Scheme Variable} block-growth-factor +A fluid that defines the growth factor of VList blocks, 2 by default. +@end defvr + +The functions below provide the usual set of higher-level list operations. + +@deffn {Scheme Procedure} vlist-fold proc init vlist +@deffnx {Scheme Procedure} vlist-fold-right proc init vlist +Fold over @var{vlist}, calling @var{proc} for each element, as for SRFI-1 +@code{fold} and @code{fold-right} (@pxref{SRFI-1, @code{fold}}). +@end deffn + +@deffn {Scheme Procedure} vlist-ref vlist index +Return the element at index @var{index} in @var{vlist}. This is typically a +constant-time operation. +@end deffn + +@deffn {Scheme Procedure} vlist-length vlist +Return the length of @var{vlist}. This is typically logarithmic in the number +of elements in @var{vlist}. +@end deffn + +@deffn {Scheme Procedure} vlist-reverse vlist +Return a new @var{vlist} whose content are those of @var{vlist} in reverse +order. +@end deffn + +@deffn {Scheme Procedure} vlist-map proc vlist +Map @var{proc} over the elements of @var{vlist} and return a new vlist. +@end deffn + +@deffn {Scheme Procedure} vlist-for-each proc vlist +Call @var{proc} on each element of @var{vlist}. The result is unspecified. +@end deffn + +@deffn {Scheme Procedure} vlist-drop vlist count +Return a new vlist that does not contain the @var{count} first elements of +@var{vlist}. This is typically a constant-time operation. +@end deffn + +@deffn {Scheme Procedure} vlist-take vlist count +Return a new vlist that contains only the @var{count} first elements of +@var{vlist}. +@end deffn + +@deffn {Scheme Procedure} vlist-filter pred vlist +Return a new vlist containing all the elements from @var{vlist} that satisfy +@var{pred}. +@end deffn + +@deffn {Scheme Procedure} vlist-delete x vlist [equal?] +Return a new vlist corresponding to @var{vlist} without the elements +@var{equal?} to @var{x}. +@end deffn + +@deffn {Scheme Procedure} vlist-unfold p f g seed [tail-gen] +@deffnx {Scheme Procedure} vlist-unfold-right p f g seed [tail] +Return a new vlist, as for SRFI-1 @code{unfold} and @code{unfold-right} +(@pxref{SRFI-1, @code{unfold}}). +@end deffn + +@deffn {Scheme Procedure} vlist-append vlist @dots{} +Append the given vlists and return the resulting vlist. +@end deffn + +@deffn {Scheme Procedure} list->vlist lst +Return a new vlist whose contents correspond to @var{lst}. +@end deffn + +@deffn {Scheme Procedure} vlist->list vlist +Return a new list whose contents match those of @var{vlist}. +@end deffn + +@node Record Overview +@subsection Record Overview + +@cindex record +@cindex structure + +@dfn{Records}, also called @dfn{structures}, are Scheme's primary +mechanism to define new disjoint types. A @dfn{record type} defines a +list of @dfn{fields} that instances of the type consist of. This is like +C's @code{struct}. + +Historically, Guile has offered several different ways to define record +types and to create records, offering different features, and making +different trade-offs. Over the years, each ``standard'' has also come +with its own new record interface, leading to a maze of record APIs. + +At the highest level is SRFI-9, a high-level record interface +implemented by most Scheme implementations (@pxref{SRFI-9 Records}). It +defines a simple and efficient syntactic abstraction of record types and +their associated type predicate, fields, and field accessors. SRFI-9 is +suitable for most uses, and this is the recommended way to create record +types in Guile. Similar high-level record APIs include SRFI-35 +(@pxref{SRFI-35}) and R6RS records (@pxref{rnrs records syntactic}). + +Then comes Guile's historical ``records'' API (@pxref{Records}). Record +types defined this way are first-class objects. Introspection +facilities are available, allowing users to query the list of fields or +the value of a specific field at run-time, without prior knowledge of +the type. + +Finally, the common denominator of these interfaces is Guile's +@dfn{structure} API (@pxref{Structures}). Guile's structures are the +low-level building block for all other record APIs. Application writers +will normally not need to use it. + +Records created with these APIs may all be pattern-matched using Guile's +standard pattern matcher (@pxref{Pattern Matching}). + + +@node SRFI-9 Records +@subsection SRFI-9 Records + +@cindex SRFI-9 +@cindex record + +SRFI-9 standardizes a syntax for defining new record types and creating +predicate, constructor, and field getter and setter functions. In Guile +this is the recommended option to create new record types (@pxref{Record +Overview}). It can be used with: + +@example +(use-modules (srfi srfi-9)) +@end example + +@deffn {Scheme Syntax} define-record-type type @* (constructor fieldname @dots{}) @* predicate @* (fieldname accessor [modifier]) @dots{} +@sp 1 +Create a new record type, and make various @code{define}s for using +it. This syntax can only occur at the top-level, not nested within +some other form. + +@var{type} is bound to the record type, which is as per the return +from the core @code{make-record-type}. @var{type} also provides the +name for the record, as per @code{record-type-name}. + +@var{constructor} is bound to a function to be called as +@code{(@var{constructor} fieldval @dots{})} to create a new record of +this type. The arguments are initial values for the fields, one +argument for each field, in the order they appear in the +@code{define-record-type} form. + +The @var{fieldname}s provide the names for the record fields, as per +the core @code{record-type-fields} etc, and are referred to in the +subsequent accessor/modifier forms. + +@var{predicate} is bound to a function to be called as +@code{(@var{predicate} obj)}. It returns @code{#t} or @code{#f} +according to whether @var{obj} is a record of this type. + +Each @var{accessor} is bound to a function to be called +@code{(@var{accessor} record)} to retrieve the respective field from a +@var{record}. Similarly each @var{modifier} is bound to a function to +be called @code{(@var{modifier} record val)} to set the respective +field in a @var{record}. +@end deffn + +@noindent +An example will illustrate typical usage, + +@example +(define-record-type <employee> + (make-employee name age salary) + employee? + (name employee-name) + (age employee-age set-employee-age!) + (salary employee-salary set-employee-salary!)) +@end example + +This creates a new employee data type, with name, age and salary +fields. Accessor functions are created for each field, but no +modifier function for the name (the intention in this example being +that it's established only when an employee object is created). These +can all then be used as for example, + +@example +<employee> @result{} #<record-type <employee>> + +(define fred (make-employee "Fred" 45 20000.00)) + +(employee? fred) @result{} #t +(employee-age fred) @result{} 45 +(set-employee-salary! fred 25000.00) ;; pay rise +@end example + +The functions created by @code{define-record-type} are ordinary +top-level @code{define}s. They can be redefined or @code{set!} as +desired, exported from a module, etc. + +@unnumberedsubsubsec Non-toplevel Record Definitions + +The SRFI-9 specification explicitly disallows record definitions in a +non-toplevel context, such as inside @code{lambda} body or inside a +@var{let} block. However, Guile's implementation does not enforce that +restriction. + +@unnumberedsubsubsec Custom Printers + +You may use @code{set-record-type-printer!} to customize the default printing +behavior of records. This is a Guile extension and is not part of SRFI-9. It +is located in the @nicode{(srfi srfi-9 gnu)} module. + +@deffn {Scheme Syntax} set-record-type-printer! type proc +Where @var{type} corresponds to the first argument of @code{define-record-type}, +and @var{proc} is a procedure accepting two arguments, the record to print, and +an output port. +@end deffn + +@noindent +This example prints the employee's name in brackets, for instance @code{[Fred]}. + +@example +(set-record-type-printer! <employee> + (lambda (record port) + (write-char #\[ port) + (display (employee-name record) port) + (write-char #\] port))) +@end example + +@unnumberedsubsubsec Functional ``Setters'' + +@cindex functional setters + +When writing code in a functional style, it is desirable to never alter +the contents of records. For such code, a simple way to return new +record instances based on existing ones is highly desirable. + +The @code{(srfi srfi-9 gnu)} module extends SRFI-9 with facilities to +return new record instances based on existing ones, only with one or +more field values changed---@dfn{functional setters}. First, the +@code{define-immutable-record-type} works like +@code{define-record-type}, except that fields are immutable and setters +are defined as functional setters. + +@deffn {Scheme Syntax} define-immutable-record-type type @* (constructor fieldname @dots{}) @* predicate @* (fieldname accessor [modifier]) @dots{} +Define @var{type} as a new record type, like @code{define-record-type}. +However, the record type is made @emph{immutable} (records may not be +mutated, even with @code{struct-set!}), and any @var{modifier} is +defined to be a functional setter---a procedure that returns a new +record instance with the specified field changed, and leaves the +original unchanged (see example below.) +@end deffn + +@noindent +In addition, the generic @code{set-field} and @code{set-fields} macros +may be applied to any SRFI-9 record. + +@deffn {Scheme Syntax} set-field record (field sub-fields ...) value +Return a new record of @var{record}'s type whose fields are equal to +the corresponding fields of @var{record} except for the one specified by +@var{field}. + +@var{field} must be the name of the getter corresponding to the field of +@var{record} being ``set''. Subsequent @var{sub-fields} must be record +getters designating sub-fields within that field value to be set (see +example below.) +@end deffn + +@deffn {Scheme Syntax} set-fields record ((field sub-fields ...) value) ... +Like @code{set-field}, but can be used to set more than one field at a +time. This expands to code that is more efficient than a series of +single @code{set-field} calls. +@end deffn + +To illustrate the use of functional setters, let's assume these two +record type definitions: + +@example +(define-record-type <address> + (address street city country) + address? + (street address-street) + (city address-city) + (country address-country)) + +(define-immutable-record-type <person> + (person age email address) + person? + (age person-age set-person-age) + (email person-email set-person-email) + (address person-address set-person-address)) +@end example + +@noindent +First, note that the @code{<person>} record type definition introduces +named functional setters. These may be used like this: + +@example +(define fsf-address + (address "Franklin Street" "Boston" "USA")) + +(define rms + (person 30 "rms@@gnu.org" fsf-address)) + +(and (equal? (set-person-age rms 60) + (person 60 "rms@@gnu.org" fsf-address)) + (= (person-age rms) 30)) +@result{} #t +@end example + +@noindent +Here, the original @code{<person>} record, to which @var{rms} is bound, +is left unchanged. + +Now, suppose we want to change both the street and age of @var{rms}. +This can be achieved using @code{set-fields}: + +@example +(set-fields rms + ((person-age) 60) + ((person-address address-street) "Temple Place")) +@result{} #<<person> age: 60 email: "rms@@gnu.org" + address: #<<address> street: "Temple Place" city: "Boston" country: "USA">> +@end example + +@noindent +Notice how the above changed two fields of @var{rms}, including the +@code{street} field of its @code{address} field, in a concise way. Also +note that @code{set-fields} works equally well for types defined with +just @code{define-record-type}. + +@node Records +@subsection Records + +A @dfn{record type} is a first class object representing a user-defined +data type. A @dfn{record} is an instance of a record type. + +Note that in many ways, this interface is too low-level for every-day +use. Most uses of records are better served by SRFI-9 records. +@xref{SRFI-9 Records}. + +@deffn {Scheme Procedure} record? obj +Return @code{#t} if @var{obj} is a record of any type and @code{#f} +otherwise. + +Note that @code{record?} may be true of any Scheme value; there is no +promise that records are disjoint with other Scheme types. +@end deffn + +@deffn {Scheme Procedure} make-record-type type-name field-names [print] +Create and return a new @dfn{record-type descriptor}. + +@var{type-name} is a string naming the type. Currently it's only used +in the printed representation of records, and in diagnostics. +@var{field-names} is a list of symbols naming the fields of a record +of the type. Duplicates are not allowed among these symbols. + +@example +(make-record-type "employee" '(name age salary)) +@end example + +The optional @var{print} argument is a function used by +@code{display}, @code{write}, etc, for printing a record of the new +type. It's called as @code{(@var{print} record port)} and should look +at @var{record} and write to @var{port}. +@end deffn + +@deffn {Scheme Procedure} record-constructor rtd [field-names] +Return a procedure for constructing new members of the type represented +by @var{rtd}. The returned procedure accepts exactly as many arguments +as there are symbols in the given list, @var{field-names}; these are +used, in order, as the initial values of those fields in a new record, +which is returned by the constructor procedure. The values of any +fields not named in that list are unspecified. The @var{field-names} +argument defaults to the list of field names in the call to +@code{make-record-type} that created the type represented by @var{rtd}; +if the @var{field-names} argument is provided, it is an error if it +contains any duplicates or any symbols not in the default list. +@end deffn + +@deffn {Scheme Procedure} record-predicate rtd +Return a procedure for testing membership in the type represented by +@var{rtd}. The returned procedure accepts exactly one argument and +returns a true value if the argument is a member of the indicated record +type; it returns a false value otherwise. +@end deffn + +@deffn {Scheme Procedure} record-accessor rtd field-name +Return a procedure for reading the value of a particular field of a +member of the type represented by @var{rtd}. The returned procedure +accepts exactly one argument which must be a record of the appropriate +type; it returns the current value of the field named by the symbol +@var{field-name} in that record. The symbol @var{field-name} must be a +member of the list of field-names in the call to @code{make-record-type} +that created the type represented by @var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-modifier rtd field-name +Return a procedure for writing the value of a particular field of a +member of the type represented by @var{rtd}. The returned procedure +accepts exactly two arguments: first, a record of the appropriate type, +and second, an arbitrary Scheme value; it modifies the field named by +the symbol @var{field-name} in that record to contain the given value. +The returned value of the modifier procedure is unspecified. The symbol +@var{field-name} must be a member of the list of field-names in the call +to @code{make-record-type} that created the type represented by +@var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-type-descriptor record +Return a record-type descriptor representing the type of the given +record. That is, for example, if the returned descriptor were passed to +@code{record-predicate}, the resulting predicate would return a true +value when passed the given record. Note that it is not necessarily the +case that the returned descriptor is the one that was passed to +@code{record-constructor} in the call that created the constructor +procedure that created the given record. +@end deffn + +@deffn {Scheme Procedure} record-type-name rtd +Return the type-name associated with the type represented by rtd. The +returned value is @code{eqv?} to the @var{type-name} argument given in +the call to @code{make-record-type} that created the type represented by +@var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-type-fields rtd +Return a list of the symbols naming the fields in members of the type +represented by @var{rtd}. The returned value is @code{equal?} to the +field-names argument given in the call to @code{make-record-type} that +created the type represented by @var{rtd}. +@end deffn + + +@node Structures +@subsection Structures +@tpindex Structures + +A @dfn{structure} is a first class data type which holds Scheme values +or C words in fields numbered 0 upwards. A @dfn{vtable} is a structure +that represents a structure type, giving field types and permissions, +and an optional print function for @code{write} etc. + +Structures are lower level than records (@pxref{Records}). Usually, +when you need to represent structured data, you just want to use +records. But sometimes you need to implement new kinds of structured +data abstractions, and for that purpose structures are useful. Indeed, +records in Guile are implemented with structures. + +@menu +* Vtables:: +* Structure Basics:: +* Vtable Contents:: +* Meta-Vtables:: +* Vtable Example:: +@end menu + +@node Vtables +@subsubsection Vtables + +A vtable is a structure type, specifying its layout, and other +information. A vtable is actually itself a structure, but there's no +need to worry about that initially (@pxref{Vtable Contents}.) + +@deffn {Scheme Procedure} make-vtable fields [print] +Create a new vtable. + +@var{fields} is a string describing the fields in the structures to be +created. Each field is represented by two characters, a type letter +and a permissions letter, for example @code{"pw"}. The types are as +follows. + +@itemize @bullet{} +@item +@code{p} -- a Scheme value. ``p'' stands for ``protected'' meaning +it's protected against garbage collection. + +@item +@code{u} -- an arbitrary word of data (an @code{scm_t_bits}). At the +Scheme level it's read and written as an unsigned integer. ``u'' stands +for ``unboxed'', as it's stored as a raw value without additional type +annotations. +@end itemize + +It used to be that the second letter for each field was a permission +code, such as @code{w} for writable or @code{r} for read-only. However +over time structs have become more of a raw low-level facility; access +control is better implemented as a layer on top. After all, +@code{struct-set!} is a cross-cutting operator that can bypass +abstractions made by higher-level record facilities; it's not generally +safe (in the sense of abstraction-preserving) to expose +@code{struct-set!} to ``untrusted'' code, even if the fields happen to +be writable. Additionally, permission checks added overhead to every +structure access in a way that couldn't be optimized out, hampering the +ability of structs to act as a low-level building block. For all of +these reasons, all fields in Guile structs are now writable; attempting +to make a read-only field will now issue a deprecation warning, and the +field will be writable regardless. + +@example +(make-vtable "pw") ;; one scheme field +(make-vtable "pwuwuw") ;; one scheme and two unboxed fields +@end example + +The optional @var{print} argument is a function called by +@code{display} and @code{write} (etc) to give a printed representation +of a structure created from this vtable. It's called +@code{(@var{print} struct port)} and should look at @var{struct} and +write to @var{port}. The default print merely gives a form like +@samp{#<struct ADDR:ADDR>} with a pair of machine addresses. + +The following print function for example shows the two fields of its +structure. + +@example +(make-vtable "pwpw" + (lambda (struct port) + (format port "#<~a and ~a>" + (struct-ref struct 0) + (struct-ref struct 1)))) +@end example +@end deffn + + +@node Structure Basics +@subsubsection Structure Basics + +This section describes the basic procedures for working with structures. +@code{make-struct/no-tail} creates a structure, and @code{struct-ref} +and @code{struct-set!} access its fields. + +@deffn {Scheme Procedure} make-struct/no-tail vtable init @dots{} +Create a new structure, with layout per the given @var{vtable} +(@pxref{Vtables}). + +The optional @var{init}@dots{} arguments are initial values for the +fields of the structure. This is the only way to +put values in read-only fields. If there are fewer @var{init} +arguments than fields then the defaults are @code{#f} for a Scheme +field (type @code{p}) or 0 for an unboxed field (type @code{u}). + +The name is a bit strange, we admit. The reason for it is that Guile +used to have a @code{make-struct} that took an additional argument; +while we deprecate that old interface, @code{make-struct/no-tail} is the +new name for this functionality. + +For example, + +@example +(define v (make-vtable "pwpwpw")) +(define s (make-struct/no-tail v 123 "abc" 456)) +(struct-ref s 0) @result{} 123 +(struct-ref s 1) @result{} "abc" +@end example +@end deffn + +@deftypefn {C Function} SCM scm_make_struct (SCM vtable, SCM tail_size, SCM init_list) +@deftypefnx {C Function} SCM scm_c_make_struct (SCM vtable, SCM tail_size, SCM init, ...) +@deftypefnx {C Function} SCM scm_c_make_structv (SCM vtable, SCM tail_size, size_t n_inits, scm_t_bits init[]) +There are a few ways to make structures from C. @code{scm_make_struct} +takes a list, @code{scm_c_make_struct} takes variable arguments +terminated with SCM_UNDEFINED, and @code{scm_c_make_structv} takes a +packed array. + +For all of these, @var{tail_size} should be zero (as a SCM value). +@end deftypefn + +@deffn {Scheme Procedure} struct? obj +@deffnx {C Function} scm_struct_p (obj) +Return @code{#t} if @var{obj} is a structure, or @code{#f} if not. +@end deffn + +@deffn {Scheme Procedure} struct-ref struct n +@deffnx {C Function} scm_struct_ref (struct, n) +Return the contents of field number @var{n} in @var{struct}. The +first field is number 0. + +An error is thrown if @var{n} is out of range. +@end deffn + +@deffn {Scheme Procedure} struct-set! struct n value +@deffnx {C Function} scm_struct_set_x (struct, n, value) +Set field number @var{n} in @var{struct} to @var{value}. The first +field is number 0. + +An error is thrown if @var{n} is out of range, or if the field cannot +be written because it's @code{r} read-only. +@end deffn + +Unboxed fields (those with type @code{u}) need to be accessed with +special procedures. + +@deffn {Scheme Procedure} struct-ref/unboxed struct n +@deffnx {Scheme Procedure} struct-set!/unboxed struct n value +@deffnx {C Function} scm_struct_ref_unboxed (struct, n) +@deffnx {C Function} scm_struct_set_x_unboxed (struct, n, value) +Like @code{struct-ref} and @code{struct-set!}, except that these may +only be used on unboxed fields. @code{struct-ref/unboxed} will always +return a positive integer. Likewise, @code{struct-set!/unboxed} takes +an unsigned integer as the @var{value} argument, and will signal an +error otherwise. +@end deffn + +@deffn {Scheme Procedure} struct-vtable struct +@deffnx {C Function} scm_struct_vtable (struct) +Return the vtable that describes @var{struct}. + +The vtable is effectively the type of the structure. See @ref{Vtable +Contents}, for more on vtables. +@end deffn + + +@node Vtable Contents +@subsubsection Vtable Contents + +A vtable is itself a structure. It has a specific set of fields +describing various aspects of its @dfn{instances}: the structures +created from a vtable. Some of the fields are internal to Guile, some +of them are part of the public interface, and there may be additional +fields added on by the user. + +Every vtable has a field for the layout of their instances, a field for +the procedure used to print its instances, and a field for the name of +the vtable itself. Access to the layout and printer is exposed directly +via field indexes. Access to the vtable name is exposed via accessor +procedures. + +@defvr {Scheme Variable} vtable-index-layout +@defvrx {C Macro} scm_vtable_index_layout +The field number of the layout specification in a vtable. The layout +specification is a symbol like @code{pwpw} formed from the fields +string passed to @code{make-vtable}, or created by +@code{make-struct-layout} (@pxref{Meta-Vtables}). + +@example +(define v (make-vtable "pwpw" 0)) +(struct-ref v vtable-index-layout) @result{} pwpw +@end example + +This field is read-only, since the layout of structures using a vtable +cannot be changed. +@end defvr + +@defvr {Scheme Variable} vtable-index-printer +@defvrx {C Macro} scm_vtable_index_printer +The field number of the printer function. This field contains @code{#f} +if the default print function should be used. + +@example +(define (my-print-func struct port) + ...) +(define v (make-vtable "pwpw" my-print-func)) +(struct-ref v vtable-index-printer) @result{} my-print-func +@end example + +This field is writable, allowing the print function to be changed +dynamically. +@end defvr + +@deffn {Scheme Procedure} struct-vtable-name vtable +@deffnx {Scheme Procedure} set-struct-vtable-name! vtable name +@deffnx {C Function} scm_struct_vtable_name (vtable) +@deffnx {C Function} scm_set_struct_vtable_name_x (vtable, name) +Get or set the name of @var{vtable}. @var{name} is a symbol and is +used in the default print function when printing structures created +from @var{vtable}. + +@example +(define v (make-vtable "pw")) +(set-struct-vtable-name! v 'my-name) + +(define s (make-struct v 0)) +(display s) @print{} #<my-name b7ab3ae0:b7ab3730> +@end example +@end deffn + + +@node Meta-Vtables +@subsubsection Meta-Vtables + +As a structure, a vtable also has a vtable, which is also a structure. +Structures, their vtables, the vtables of the vtables, and so on form a +tree of structures. Making a new structure adds a leaf to the tree, and +if that structure is a vtable, it may be used to create other leaves. + +If you traverse up the tree of vtables, via calling +@code{struct-vtable}, eventually you reach a root which is the vtable of +itself: + +@example +scheme@@(guile-user)> (current-module) +$1 = #<directory (guile-user) 221b090> +scheme@@(guile-user)> (struct-vtable $1) +$2 = #<record-type module> +scheme@@(guile-user)> (struct-vtable $2) +$3 = #<<standard-vtable> 12c30a0> +scheme@@(guile-user)> (struct-vtable $3) +$4 = #<<standard-vtable> 12c3fa0> +scheme@@(guile-user)> (struct-vtable $4) +$5 = #<<standard-vtable> 12c3fa0> +scheme@@(guile-user)> <standard-vtable> +$6 = #<<standard-vtable> 12c3fa0> +@end example + +In this example, we can say that @code{$1} is an instance of @code{$2}, +@code{$2} is an instance of @code{$3}, @code{$3} is an instance of +@code{$4}, and @code{$4}, strangely enough, is an instance of itself. +The value bound to @code{$4} in this console session also bound to +@code{<standard-vtable>} in the default environment. + +@defvr {Scheme Variable} <standard-vtable> +A meta-vtable, useful for making new vtables. +@end defvr + +All of these values are structures. All but @code{$1} are vtables. As +@code{$2} is an instance of @code{$3}, and @code{$3} is a vtable, we can +say that @code{$3} is a @dfn{meta-vtable}: a vtable that can create +vtables. + +With this definition, we can specify more precisely what a vtable is: a +vtable is a structure made from a meta-vtable. Making a structure from +a meta-vtable runs some special checks to ensure that the first field of +the structure is a valid layout. Additionally, if these checks see that +the layout of the child vtable contains all the required fields of a +vtable, in the correct order, then the child vtable will also be a +meta-table, inheriting a magical bit from the parent. + +@deffn {Scheme Procedure} struct-vtable? obj +@deffnx {C Function} scm_struct_vtable_p (obj) +Return @code{#t} if @var{obj} is a vtable structure: an instance of a +meta-vtable. +@end deffn + +@code{<standard-vtable>} is a root of the vtable tree. (Normally there +is only one root in a given Guile process, but due to some legacy +interfaces there may be more than one.) + +The set of required fields of a vtable is the set of fields in the +@code{<standard-vtable>}, and is bound to @code{standard-vtable-fields} +in the default environment. It is possible to create a meta-vtable that +with additional fields in its layout, which can be used to create +vtables with additional data: + +@example +scheme@@(guile-user)> (struct-ref $3 vtable-index-layout) +$6 = pwuhuhpwphuhuhpwpwpw +scheme@@(guile-user)> (struct-ref $4 vtable-index-layout) +$7 = pwuhuhpwphuhuh +scheme@@(guile-user)> standard-vtable-fields +$8 = "pwuhuhpwphuhuh" +scheme@@(guile-user)> (struct-ref $2 vtable-offset-user) +$9 = module +@end example + +In this continuation of our earlier example, @code{$2} is a vtable that +has extra fields, because its vtable, @code{$3}, was made from a +meta-vtable with an extended layout. @code{vtable-offset-user} is a +convenient definition that indicates the number of fields in +@code{standard-vtable-fields}. + +@defvr {Scheme Variable} standard-vtable-fields +A string containing the ordered set of fields that a vtable must have. +@end defvr + +@defvr {Scheme Variable} vtable-offset-user +The first index in a vtable that is available for a user. +@end defvr + +@deffn {Scheme Procedure} make-struct-layout fields +@deffnx {C Function} scm_make_struct_layout (fields) +Return a structure layout symbol, from a @var{fields} string. +@var{fields} is as described under @code{make-vtable} +(@pxref{Vtables}). An invalid @var{fields} string is an error. +@end deffn + +With these definitions, one can define @code{make-vtable} in this way: + +@example +(define* (make-vtable fields #:optional printer) + (make-struct/no-tail <standard-vtable> + (make-struct-layout fields) + printer)) +@end example + + +@node Vtable Example +@subsubsection Vtable Example + +Let us bring these points together with an example. Consider a simple +object system with single inheritance. Objects will be normal +structures, and classes will be vtables with three extra class fields: +the name of the class, the parent class, and the list of fields. + +So, first we need a meta-vtable that allocates instances with these +extra class fields. + +@example +(define <class> + (make-vtable + (string-append standard-vtable-fields "pwpwpw") + (lambda (x port) + (format port "<<class> ~a>" (class-name x))))) + +(define (class? x) + (and (struct? x) + (eq? (struct-vtable x) <class>))) +@end example + +To make a structure with a specific meta-vtable, we will use +@code{make-struct/no-tail}, passing it the computed instance layout and +printer, as with @code{make-vtable}, and additionally the extra three +class fields. + +@example +(define (make-class name parent fields) + (let* ((fields (compute-fields parent fields)) + (layout (compute-layout fields))) + (make-struct/no-tail <class> + layout + (lambda (x port) + (print-instance x port)) + name + parent + fields))) +@end example + +Instances will store their associated data in slots in the structure: as +many slots as there are fields. The @code{compute-layout} procedure +below can compute a layout, and @code{field-index} returns the slot +corresponding to a field. + +@example +(define-syntax-rule (define-accessor name n) + (define (name obj) + (struct-ref obj n))) + +;; Accessors for classes +(define-accessor class-name (+ vtable-offset-user 0)) +(define-accessor class-parent (+ vtable-offset-user 1)) +(define-accessor class-fields (+ vtable-offset-user 2)) + +(define (compute-fields parent fields) + (if parent + (append (class-fields parent) fields) + fields)) + +(define (compute-layout fields) + (make-struct-layout + (string-concatenate (make-list (length fields) "pw")))) + +(define (field-index class field) + (list-index (class-fields class) field)) + +(define (print-instance x port) + (format port "<~a" (class-name (struct-vtable x))) + (for-each (lambda (field idx) + (format port " ~a: ~a" field (struct-ref x idx))) + (class-fields (struct-vtable x)) + (iota (length (class-fields (struct-vtable x))))) + (format port ">")) +@end example + +So, at this point we can actually make a few classes: + +@example +(define-syntax-rule (define-class name parent field ...) + (define name (make-class 'name parent '(field ...)))) + +(define-class <surface> #f + width height) + +(define-class <window> <surface> + x y) +@end example + +And finally, make an instance: + +@example +(make-struct/no-tail <window> 400 300 10 20) +@result{} <<window> width: 400 height: 300 x: 10 y: 20> +@end example + +And that's that. Note that there are many possible optimizations and +feature enhancements that can be made to this object system, and the +included GOOPS system does make most of them. For more simple use +cases, the records facility is usually sufficient. But sometimes you +need to make new kinds of data abstractions, and for that purpose, +structs are here. + + +@node Dictionary Types +@subsection Dictionary Types + +A @dfn{dictionary} object is a data structure used to index +information in a user-defined way. In standard Scheme, the main +aggregate data types are lists and vectors. Lists are not really +indexed at all, and vectors are indexed only by number +(e.g.@: @code{(vector-ref foo 5)}). Often you will find it useful +to index your data on some other type; for example, in a library +catalog you might want to look up a book by the name of its +author. Dictionaries are used to help you organize information in +such a way. + +An @dfn{association list} (or @dfn{alist} for short) is a list of +key-value pairs. Each pair represents a single quantity or +object; the @code{car} of the pair is a key which is used to +identify the object, and the @code{cdr} is the object's value. + +A @dfn{hash table} also permits you to index objects with +arbitrary keys, but in a way that makes looking up any one object +extremely fast. A well-designed hash system makes hash table +lookups almost as fast as conventional array or vector references. + +Alists are popular among Lisp programmers because they use only +the language's primitive operations (lists, @dfn{car}, @dfn{cdr} +and the equality primitives). No changes to the language core are +necessary. Therefore, with Scheme's built-in list manipulation +facilities, it is very convenient to handle data stored in an +association list. Also, alists are highly portable and can be +easily implemented on even the most minimal Lisp systems. + +However, alists are inefficient, especially for storing large +quantities of data. Because we want Guile to be useful for large +software systems as well as small ones, Guile provides a rich set +of tools for using either association lists or hash tables. + +@node Association Lists +@subsection Association Lists +@tpindex Association Lists +@tpindex Alist +@cindex association List +@cindex alist +@cindex database + +An association list is a conventional data structure that is often used +to implement simple key-value databases. It consists of a list of +entries in which each entry is a pair. The @dfn{key} of each entry is +the @code{car} of the pair and the @dfn{value} of each entry is the +@code{cdr}. + +@example +ASSOCIATION LIST ::= '( (KEY1 . VALUE1) + (KEY2 . VALUE2) + (KEY3 . VALUE3) + @dots{} + ) +@end example + +@noindent +Association lists are also known, for short, as @dfn{alists}. + +The structure of an association list is just one example of the infinite +number of possible structures that can be built using pairs and lists. +As such, the keys and values in an association list can be manipulated +using the general list structure procedures @code{cons}, @code{car}, +@code{cdr}, @code{set-car!}, @code{set-cdr!} and so on. However, +because association lists are so useful, Guile also provides specific +procedures for manipulating them. + +@menu +* Alist Key Equality:: +* Adding or Setting Alist Entries:: +* Retrieving Alist Entries:: +* Removing Alist Entries:: +* Sloppy Alist Functions:: +* Alist Example:: +@end menu + +@node Alist Key Equality +@subsubsection Alist Key Equality + +All of Guile's dedicated association list procedures, apart from +@code{acons}, come in three flavours, depending on the level of equality +that is required to decide whether an existing key in the association +list is the same as the key that the procedure call uses to identify the +required entry. + +@itemize @bullet +@item +Procedures with @dfn{assq} in their name use @code{eq?} to determine key +equality. + +@item +Procedures with @dfn{assv} in their name use @code{eqv?} to determine +key equality. + +@item +Procedures with @dfn{assoc} in their name use @code{equal?} to +determine key equality. +@end itemize + +@code{acons} is an exception because it is used to build association +lists which do not require their entries' keys to be unique. + +@node Adding or Setting Alist Entries +@subsubsection Adding or Setting Alist Entries + +@code{acons} adds a new entry to an association list and returns the +combined association list. The combined alist is formed by consing the +new entry onto the head of the alist specified in the @code{acons} +procedure call. So the specified alist is not modified, but its +contents become shared with the tail of the combined alist that +@code{acons} returns. + +In the most common usage of @code{acons}, a variable holding the +original association list is updated with the combined alist: + +@example +(set! address-list (acons name address address-list)) +@end example + +In such cases, it doesn't matter that the old and new values of +@code{address-list} share some of their contents, since the old value is +usually no longer independently accessible. + +Note that @code{acons} adds the specified new entry regardless of +whether the alist may already contain entries with keys that are, in +some sense, the same as that of the new entry. Thus @code{acons} is +ideal for building alists where there is no concept of key uniqueness. + +@example +(set! task-list (acons 3 "pay gas bill" '())) +task-list +@result{} +((3 . "pay gas bill")) + +(set! task-list (acons 3 "tidy bedroom" task-list)) +task-list +@result{} +((3 . "tidy bedroom") (3 . "pay gas bill")) +@end example + +@code{assq-set!}, @code{assv-set!} and @code{assoc-set!} are used to add +or replace an entry in an association list where there @emph{is} a +concept of key uniqueness. If the specified association list already +contains an entry whose key is the same as that specified in the +procedure call, the existing entry is replaced by the new one. +Otherwise, the new entry is consed onto the head of the old association +list to create the combined alist. In all cases, these procedures +return the combined alist. + +@code{assq-set!} and friends @emph{may} destructively modify the +structure of the old association list in such a way that an existing +variable is correctly updated without having to @code{set!} it to the +value returned: + +@example +address-list +@result{} +(("mary" . "34 Elm Road") ("james" . "16 Bow Street")) + +(assoc-set! address-list "james" "1a London Road") +@result{} +(("mary" . "34 Elm Road") ("james" . "1a London Road")) + +address-list +@result{} +(("mary" . "34 Elm Road") ("james" . "1a London Road")) +@end example + +Or they may not: + +@example +(assoc-set! address-list "bob" "11 Newington Avenue") +@result{} +(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road") + ("james" . "1a London Road")) + +address-list +@result{} +(("mary" . "34 Elm Road") ("james" . "1a London Road")) +@end example + +The only safe way to update an association list variable when adding or +replacing an entry like this is to @code{set!} the variable to the +returned value: + +@example +(set! address-list + (assoc-set! address-list "bob" "11 Newington Avenue")) +address-list +@result{} +(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road") + ("james" . "1a London Road")) +@end example + +Because of this slight inconvenience, you may find it more convenient to +use hash tables to store dictionary data. If your application will not +be modifying the contents of an alist very often, this may not make much +difference to you. + +If you need to keep the old value of an association list in a form +independent from the list that results from modification by +@code{acons}, @code{assq-set!}, @code{assv-set!} or @code{assoc-set!}, +use @code{list-copy} to copy the old association list before modifying +it. + +@deffn {Scheme Procedure} acons key value alist +@deffnx {C Function} scm_acons (key, value, alist) +Add a new key-value pair to @var{alist}. A new pair is +created whose car is @var{key} and whose cdr is @var{value}, and the +pair is consed onto @var{alist}, and the new list is returned. This +function is @emph{not} destructive; @var{alist} is not modified. +@end deffn + +@deffn {Scheme Procedure} assq-set! alist key val +@deffnx {Scheme Procedure} assv-set! alist key value +@deffnx {Scheme Procedure} assoc-set! alist key value +@deffnx {C Function} scm_assq_set_x (alist, key, val) +@deffnx {C Function} scm_assv_set_x (alist, key, val) +@deffnx {C Function} scm_assoc_set_x (alist, key, val) +Reassociate @var{key} in @var{alist} with @var{value}: find any existing +@var{alist} entry for @var{key} and associate it with the new +@var{value}. If @var{alist} does not contain an entry for @var{key}, +add a new one. Return the (possibly new) alist. + +These functions do not attempt to verify the structure of @var{alist}, +and so may cause unusual results if passed an object that is not an +association list. +@end deffn + +@node Retrieving Alist Entries +@subsubsection Retrieving Alist Entries +@rnindex assq +@rnindex assv +@rnindex assoc + +@code{assq}, @code{assv} and @code{assoc} find the entry in an alist +for a given key, and return the @code{(@var{key} . @var{value})} pair. +@code{assq-ref}, @code{assv-ref} and @code{assoc-ref} do a similar +lookup, but return just the @var{value}. + +@deffn {Scheme Procedure} assq key alist +@deffnx {Scheme Procedure} assv key alist +@deffnx {Scheme Procedure} assoc key alist +@deffnx {C Function} scm_assq (key, alist) +@deffnx {C Function} scm_assv (key, alist) +@deffnx {C Function} scm_assoc (key, alist) +Return the first entry in @var{alist} with the given @var{key}. The +return is the pair @code{(KEY . VALUE)} from @var{alist}. If there's +no matching entry the return is @code{#f}. + +@code{assq} compares keys with @code{eq?}, @code{assv} uses +@code{eqv?} and @code{assoc} uses @code{equal?}. See also SRFI-1 +which has an extended @code{assoc} (@ref{SRFI-1 Association Lists}). +@end deffn + +@deffn {Scheme Procedure} assq-ref alist key +@deffnx {Scheme Procedure} assv-ref alist key +@deffnx {Scheme Procedure} assoc-ref alist key +@deffnx {C Function} scm_assq_ref (alist, key) +@deffnx {C Function} scm_assv_ref (alist, key) +@deffnx {C Function} scm_assoc_ref (alist, key) +Return the value from the first entry in @var{alist} with the given +@var{key}, or @code{#f} if there's no such entry. + +@code{assq-ref} compares keys with @code{eq?}, @code{assv-ref} uses +@code{eqv?} and @code{assoc-ref} uses @code{equal?}. + +Notice these functions have the @var{key} argument last, like other +@code{-ref} functions, but this is opposite to what @code{assq} +etc above use. + +When the return is @code{#f} it can be either @var{key} not found, or +an entry which happens to have value @code{#f} in the @code{cdr}. Use +@code{assq} etc above if you need to differentiate these cases. +@end deffn + + +@node Removing Alist Entries +@subsubsection Removing Alist Entries + +To remove the element from an association list whose key matches a +specified key, use @code{assq-remove!}, @code{assv-remove!} or +@code{assoc-remove!} (depending, as usual, on the level of equality +required between the key that you specify and the keys in the +association list). + +As with @code{assq-set!} and friends, the specified alist may or may not +be modified destructively, and the only safe way to update a variable +containing the alist is to @code{set!} it to the value that +@code{assq-remove!} and friends return. + +@example +address-list +@result{} +(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road") + ("james" . "1a London Road")) + +(set! address-list (assoc-remove! address-list "mary")) +address-list +@result{} +(("bob" . "11 Newington Avenue") ("james" . "1a London Road")) +@end example + +Note that, when @code{assq/v/oc-remove!} is used to modify an +association list that has been constructed only using the corresponding +@code{assq/v/oc-set!}, there can be at most one matching entry in the +alist, so the question of multiple entries being removed in one go does +not arise. If @code{assq/v/oc-remove!} is applied to an association +list that has been constructed using @code{acons}, or an +@code{assq/v/oc-set!} with a different level of equality, or any mixture +of these, it removes only the first matching entry from the alist, even +if the alist might contain further matching entries. For example: + +@example +(define address-list '()) +(set! address-list (assq-set! address-list "mary" "11 Elm Street")) +(set! address-list (assq-set! address-list "mary" "57 Pine Drive")) +address-list +@result{} +(("mary" . "57 Pine Drive") ("mary" . "11 Elm Street")) + +(set! address-list (assoc-remove! address-list "mary")) +address-list +@result{} +(("mary" . "11 Elm Street")) +@end example + +In this example, the two instances of the string "mary" are not the same +when compared using @code{eq?}, so the two @code{assq-set!} calls add +two distinct entries to @code{address-list}. When compared using +@code{equal?}, both "mary"s in @code{address-list} are the same as the +"mary" in the @code{assoc-remove!} call, but @code{assoc-remove!} stops +after removing the first matching entry that it finds, and so one of the +"mary" entries is left in place. + +@deffn {Scheme Procedure} assq-remove! alist key +@deffnx {Scheme Procedure} assv-remove! alist key +@deffnx {Scheme Procedure} assoc-remove! alist key +@deffnx {C Function} scm_assq_remove_x (alist, key) +@deffnx {C Function} scm_assv_remove_x (alist, key) +@deffnx {C Function} scm_assoc_remove_x (alist, key) +Delete the first entry in @var{alist} associated with @var{key}, and return +the resulting alist. +@end deffn + +@node Sloppy Alist Functions +@subsubsection Sloppy Alist Functions + +@code{sloppy-assq}, @code{sloppy-assv} and @code{sloppy-assoc} behave +like the corresponding non-@code{sloppy-} procedures, except that they +return @code{#f} when the specified association list is not well-formed, +where the non-@code{sloppy-} versions would signal an error. + +Specifically, there are two conditions for which the non-@code{sloppy-} +procedures signal an error, which the @code{sloppy-} procedures handle +instead by returning @code{#f}. Firstly, if the specified alist as a +whole is not a proper list: + +@example +(assoc "mary" '((1 . 2) ("key" . "door") . "open sesame")) +@result{} +ERROR: In procedure assoc in expression (assoc "mary" (quote #)): +ERROR: Wrong type argument in position 2 (expecting + association list): ((1 . 2) ("key" . "door") . "open sesame") + +(sloppy-assoc "mary" '((1 . 2) ("key" . "door") . "open sesame")) +@result{} +#f +@end example + +@noindent +Secondly, if one of the entries in the specified alist is not a pair: + +@example +(assoc 2 '((1 . 1) 2 (3 . 9))) +@result{} +ERROR: In procedure assoc in expression (assoc 2 (quote #)): +ERROR: Wrong type argument in position 2 (expecting + association list): ((1 . 1) 2 (3 . 9)) + +(sloppy-assoc 2 '((1 . 1) 2 (3 . 9))) +@result{} +#f +@end example + +Unless you are explicitly working with badly formed association lists, +it is much safer to use the non-@code{sloppy-} procedures, because they +help to highlight coding and data errors that the @code{sloppy-} +versions would silently cover up. + +@deffn {Scheme Procedure} sloppy-assq key alist +@deffnx {C Function} scm_sloppy_assq (key, alist) +Behaves like @code{assq} but does not do any error checking. +Recommended only for use in Guile internals. +@end deffn + +@deffn {Scheme Procedure} sloppy-assv key alist +@deffnx {C Function} scm_sloppy_assv (key, alist) +Behaves like @code{assv} but does not do any error checking. +Recommended only for use in Guile internals. +@end deffn + +@deffn {Scheme Procedure} sloppy-assoc key alist +@deffnx {C Function} scm_sloppy_assoc (key, alist) +Behaves like @code{assoc} but does not do any error checking. +Recommended only for use in Guile internals. +@end deffn + +@node Alist Example +@subsubsection Alist Example + +Here is a longer example of how alists may be used in practice. + +@lisp +(define capitals '(("New York" . "Albany") + ("Oregon" . "Salem") + ("Florida" . "Miami"))) + +;; What's the capital of Oregon? +(assoc "Oregon" capitals) @result{} ("Oregon" . "Salem") +(assoc-ref capitals "Oregon") @result{} "Salem" + +;; We left out South Dakota. +(set! capitals + (assoc-set! capitals "South Dakota" "Pierre")) +capitals +@result{} (("South Dakota" . "Pierre") + ("New York" . "Albany") + ("Oregon" . "Salem") + ("Florida" . "Miami")) + +;; And we got Florida wrong. +(set! capitals + (assoc-set! capitals "Florida" "Tallahassee")) +capitals +@result{} (("South Dakota" . "Pierre") + ("New York" . "Albany") + ("Oregon" . "Salem") + ("Florida" . "Tallahassee")) + +;; After Oregon secedes, we can remove it. +(set! capitals + (assoc-remove! capitals "Oregon")) +capitals +@result{} (("South Dakota" . "Pierre") + ("New York" . "Albany") + ("Florida" . "Tallahassee")) +@end lisp + +@node VHashes +@subsection VList-Based Hash Lists or ``VHashes'' + +@cindex VList-based hash lists +@cindex VHash + +The @code{(ice-9 vlist)} module provides an implementation of @dfn{VList-based +hash lists} (@pxref{VLists}). VList-based hash lists, or @dfn{vhashes}, are an +immutable dictionary type similar to association lists that maps @dfn{keys} to +@dfn{values}. However, unlike association lists, accessing a value given its +key is typically a constant-time operation. + +The VHash programming interface of @code{(ice-9 vlist)} is mostly the same as +that of association lists found in SRFI-1, with procedure names prefixed by +@code{vhash-} instead of @code{alist-} (@pxref{SRFI-1 Association Lists}). + +In addition, vhashes can be manipulated using VList operations: + +@example +(vlist-head (vhash-consq 'a 1 vlist-null)) +@result{} (a . 1) + +(define vh1 (vhash-consq 'b 2 (vhash-consq 'a 1 vlist-null))) +(define vh2 (vhash-consq 'c 3 (vlist-tail vh1))) + +(vhash-assq 'a vh2) +@result{} (a . 1) +(vhash-assq 'b vh2) +@result{} #f +(vhash-assq 'c vh2) +@result{} (c . 3) +(vlist->list vh2) +@result{} ((c . 3) (a . 1)) +@end example + +However, keep in mind that procedures that construct new VLists +(@code{vlist-map}, @code{vlist-filter}, etc.) return raw VLists, not vhashes: + +@example +(define vh (alist->vhash '((a . 1) (b . 2) (c . 3)) hashq)) +(vhash-assq 'a vh) +@result{} (a . 1) + +(define vl + ;; This will create a raw vlist. + (vlist-filter (lambda (key+value) (odd? (cdr key+value))) vh)) +(vhash-assq 'a vl) +@result{} ERROR: Wrong type argument in position 2 + +(vlist->list vl) +@result{} ((a . 1) (c . 3)) +@end example + +@deffn {Scheme Procedure} vhash? obj +Return true if @var{obj} is a vhash. +@end deffn + +@deffn {Scheme Procedure} vhash-cons key value vhash [hash-proc] +@deffnx {Scheme Procedure} vhash-consq key value vhash +@deffnx {Scheme Procedure} vhash-consv key value vhash +Return a new hash list based on @var{vhash} where @var{key} is associated with +@var{value}, using @var{hash-proc} to compute the hash of @var{key}. +@var{vhash} must be either @code{vlist-null} or a vhash returned by a previous +call to @code{vhash-cons}. @var{hash-proc} defaults to @code{hash} (@pxref{Hash +Table Reference, @code{hash} procedure}). With @code{vhash-consq}, the +@code{hashq} hash function is used; with @code{vhash-consv} the @code{hashv} +hash function is used. + +All @code{vhash-cons} calls made to construct a vhash should use the same +@var{hash-proc}. Failing to do that, the result is undefined. +@end deffn + +@deffn {Scheme Procedure} vhash-assoc key vhash [equal? [hash-proc]] +@deffnx {Scheme Procedure} vhash-assq key vhash +@deffnx {Scheme Procedure} vhash-assv key vhash +Return the first key/value pair from @var{vhash} whose key is equal to @var{key} +according to the @var{equal?} equality predicate (which defaults to +@code{equal?}), and using @var{hash-proc} (which defaults to @code{hash}) to +compute the hash of @var{key}. The second form uses @code{eq?} as the equality +predicate and @code{hashq} as the hash function; the last form uses @code{eqv?} +and @code{hashv}. + +Note that it is important to consistently use the same hash function for +@var{hash-proc} as was passed to @code{vhash-cons}. Failing to do that, the +result is unpredictable. +@end deffn + +@deffn {Scheme Procedure} vhash-delete key vhash [equal? [hash-proc]] +@deffnx {Scheme Procedure} vhash-delq key vhash +@deffnx {Scheme Procedure} vhash-delv key vhash +Remove all associations from @var{vhash} with @var{key}, comparing keys with +@var{equal?} (which defaults to @code{equal?}), and computing the hash of +@var{key} using @var{hash-proc} (which defaults to @code{hash}). The second +form uses @code{eq?} as the equality predicate and @code{hashq} as the hash +function; the last one uses @code{eqv?} and @code{hashv}. + +Again the choice of @var{hash-proc} must be consistent with previous calls to +@code{vhash-cons}. +@end deffn + +@deffn {Scheme Procedure} vhash-fold proc init vhash +@deffnx {Scheme Procedure} vhash-fold-right proc init vhash +Fold over the key/value elements of @var{vhash} in the given direction, +with each call to @var{proc} having the form @code{(@var{proc} key value +result)}, where @var{result} is the result of the previous call to +@var{proc} and @var{init} the value of @var{result} for the first call +to @var{proc}. +@end deffn + +@deffn {Scheme Procedure} vhash-fold* proc init key vhash [equal? [hash]] +@deffnx {Scheme Procedure} vhash-foldq* proc init key vhash +@deffnx {Scheme Procedure} vhash-foldv* proc init key vhash +Fold over all the values associated with @var{key} in @var{vhash}, with each +call to @var{proc} having the form @code{(proc value result)}, where +@var{result} is the result of the previous call to @var{proc} and @var{init} the +value of @var{result} for the first call to @var{proc}. + +Keys in @var{vhash} are hashed using @var{hash} are compared using @var{equal?}. +The second form uses @code{eq?} as the equality predicate and @code{hashq} as +the hash function; the third one uses @code{eqv?} and @code{hashv}. + +Example: + +@example +(define vh + (alist->vhash '((a . 1) (a . 2) (z . 0) (a . 3)))) + +(vhash-fold* cons '() 'a vh) +@result{} (3 2 1) + +(vhash-fold* cons '() 'z vh) +@result{} (0) +@end example +@end deffn + +@deffn {Scheme Procedure} alist->vhash alist [hash-proc] +Return the vhash corresponding to @var{alist}, an association list, using +@var{hash-proc} to compute key hashes. When omitted, @var{hash-proc} defaults +to @code{hash}. +@end deffn + + +@node Hash Tables +@subsection Hash Tables +@tpindex Hash Tables + +Hash tables are dictionaries which offer similar functionality as +association lists: They provide a mapping from keys to values. The +difference is that association lists need time linear in the size of +elements when searching for entries, whereas hash tables can normally +search in constant time. The drawback is that hash tables require a +little bit more memory, and that you can not use the normal list +procedures (@pxref{Lists}) for working with them. + +@menu +* Hash Table Examples:: Demonstration of hash table usage. +* Hash Table Reference:: Hash table procedure descriptions. +@end menu + + +@node Hash Table Examples +@subsubsection Hash Table Examples + +For demonstration purposes, this section gives a few usage examples of +some hash table procedures, together with some explanation what they do. + +First we start by creating a new hash table with 31 slots, and +populate it with two key/value pairs. + +@lisp +(define h (make-hash-table 31)) + +;; This is an opaque object +h +@result{} +#<hash-table 0/31> + +;; Inserting into a hash table can be done with hashq-set! +(hashq-set! h 'foo "bar") +@result{} +"bar" + +(hashq-set! h 'braz "zonk") +@result{} +"zonk" + +;; Or with hash-create-handle! +(hashq-create-handle! h 'frob #f) +@result{} +(frob . #f) +@end lisp + +You can get the value for a given key with the procedure +@code{hashq-ref}, but the problem with this procedure is that you +cannot reliably determine whether a key does exists in the table. The +reason is that the procedure returns @code{#f} if the key is not in +the table, but it will return the same value if the key is in the +table and just happens to have the value @code{#f}, as you can see in +the following examples. + +@lisp +(hashq-ref h 'foo) +@result{} +"bar" + +(hashq-ref h 'frob) +@result{} +#f + +(hashq-ref h 'not-there) +@result{} +#f +@end lisp + +It is often better is to use the procedure @code{hashq-get-handle}, +which makes a distinction between the two cases. Just like @code{assq}, +this procedure returns a key/value-pair on success, and @code{#f} if the +key is not found. + +@lisp +(hashq-get-handle h 'foo) +@result{} +(foo . "bar") + +(hashq-get-handle h 'not-there) +@result{} +#f +@end lisp + +Interesting results can be computed by using @code{hash-fold} to work +through each element. This example will count the total number of +elements: + +@lisp +(hash-fold (lambda (key value seed) (+ 1 seed)) 0 h) +@result{} +3 +@end lisp + +The same thing can be done with the procedure @code{hash-count}, which +can also count the number of elements matching a particular predicate. +For example, count the number of elements with string values: + +@lisp +(hash-count (lambda (key value) (string? value)) h) +@result{} +2 +@end lisp + +Counting all the elements is a simple task using @code{const}: + +@lisp +(hash-count (const #t) h) +@result{} +3 +@end lisp + +@node Hash Table Reference +@subsubsection Hash Table Reference + +@c FIXME: Describe in broad terms what happens for resizing, and what +@c the initial size means for this. + +Like the association list functions, the hash table functions come in +several varieties, according to the equality test used for the keys. +Plain @code{hash-} functions use @code{equal?}, @code{hashq-} +functions use @code{eq?}, @code{hashv-} functions use @code{eqv?}, and +the @code{hashx-} functions use an application supplied test. + +A single @code{make-hash-table} creates a hash table suitable for use +with any set of functions, but it's imperative that just one set is +then used consistently, or results will be unpredictable. + +Hash tables are implemented as a vector indexed by a hash value formed +from the key, with an association list of key/value pairs for each +bucket in case distinct keys hash together. Direct access to the +pairs in those lists is provided by the @code{-handle-} functions. + +When the number of entries in a hash table goes above a threshold, the +vector is made larger and the entries are rehashed, to prevent the +bucket lists from becoming too long and slowing down accesses. When the +number of entries goes below a threshold, the vector is shrunk to save +space. + +For the @code{hashx-} ``extended'' routines, an application supplies a +@var{hash} function producing an integer index like @code{hashq} etc +below, and an @var{assoc} alist search function like @code{assq} etc +(@pxref{Retrieving Alist Entries}). Here's an example of such +functions implementing case-insensitive hashing of string keys, + +@example +(use-modules (srfi srfi-1) + (srfi srfi-13)) + +(define (my-hash str size) + (remainder (string-hash-ci str) size)) +(define (my-assoc str alist) + (find (lambda (pair) (string-ci=? str (car pair))) alist)) + +(define my-table (make-hash-table)) +(hashx-set! my-hash my-assoc my-table "foo" 123) + +(hashx-ref my-hash my-assoc my-table "FOO") +@result{} 123 +@end example + +In a @code{hashx-} @var{hash} function the aim is to spread keys +across the vector, so bucket lists don't become long. But the actual +values are arbitrary as long as they're in the range 0 to +@math{@var{size}-1}. Helpful functions for forming a hash value, in +addition to @code{hashq} etc below, include @code{symbol-hash} +(@pxref{Symbol Keys}), @code{string-hash} and @code{string-hash-ci} +(@pxref{String Comparison}), and @code{char-set-hash} +(@pxref{Character Set Predicates/Comparison}). + +@sp 1 +@deffn {Scheme Procedure} make-hash-table [size] +Create a new hash table object, with an optional minimum +vector @var{size}. + +When @var{size} is given, the table vector will still grow and shrink +automatically, as described above, but with @var{size} as a minimum. +If an application knows roughly how many entries the table will hold +then it can use @var{size} to avoid rehashing when initial entries are +added. +@end deffn + +@deffn {Scheme Procedure} alist->hash-table alist +@deffnx {Scheme Procedure} alist->hashq-table alist +@deffnx {Scheme Procedure} alist->hashv-table alist +@deffnx {Scheme Procedure} alist->hashx-table hash assoc alist +Convert @var{alist} into a hash table. When keys are repeated in +@var{alist}, the leftmost association takes precedence. + +@example +(use-modules (ice-9 hash-table)) +(alist->hash-table '((foo . 1) (bar . 2))) +@end example + +When converting to an extended hash table, custom @var{hash} and +@var{assoc} procedures must be provided. + +@example +(alist->hashx-table hash assoc '((foo . 1) (bar . 2))) +@end example + +@end deffn + +@deffn {Scheme Procedure} hash-table? obj +@deffnx {C Function} scm_hash_table_p (obj) +Return @code{#t} if @var{obj} is a abstract hash table object. +@end deffn + +@deffn {Scheme Procedure} hash-clear! table +@deffnx {C Function} scm_hash_clear_x (table) +Remove all items from @var{table} (without triggering a resize). +@end deffn + +@deffn {Scheme Procedure} hash-ref table key [dflt] +@deffnx {Scheme Procedure} hashq-ref table key [dflt] +@deffnx {Scheme Procedure} hashv-ref table key [dflt] +@deffnx {Scheme Procedure} hashx-ref hash assoc table key [dflt] +@deffnx {C Function} scm_hash_ref (table, key, dflt) +@deffnx {C Function} scm_hashq_ref (table, key, dflt) +@deffnx {C Function} scm_hashv_ref (table, key, dflt) +@deffnx {C Function} scm_hashx_ref (hash, assoc, table, key, dflt) +Lookup @var{key} in the given hash @var{table}, and return the +associated value. If @var{key} is not found, return @var{dflt}, or +@code{#f} if @var{dflt} is not given. +@end deffn + +@deffn {Scheme Procedure} hash-set! table key val +@deffnx {Scheme Procedure} hashq-set! table key val +@deffnx {Scheme Procedure} hashv-set! table key val +@deffnx {Scheme Procedure} hashx-set! hash assoc table key val +@deffnx {C Function} scm_hash_set_x (table, key, val) +@deffnx {C Function} scm_hashq_set_x (table, key, val) +@deffnx {C Function} scm_hashv_set_x (table, key, val) +@deffnx {C Function} scm_hashx_set_x (hash, assoc, table, key, val) +Associate @var{val} with @var{key} in the given hash @var{table}. If +@var{key} is already present then it's associated value is changed. +If it's not present then a new entry is created. +@end deffn + +@deffn {Scheme Procedure} hash-remove! table key +@deffnx {Scheme Procedure} hashq-remove! table key +@deffnx {Scheme Procedure} hashv-remove! table key +@deffnx {Scheme Procedure} hashx-remove! hash assoc table key +@deffnx {C Function} scm_hash_remove_x (table, key) +@deffnx {C Function} scm_hashq_remove_x (table, key) +@deffnx {C Function} scm_hashv_remove_x (table, key) +@deffnx {C Function} scm_hashx_remove_x (hash, assoc, table, key) +Remove any association for @var{key} in the given hash @var{table}. +If @var{key} is not in @var{table} then nothing is done. +@end deffn + +@deffn {Scheme Procedure} hash key size +@deffnx {Scheme Procedure} hashq key size +@deffnx {Scheme Procedure} hashv key size +@deffnx {C Function} scm_hash (key, size) +@deffnx {C Function} scm_hashq (key, size) +@deffnx {C Function} scm_hashv (key, size) +Return a hash value for @var{key}. This is a number in the range +@math{0} to @math{@var{size}-1}, which is suitable for use in a hash +table of the given @var{size}. + +Note that @code{hashq} and @code{hashv} may use internal addresses of +objects, so if an object is garbage collected and re-created it can +have a different hash value, even when the two are notionally +@code{eq?}. For instance with symbols, + +@example +(hashq 'something 123) @result{} 19 +(gc) +(hashq 'something 123) @result{} 62 +@end example + +In normal use this is not a problem, since an object entered into a +hash table won't be garbage collected until removed. It's only if +hashing calculations are somehow separated from normal references that +its lifetime needs to be considered. +@end deffn + +@deffn {Scheme Procedure} hash-get-handle table key +@deffnx {Scheme Procedure} hashq-get-handle table key +@deffnx {Scheme Procedure} hashv-get-handle table key +@deffnx {Scheme Procedure} hashx-get-handle hash assoc table key +@deffnx {C Function} scm_hash_get_handle (table, key) +@deffnx {C Function} scm_hashq_get_handle (table, key) +@deffnx {C Function} scm_hashv_get_handle (table, key) +@deffnx {C Function} scm_hashx_get_handle (hash, assoc, table, key) +Return the @code{(@var{key} . @var{value})} pair for @var{key} in the +given hash @var{table}, or @code{#f} if @var{key} is not in +@var{table}. +@end deffn + +@deffn {Scheme Procedure} hash-create-handle! table key init +@deffnx {Scheme Procedure} hashq-create-handle! table key init +@deffnx {Scheme Procedure} hashv-create-handle! table key init +@deffnx {Scheme Procedure} hashx-create-handle! hash assoc table key init +@deffnx {C Function} scm_hash_create_handle_x (table, key, init) +@deffnx {C Function} scm_hashq_create_handle_x (table, key, init) +@deffnx {C Function} scm_hashv_create_handle_x (table, key, init) +@deffnx {C Function} scm_hashx_create_handle_x (hash, assoc, table, key, init) +Return the @code{(@var{key} . @var{value})} pair for @var{key} in the +given hash @var{table}. If @var{key} is not in @var{table} then +create an entry for it with @var{init} as the value, and return that +pair. +@end deffn + +@deffn {Scheme Procedure} hash-map->list proc table +@deffnx {Scheme Procedure} hash-for-each proc table +@deffnx {C Function} scm_hash_map_to_list (proc, table) +@deffnx {C Function} scm_hash_for_each (proc, table) +Apply @var{proc} to the entries in the given hash @var{table}. Each +call is @code{(@var{proc} @var{key} @var{value})}. @code{hash-map->list} +returns a list of the results from these calls, @code{hash-for-each} +discards the results and returns an unspecified value. + +Calls are made over the table entries in an unspecified order, and for +@code{hash-map->list} the order of the values in the returned list is +unspecified. Results will be unpredictable if @var{table} is modified +while iterating. + +For example the following returns a new alist comprising all the +entries from @code{mytable}, in no particular order. + +@example +(hash-map->list cons mytable) +@end example +@end deffn + +@deffn {Scheme Procedure} hash-for-each-handle proc table +@deffnx {C Function} scm_hash_for_each_handle (proc, table) +Apply @var{proc} to the entries in the given hash @var{table}. Each +call is @code{(@var{proc} @var{handle})}, where @var{handle} is a +@code{(@var{key} . @var{value})} pair. Return an unspecified value. + +@code{hash-for-each-handle} differs from @code{hash-for-each} only in +the argument list of @var{proc}. +@end deffn + +@deffn {Scheme Procedure} hash-fold proc init table +@deffnx {C Function} scm_hash_fold (proc, init, table) +Accumulate a result by applying @var{proc} to the elements of the +given hash @var{table}. Each call is @code{(@var{proc} @var{key} +@var{value} @var{prior-result})}, where @var{key} and @var{value} are +from the @var{table} and @var{prior-result} is the return from the +previous @var{proc} call. For the first call, @var{prior-result} is +the given @var{init} value. + +Calls are made over the table entries in an unspecified order. +Results will be unpredictable if @var{table} is modified while +@code{hash-fold} is running. + +For example, the following returns a count of how many keys in +@code{mytable} are strings. + +@example +(hash-fold (lambda (key value prior) + (if (string? key) (1+ prior) prior)) + 0 mytable) +@end example +@end deffn + +@deffn {Scheme Procedure} hash-count pred table +@deffnx {C Function} scm_hash_count (pred, table) +Return the number of elements in the given hash @var{table} that cause +@code{(@var{pred} @var{key} @var{value})} to return true. To quickly +determine the total number of elements, use @code{(const #t)} for +@var{pred}. +@end deffn + +@node Other Types +@subsection Other Types + +Procedures are documented in their own section. @xref{Procedures}. + +Variable objects are documented as part of the description of Guile's +module system: see @ref{Variables}. + +@xref{Scheduling}, for discussion of threads, mutexes, and so on. + +Ports are described in the section on I/O: see @ref{Input and Output}. + +Regular expressions are described in their own section: see @ref{Regular +Expressions}. + +There are quite a number of additional data types documented in this +manual; if you feel a link is missing here, please file a bug. + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi new file mode 100644 index 000000000..4fc295dc5 --- /dev/null +++ b/doc/ref/api-debug.texi @@ -0,0 +1,1529 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2010, 2011, 2012, 2013, 2014, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Debugging +@section Debugging Infrastructure + +@cindex Debugging +In order to understand Guile's debugging facilities, you first need to +understand a little about how Guile represent the Scheme control stack. +With that in place we explain the low level trap calls that the virtual +machine can be configured to make, and the trap and breakpoint +infrastructure that builds on top of those calls. + +@menu +* Evaluation Model:: Evaluation and the Scheme stack. +* Source Properties:: From expressions to source locations. +* Programmatic Error Handling:: Debugging when an error occurs. +* Traps:: Breakpoints, tracepoints, oh my! +* GDB Support:: C-level debugging with GDB. +@end menu + +@node Evaluation Model +@subsection Evaluation and the Scheme Stack + +The idea of the Scheme stack is central to a lot of debugging. The +Scheme stack is a reified representation of the pending function returns +in an expression's continuation. As Guile implements function calls +using a stack, this reification takes the form of a number of nested +stack frames, each of which corresponds to the application of a +procedure to a set of arguments. + +A Scheme stack always exists implicitly, and can be summoned into +concrete existence as a first-class Scheme value by the +@code{make-stack} call, so that an introspective Scheme program -- such +as a debugger -- can present it in some way and allow the user to query +its details. The first thing to understand, therefore, is how Guile's +function call convention creates the stack. + +Broadly speaking, Guile represents all control flow on a stack. Calling +a function involves pushing an empty frame on the stack, then evaluating +the procedure and its arguments, then fixing up the new frame so that it +points to the old one. Frames on the stack are thus linked together. A +tail call is the same, except it reuses the existing frame instead of +pushing on a new one. + +In this way, the only frames that are on the stack are ``active'' +frames, frames which need to do some work before the computation is +complete. On the other hand, a function that has tail-called another +function will not be on the stack, as it has no work left to do. + +Therefore, when an error occurs in a running program, or the program +hits a breakpoint, or in fact at any point that the programmer chooses, +its state at that point can be represented by a @dfn{stack} of all the +procedure applications that are logically in progress at that time, each +of which is known as a @dfn{frame}. The programmer can learn more about +the program's state at that point by inspecting the stack and its +frames. + +@menu +* Stack Capture:: Reifying a continuation. +* Stacks:: Accessors for the stack data type. +* Frames:: Likewise, accessors for stack frames. +@end menu + +@node Stack Capture +@subsubsection Stack Capture + +A Scheme program can use the @code{make-stack} primitive anywhere in its +code, with first arg @code{#t}, to construct a Scheme value that +describes the Scheme stack at that point. + +@lisp +(make-stack #t) +@result{} +#<stack 25205a0> +@end lisp + +Use @code{start-stack} to limit the stack extent captured by future +@code{make-stack} calls. + +@deffn {Scheme Procedure} make-stack obj arg @dots{} +@deffnx {C Function} scm_make_stack (obj, args) +Create a new stack. If @var{obj} is @code{#t}, the current +evaluation stack is used for creating the stack frames, +otherwise the frames are taken from @var{obj} (which must be +a continuation or a frame object). + +@var{arg} @dots{} can be any combination of integer, procedure, address +range, and prompt tag values. + +These values specify various ways of cutting away uninteresting stack +frames from the top and bottom of the stack that @code{make-stack} +returns. They come in pairs like this: @code{(@var{inner_cut_1} +@var{outer_cut_1} @var{inner_cut_2} @var{outer_cut_2} @dots{})}. + +Each @var{inner_cut_i} can be an integer, a procedure, an address range, +or a prompt tag. An integer means to cut away exactly that number of +frames. A procedure means to cut away all frames up to but excluding +the frame whose procedure matches the specified one. An address range +is a pair of integers indicating the low and high addresses of a +procedure's code, and is the same as cutting away to a procedure (though +with less work). Anything else is interpreted as a prompt tag which +cuts away all frames that are inside a prompt with the given tag. + +Each @var{outer_cut_i} can likewise be an integer, a procedure, an +address range, or a prompt tag. An integer means to cut away that +number of frames. A procedure means to cut away frames down to but +excluding the frame whose procedure matches the specified one. An +address range is the same, but with the procedure's code specified as an +address range. Anything else is taken to be a prompt tag, which cuts +away all frames that are outside a prompt with the given tag. + + +If the @var{outer_cut_i} of the last pair is missing, it is taken as 0. +@end deffn + +@deffn {Scheme Syntax} start-stack id exp +Evaluate @var{exp} on a new calling stack with identity @var{id}. If +@var{exp} is interrupted during evaluation, backtraces will not display +frames farther back than @var{exp}'s top-level form. This macro is a +way of artificially limiting backtraces and stack procedures, largely as +a convenience to the user. +@end deffn + + +@node Stacks +@subsubsection Stacks + +@deffn {Scheme Procedure} stack? obj +@deffnx {C Function} scm_stack_p (obj) +Return @code{#t} if @var{obj} is a calling stack. +@end deffn + +@deffn {Scheme Procedure} stack-id stack +@deffnx {C Function} scm_stack_id (stack) +Return the identifier given to @var{stack} by @code{start-stack}. +@end deffn + +@deffn {Scheme Procedure} stack-length stack +@deffnx {C Function} scm_stack_length (stack) +Return the length of @var{stack}. +@end deffn + +@deffn {Scheme Procedure} stack-ref stack index +@deffnx {C Function} scm_stack_ref (stack, index) +Return the @var{index}'th frame from @var{stack}. +@end deffn + +@deffn {Scheme Procedure} display-backtrace stack port [first [depth [highlights]]] +@deffnx {C Function} scm_display_backtrace_with_highlights (stack, port, first, depth, highlights) +@deffnx {C Function} scm_display_backtrace (stack, port, first, depth) +Display a backtrace to the output port @var{port}. @var{stack} +is the stack to take the backtrace from, @var{first} specifies +where in the stack to start and @var{depth} how many frames +to display. @var{first} and @var{depth} can be @code{#f}, +which means that default values will be used. +If @var{highlights} is given it should be a list; the elements +of this list will be highlighted wherever they appear in the +backtrace. +@end deffn + + +@node Frames +@subsubsection Frames + +@deffn {Scheme Procedure} frame? obj +@deffnx {C Function} scm_frame_p (obj) +Return @code{#t} if @var{obj} is a stack frame. +@end deffn + +@deffn {Scheme Procedure} frame-previous frame +@deffnx {C Function} scm_frame_previous (frame) +Return the previous frame of @var{frame}, or @code{#f} if +@var{frame} is the first frame in its stack. +@end deffn + +@deffn {Scheme Procedure} frame-procedure-name frame +@deffnx {C Function} scm_frame_procedure_name (frame) +Return the name of the procedure being applied in @var{frame}, as a +symbol, or @code{#f} if the procedure has no name. +@end deffn + +@deffn {Scheme Procedure} frame-arguments frame +@deffnx {C Function} scm_frame_arguments (frame) +Return the arguments of @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-address frame +@deffnx {Scheme Procedure} frame-instruction-pointer frame +@deffnx {Scheme Procedure} frame-stack-pointer frame +Accessors for the three VM registers associated with this frame: the +frame pointer (fp), instruction pointer (ip), and stack pointer (sp), +respectively. @xref{VM Concepts}, for more information. +@end deffn + +@deffn {Scheme Procedure} frame-dynamic-link frame +@deffnx {Scheme Procedure} frame-return-address frame +@deffnx {Scheme Procedure} frame-mv-return-address frame +Accessors for the three saved VM registers in a frame: the previous +frame pointer, the single-value return address, and the multiple-value +return address. @xref{Stack Layout}, for more information. +@end deffn + +@deffn {Scheme Procedure} frame-bindings frame +Return a list of binding records indicating the local variables that are +live in a frame. +@end deffn + +@deffn {Scheme Procedure} frame-lookup-binding frame var +Fetch the bindings in @var{frame}, and return the first one whose name +is @var{var}, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} binding-index binding +@deffnx {Scheme Procedure} binding-name binding +@deffnx {Scheme Procedure} binding-slot binding +@deffnx {Scheme Procedure} binding-representation binding +Accessors for the various fields in a binding. The implicit ``callee'' +argument is index 0, the first argument is index 1, and so on to the end +of the arguments. After that are temporary variables. Note that if a +variable is dead, it might not be available. +@end deffn + +@deffn {Scheme Procedure} binding-ref binding +@deffnx {Scheme Procedure} binding-set! binding val +Accessors for the values of local variables in a frame. +@end deffn + +@deffn {Scheme Procedure} display-application frame [port [indent]] +@deffnx {C Function} scm_display_application (frame, port, indent) +Display a procedure application @var{frame} to the output port +@var{port}. @var{indent} specifies the indentation of the +output. +@end deffn + +Additionally, the @code{(system vm frame)} module defines a number of +higher-level introspective procedures, for example to retrieve the names +of local variables, and the source location to correspond to a +frame. See its source code for more details. + + +@node Source Properties +@subsection Source Properties + +@cindex source properties +As Guile reads in Scheme code from file or from standard input, it +remembers the file name, line number and column number where each +expression begins. These pieces of information are known as the +@dfn{source properties} of the expression. Syntax expanders and the +compiler propagate these source properties to compiled procedures, so +that, if an error occurs when evaluating the transformed expression, +Guile's debugger can point back to the file and location where the +expression originated. + +The way that source properties are stored means that Guile cannot +associate source properties with individual symbols, keywords, +characters, booleans, or small integers. This can be seen by typing +@code{(xxx)} and @code{xxx} at the Guile prompt (where the variable +@code{xxx} has not been defined): + +@example +scheme@@(guile-user)> (xxx) +<unnamed port>:4:1: In procedure module-lookup: +<unnamed port>:4:1: Unbound variable: xxx + +scheme@@(guile-user)> xxx +ERROR: In procedure module-lookup: +ERROR: Unbound variable: xxx +@end example + +@noindent +In the latter case, no source properties were stored, so the error +doesn't have any source information. + +@deffn {Scheme Procedure} supports-source-properties? obj +@deffnx {C Function} scm_supports_source_properties_p (obj) +Return #t if source properties can be associated with @var{obj}, +otherwise return #f. +@end deffn + +The recording of source properties is controlled by the read option +named ``positions'' (@pxref{Scheme Read}). This option is switched +@emph{on} by default. + +The following procedures can be used to access and set the source +properties of read expressions. + +@deffn {Scheme Procedure} set-source-properties! obj alist +@deffnx {C Function} scm_set_source_properties_x (obj, alist) +Install the association list @var{alist} as the source property +list for @var{obj}. +@end deffn + +@deffn {Scheme Procedure} set-source-property! obj key datum +@deffnx {C Function} scm_set_source_property_x (obj, key, datum) +Set the source property of object @var{obj}, which is specified by +@var{key} to @var{datum}. Normally, the key will be a symbol. +@end deffn + +@deffn {Scheme Procedure} source-properties obj +@deffnx {C Function} scm_source_properties (obj) +Return the source property association list of @var{obj}. +@end deffn + +@deffn {Scheme Procedure} source-property obj key +@deffnx {C Function} scm_source_property (obj, key) +Return the property specified by @var{key} from @var{obj}'s source +properties. +@end deffn + +If the @code{positions} reader option is enabled, supported expressions +will have values set for the @code{filename}, @code{line} and +@code{column} properties. + +Source properties are also associated with syntax objects. Procedural +macros can get at the source location of their input using the +@code{syntax-source} accessor. @xref{Syntax Transformer Helpers}, for +more. + +Guile also defines a couple of convenience macros built on +@code{syntax-source}: + +@deffn {Scheme Syntax} current-source-location +Expands to the source properties corresponding to the location of the +@code{(current-source-location)} form. +@end deffn + +@deffn {Scheme Syntax} current-filename +Expands to the current filename: the filename that the +@code{(current-filename)} form appears in. Expands to @code{#f} if this +information is unavailable. +@end deffn + +If you're stuck with defmacros (@pxref{Defmacros}), and want to preserve +source information, the following helper function might be useful to +you: + +@deffn {Scheme Procedure} cons-source xorig x y +@deffnx {C Function} scm_cons_source (xorig, x, y) +Create and return a new pair whose car and cdr are @var{x} and @var{y}. +Any source properties associated with @var{xorig} are also associated +with the new pair. +@end deffn + + +@node Programmatic Error Handling +@subsection Programmatic Error Handling + +For better or for worse, all programs have bugs, and dealing with bugs +is part of programming. This section deals with that class of bugs that +causes an exception to be raised -- from your own code, from within a +library, or from Guile itself. + +@menu +* Catching Exceptions:: Handling errors after the stack is unwound. +* Capturing Stacks:: Capturing the stack at the time of error. +* Pre-Unwind Debugging:: Debugging before the exception is thrown. +* Stack Overflow:: Detecting and handling runaway recursion. +* Debug Options:: A historical interface to debugging. +@end menu + +@node Catching Exceptions +@subsubsection Catching Exceptions + +A common requirement is to be able to show as much useful context as +possible when a Scheme program hits an error. The most immediate +information about an error is the kind of error that it is -- such as +``division by zero'' -- and any parameters that the code which signalled +the error chose explicitly to provide. This information originates with +the @code{error} or @code{throw} call (or their C code equivalents, if +the error is detected by C code) that signals the error, and is passed +automatically to the handler procedure of the innermost applicable +@code{catch} or @code{with-throw-handler} expression. + +Therefore, to catch errors that occur within a chunk of Scheme code, and +to intercept basic information about those errors, you need to execute +that code inside the dynamic context of a @code{catch} or +@code{with-throw-handler} expression, or the equivalent in C. In Scheme, +this means you need something like this: + +@lisp +(catch #t + (lambda () + ;; Execute the code in which + ;; you want to catch errors here. + ...) + (lambda (key . parameters) + ;; Put the code which you want + ;; to handle an error here. + ...)) +@end lisp + +@noindent +The @code{catch} here can also be @code{with-throw-handler}; see +@ref{Throw Handlers} for information on the when you might want to use +@code{with-throw-handler} instead of @code{catch}. + +For example, to print out a message and return #f when an error occurs, +you might use: + +@smalllisp +(define (catch-all thunk) + (catch #t + thunk + (lambda (key . parameters) + (format (current-error-port) + "Uncaught throw to '~a: ~a\n" key parameters) + #f))) + +(catch-all + (lambda () (error "Not a vegetable: tomato"))) +@print{} Uncaught throw to 'misc-error: (#f ~A (Not a vegetable: tomato) #f) +@result{} #f +@end smalllisp + +The @code{#t} means that the catch is applicable to all kinds of error. +If you want to restrict your catch to just one kind of error, you can +put the symbol for that kind of error instead of @code{#t}. The +equivalent to this in C would be something like this: + +@lisp +SCM my_body_proc (void *body_data) +@{ + /* Execute the code in which + you want to catch errors here. */ + ... +@} + +SCM my_handler_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Put the code which you want + to handle an error here. */ + ... +@} + +@{ + ... + scm_c_catch (SCM_BOOL_T, + my_body_proc, body_data, + my_handler_proc, handler_data, + NULL, NULL); + ... +@} +@end lisp + +@noindent +Again, as with the Scheme version, @code{scm_c_catch} could be replaced +by @code{scm_c_with_throw_handler}, and @code{SCM_BOOL_T} could instead +be the symbol for a particular kind of error. + +@node Capturing Stacks +@subsubsection Capturing the full error stack + +The other interesting information about an error is the full Scheme +stack at the point where the error occurred; in other words what +innermost expression was being evaluated, what was the expression that +called that one, and so on. If you want to write your code so that it +captures and can display this information as well, there are a couple +important things to understand. + +Firstly, the stack at the point of the error needs to be explicitly +captured by a @code{make-stack} call (or the C equivalent +@code{scm_make_stack}). The Guile library does not do this +``automatically'' for you, so you will need to write code with a +@code{make-stack} or @code{scm_make_stack} call yourself. (We emphasise +this point because some people are misled by the fact that the Guile +interactive REPL code @emph{does} capture and display the stack +automatically. But the Guile interactive REPL is itself a Scheme +program@footnote{In effect, it is the default program which is run when +no commands or script file are specified on the Guile command line.} +running on top of the Guile library, and which uses @code{catch} and +@code{make-stack} in the way we are about to describe to capture the +stack when an error occurs.) + +And secondly, in order to capture the stack effectively at the point +where the error occurred, the @code{make-stack} call must be made before +Guile unwinds the stack back to the location of the prevailing catch +expression. This means that the @code{make-stack} call must be made +within the handler of a @code{with-throw-handler} expression, or the +optional "pre-unwind" handler of a @code{catch}. (For the full story of +how these alternatives differ from each other, see @ref{Exceptions}. The +main difference is that @code{catch} terminates the error, whereas +@code{with-throw-handler} only intercepts it temporarily and then allow +it to continue propagating up to the next innermost handler.) + +So, here are some examples of how to do all this in Scheme and in C. +For the purpose of these examples we assume that the captured stack +should be stored in a variable, so that it can be displayed or +arbitrarily processed later on. In Scheme: + +@lisp +(let ((captured-stack #f)) + (catch #t + (lambda () + ;; Execute the code in which + ;; you want to catch errors here. + ...) + (lambda (key . parameters) + ;; Put the code which you want + ;; to handle an error after the + ;; stack has been unwound here. + ...) + (lambda (key . parameters) + ;; Capture the stack here: + (set! captured-stack (make-stack #t)))) + ... + (if captured-stack + (begin + ;; Display or process the captured stack. + ...)) + ...) +@end lisp + +@noindent +And in C: + +@lisp +SCM my_body_proc (void *body_data) +@{ + /* Execute the code in which + you want to catch errors here. */ + ... +@} + +SCM my_handler_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Put the code which you want + to handle an error after the + stack has been unwound here. */ + ... +@} + +SCM my_preunwind_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Capture the stack here: */ + *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL); +@} + +@{ + SCM captured_stack = SCM_BOOL_F; + ... + scm_c_catch (SCM_BOOL_T, + my_body_proc, body_data, + my_handler_proc, handler_data, + my_preunwind_proc, &captured_stack); + ... + if (captured_stack != SCM_BOOL_F) + @{ + /* Display or process the captured stack. */ + ... + @} + ... +@} +@end lisp + +Once you have a captured stack, you can interrogate and display its +details in any way that you want, using the @code{stack-@dots{}} and +@code{frame-@dots{}} API described in @ref{Stacks} and +@ref{Frames}. + +If you want to print out a backtrace in the same format that the Guile +REPL does, you can use the @code{display-backtrace} procedure to do so. +You can also use @code{display-application} to display an individual +frame in the Guile REPL format. + +@node Pre-Unwind Debugging +@subsubsection Pre-Unwind Debugging + +Instead of saving a stack away and waiting for the @code{catch} to +return, you can handle errors directly, from within the pre-unwind +handler. + +For example, to show a backtrace when an error is thrown, you might want +to use a procedure like this: + +@lisp +(define (with-backtrace thunk) + (with-throw-handler #t + thunk + (lambda args (backtrace)))) +(with-backtrace (lambda () (error "Not a vegetable: tomato"))) +@end lisp + +Since we used @code{with-throw-handler} here, we didn't actually catch +the error. @xref{Throw Handlers}, for more information. However, we did +print out a context at the time of the error, using the built-in +procedure, @code{backtrace}. + +@deffn {Scheme Procedure} backtrace [highlights] +@deffnx {C Function} scm_backtrace_with_highlights (highlights) +@deffnx {C Function} scm_backtrace () +Display a backtrace of the current stack to the current output port. If +@var{highlights} is given it should be a list; the elements of this list +will be highlighted wherever they appear in the backtrace. +@end deffn + +The Guile REPL code (in @file{system/repl/repl.scm} and related files) +uses a @code{catch} with a pre-unwind handler to capture the stack when +an error occurs in an expression that was typed into the REPL, and debug +that stack interactively in the context of the error. + +These procedures are available for use by user programs, in the +@code{(system repl error-handling)} module. + +@lisp +(use-modules (system repl error-handling)) +@end lisp + +@deffn {Scheme Procedure} call-with-error-handling thunk @ + [#:on-error on-error='debug] [#:post-error post-error='catch] @ + [#:pass-keys pass-keys='(quit)] @ + [#:report-keys report-keys='(stack-overflow)] @ + [#:trap-handler trap-handler='debug] +Call a thunk in a context in which errors are handled. + +There are five keyword arguments: + +@table @var +@item on-error +Specifies what to do before the stack is unwound. + +Valid options are @code{debug} (the default), which will enter a +debugger; @code{pass}, in which case nothing is done, and the exception +is rethrown; or a procedure, which will be the pre-unwind handler. + +@item post-error +Specifies what to do after the stack is unwound. + +Valid options are @code{catch} (the default), which will silently catch +errors, returning the unspecified value; @code{report}, which prints out +a description of the error (via @code{display-error}), and then returns +the unspecified value; or a procedure, which will be the catch handler. + +@item trap-handler +Specifies a trap handler: what to do when a breakpoint is hit. + +Valid options are @code{debug}, which will enter the debugger; +@code{pass}, which does nothing; or @code{disabled}, which disables +traps entirely. @xref{Traps}, for more information. + +@item pass-keys +A set of keys to ignore, as a list. + +@item report-keys +A set of keys to always report even if the post-error handler is +@code{catch}, as a list. +@end table +@end deffn + +@node Stack Overflow +@subsubsection Stack Overflow + +@cindex overflow, stack +@cindex stack overflow +Every time a Scheme program makes a call that is not in tail position, +it pushes a new frame onto the stack. Returning a value from a function +pops the top frame off the stack. Stack frames take up memory, and as +nobody has an infinite amount of memory, deep recursion could cause +Guile to run out of memory. Running out of stack memory is called +@dfn{stack overflow}. + +@subsubheading Stack Limits + +Most languages have a terrible stack overflow story. For example, in C, +if you use too much stack, your program will exhibit ``undefined +behavior'', which if you are lucky means that it will crash. It's +especially bad in C, as you neither know ahead of time how much stack +your functions use, nor the stack limit imposed by the user's system, +and the stack limit is often quite small relative to the total memory +size. + +Managed languages like Python have a better error story, as they are +defined to raise an exception on stack overflow -- but like C, Python +and most dynamic languages still have a fixed stack size limit that is +usually much smaller than the heap. + +Arbitrary stack limits would have an unfortunate effect on Guile +programs. For example, the following implementation of the inner loop +of @code{map} is clean and elegant: + +@example +(define (map f l) + (if (pair? l) + (cons (f (car l)) + (map f (cdr l))) + '())) +@end example + +However, if there were a stack limit, that would limit the size of lists +that can be processed with this @code{map}. Eventually, you would have +to rewrite it to use iteration with an accumulator: + +@example +(define (map f l) + (let lp ((l l) (out '())) + (if (pair? l) + (lp (cdr l) (cons (f (car l)) out)) + (reverse out)))) +@end example + +This second version is sadly not as clear, and it also allocates more +heap memory (once to build the list in reverse, and then again to +reverse the list). You would be tempted to use the destructive +@code{reverse!} to save memory and time, but then your code would not be +continuation-safe -- if @var{f} returned again after the map had +finished, it would see an @var{out} list that had already been +reversed. The recursive @code{map} has none of these problems. + +Guile has no stack limit for Scheme code. When a thread makes its first +Guile call, a small stack is allocated -- just one page of memory. +Whenever that memory limit would be reached, Guile arranges to grow the +stack by a factor of two. When garbage collection happens, Guile +arranges to return the unused part of the stack to the operating system, +but without causing the stack to shrink. In this way, the stack can +grow to consume up to all memory available to the Guile process, and +when the recursive computation eventually finishes, that stack memory is +returned to the system. + +@subsubheading Exceptional Situations + +Of course, it's still possible to run out of stack memory. The most +common cause of this is program bugs that cause unbounded recursion, as +in: + +@example +(define (faulty-map f l) + (if (pair? l) + (cons (f (car l)) (faulty-map f l)) + '())) +@end example + +Did you spot the bug? The recursive call to @code{faulty-map} recursed +on @var{l}, not @code{(cdr @var{l})}. Running this program would cause +Guile to use up all memory in your system, and eventually Guile would +fail to grow the stack. At that point you have a problem: Guile needs +to raise an exception to unwind the stack and return memory to the +system, but the user might have throw handlers in place (@pxref{Throw +Handlers}) that want to run before the stack is unwound, and we don't +have any stack in which to run them. + +Therefore in this case, Guile throws an unwind-only exception that does +not run pre-unwind handlers. Because this is such an odd case, Guile +prints out a message on the console, in case the user was expecting to +be able to get a backtrace from any pre-unwind handler. + +@subsubheading Runaway Recursion + +Still, this failure mode is not so nice. If you are running an +environment in which you are interactively building a program while it +is running, such as at a REPL, you might want to impose an artificial +stack limit on the part of your program that you are building to detect +accidental runaway recursion. For that purpose, there is +@code{call-with-stack-overflow-handler}, from @code{(system vm vm)}. + +@example +(use-module (system vm vm)) +@end example + +@deffn {Scheme Procedure} call-with-stack-overflow-handler limit thunk handler +Call @var{thunk} in an environment in which the stack limit has been +reduced to @var{limit} additional words. If the limit is reached, +@var{handler} (a thunk) will be invoked in the dynamic environment of +the error. For the extent of the call to @var{handler}, the stack limit +and handler are restored to the values that were in place when +@code{call-with-stack-overflow-handler} was called. + +Usually, @var{handler} should raise an exception or abort to an outer +prompt. However if @var{handler} does return, it should return a number +of additional words of stack space to allow to the inner environment. +@end deffn + +A stack overflow handler may only ever ``credit'' the inner thunk with +stack space that was available when the handler was instated. When +Guile first starts, there is no stack limit in place, so the outer +handler may allow the inner thunk an arbitrary amount of space, but any +nested stack overflow handler will not be able to consume more than its +limit. + +Unlike the unwind-only exception that is thrown if Guile is unable to +grow its stack, any exception thrown by a stack overflow handler might +invoke pre-unwind handlers. Indeed, the stack overflow handler is +itself a pre-unwind handler of sorts. If the code imposing the stack +limit wants to protect itself against malicious pre-unwind handlers from +the inner thunk, it should abort to a prompt of its own making instead +of throwing an exception that might be caught by the inner thunk. + +@subsubheading C Stack Usage + +It is also possible for Guile to run out of space on the C stack. If +you call a primitive procedure which then calls a Scheme procedure in a +loop, you will consume C stack space. Guile tries to detect excessive +consumption of C stack space, throwing an error when you have hit 80% of +the process' available stack (as allocated by the operating system), or +160 kilowords in the absence of a strict limit. + +For example, looping through @code{call-with-vm}, a primitive that calls +a thunk, gives us the following: + +@lisp +scheme@@(guile-user)> (use-modules (system vm vm)) +scheme@@(guile-user)> (let lp () (call-with-vm lp)) +ERROR: Stack overflow +@end lisp + +Unfortunately, that's all the information we get. Overrunning the C +stack will throw an unwind-only exception, because it's not safe to +do very much when you are close to the C stack limit. + +If you get an error like this, you can either try rewriting your code to +use less stack space, or increase the maximum stack size. To increase +the maximum stack size, use @code{debug-set!}, for example: + +@lisp +(debug-set! stack 200000) +@end lisp + +The next section describes @code{debug-set!} more thoroughly. Of course +the best thing is to have your code operate without so much resource +consumption by avoiding loops through C trampolines. + + +@node Debug Options +@subsubsection Debug options + +The behavior of the @code{backtrace} procedure and of the default error +handler can be parameterized via the debug options. + +@cindex options - debug +@cindex debug options +@deffn {Scheme Procedure} debug-options [setting] +Display the current settings of the debug options. If @var{setting} is +omitted, only a short form of the current read options is printed. +Otherwise if @var{setting} is the symbol @code{help}, a complete options +description is displayed. +@end deffn + +The set of available options, and their default values, may be had by +invoking @code{debug-options} at the prompt. + +@smallexample +scheme@@(guile-user)> +backwards no Display backtrace in anti-chronological order. +width 79 Maximal width of backtrace. +depth 20 Maximal length of printed backtrace. +backtrace yes Show backtrace on error. +stack 1048576 Stack size limit (measured in words; + 0 = no check). +show-file-name #t Show file names and line numbers in backtraces + when not `#f'. A value of `base' displays only + base names, while `#t' displays full names. +warn-deprecated no Warn when deprecated features are used. +@end smallexample + +The boolean options may be toggled with @code{debug-enable} and +@code{debug-disable}. The non-boolean options must be set using +@code{debug-set!}. + +@deffn {Scheme Procedure} debug-enable option-name +@deffnx {Scheme Procedure} debug-disable option-name +@deffnx {Scheme Syntax} debug-set! option-name value +Modify the debug options. @code{debug-enable} should be used with boolean +options and switches them on, @code{debug-disable} switches them off. + +@code{debug-set!} can be used to set an option to a specific value. Due +to historical oddities, it is a macro that expects an unquoted option +name. +@end deffn + + +@node Traps +@subsection Traps + +@cindex Traps +@cindex VM hooks +@cindex Breakpoints +@cindex Trace +@cindex Tracing +@cindex Code coverage +@cindex Profiling +Guile's virtual machine can be configured to call out at key points to +arbitrary user-specified procedures. + +In principle, these @dfn{hooks} allow Scheme code to implement any model +it chooses for examining the evaluation stack as program execution +proceeds, and for suspending execution to be resumed later. + +VM hooks are very low-level, though, and so Guile also has a library of +higher-level @dfn{traps} on top of the VM hooks. A trap is an execution +condition that, when fulfilled, will fire a handler. For example, Guile +defines a trap that fires when control reaches a certain source +location. + +Finally, Guile also defines a third level of abstractions: per-thread +@dfn{trap states}. A trap state exists to give names to traps, and to +hold on to the set of traps so that they can be enabled, disabled, or +removed. The trap state infrastructure defines the most useful +abstractions for most cases. For example, Guile's REPL uses trap state +functions to set breakpoints and tracepoints. + +The following subsections describe all this in detail, for both the +user wanting to use traps, and the developer interested in +understanding how the interface hangs together. + + +@menu +* VM Hooks:: Modifying Guile's virtual machine. +* Trap Interface:: Traps are on or off. +* Low-Level Traps:: The various kinds of low-level traps. +* Tracing Traps:: Traps to trace procedure calls and returns. +* Trap States:: One state (per thread) to bind them. +* High-Level Traps:: The highest-level trap interface. Use this. +@end menu + + +@node VM Hooks +@subsubsection VM Hooks + +Everything that runs in Guile runs on its virtual machine, a C program +that defines a number of operations that Scheme programs can +perform. + +Note that there are multiple VM ``engines'' for Guile. Only some of them +have support for hooks compiled in. Normally the deal is that you get +hooks if you are running interactively, and otherwise they are disabled, +as they do have some overhead (about 10 or 20 percent). + +To ensure that you are running with hooks, pass @code{--debug} to Guile +when running your program, or otherwise use the @code{call-with-vm} and +@code{set-vm-engine!} procedures to ensure that you are running in a VM +with the @code{debug} engine. + +To digress, Guile's VM has 4 different hooks that can be fired at +different times. For implementation reasons, these hooks are not +actually implemented with first-class Scheme hooks (@pxref{Hooks}); they +are managed using an ad-hoc interface. + +VM hooks are called with one argument: the current frame. +@xref{Frames}. Since these hooks may be fired very frequently, Guile +does a terrible thing: it allocates the frames on the C stack instead of +the garbage-collected heap. + +The upshot here is that the frames are only valid within the dynamic +extent of the call to the hook. If a hook procedure keeps a reference to +the frame outside the extent of the hook, bad things will happen. + +The interface to hooks is provided by the @code{(system vm vm)} module: + +@example +(use-modules (system vm vm)) +@end example + +@noindent +All of these functions implicitly act on the VM for the current thread +only. + +@deffn {Scheme Procedure} vm-add-next-hook! f +Arrange to call @var{f} when before an instruction is retired (and +executed). +@end deffn + +@deffn {Scheme Procedure} vm-add-apply-hook! f +Arrange to call @var{f} whenever a procedure is applied. The frame +locals will be the callee, followed by the arguments to the call. + +Note that procedure application is somewhat orthogonal to continuation +pushes and pops. To know whether a call is a tail call or not, with +respect to the frame previously in place, check the value of the frame +pointer compared the previous frame pointer. +@end deffn + +@deffn {Scheme Procedure} vm-add-return-hook! f +Arrange to call @var{f} before returning from a frame. The values in +the frame will be the frame's return values. + +Note that it's possible to return from an ``inner'' frame: one that was +not immediately proceeded by a call with that frame pointer. In that +case, it corresponds to a non-local control flow jump, either because of +applying a composable continuation or because of restoring a saved +undelimited continuation. +@end deffn + +@deffn {Scheme Procedure} vm-add-abort-hook! +Arrange to call @var{f} after aborting to a prompt. @xref{Prompts}. + +Unfortunately, the values passed to the prompt handler are not easily +available to @var{f}. +@end deffn + +@deffn {Scheme Procedure} vm-remove-next-hook! f +@deffnx {Scheme Procedure} vm-remove-apply-hook! f +@deffnx {Scheme Procedure} vm-remove-return-hook! f +@deffnx {Scheme Procedure} vm-remove-abort-hook! f +Remove @var{f} from the corresponding VM hook for the current thread. +@end deffn + +@cindex VM trace level +These hooks do impose a performance penalty, if they are on. Obviously, +the @code{vm-next-hook} has quite an impact, performance-wise. Therefore +Guile exposes a single, heavy-handed knob to turn hooks on or off, the +@dfn{VM trace level}. If the trace level is positive, hooks run; +otherwise they don't. + +For convenience, when the VM fires a hook, it does so with the trap +level temporarily set to 0. That way the hooks don't fire while you're +handling a hook. The trace level is restored to whatever it was once the hook +procedure finishes. + +@deffn {Scheme Procedure} vm-trace-level +Retrieve the ``trace level'' of the VM. If positive, the trace hooks +associated with @var{vm} will be run. The initial trace level is 0. +@end deffn + +@deffn {Scheme Procedure} set-vm-trace-level! level +Set the ``trace level'' of the VM. +@end deffn + +@xref{A Virtual Machine for Guile}, for more information on Guile's +virtual machine. + +@node Trap Interface +@subsubsection Trap Interface + +The capabilities provided by hooks are great, but hooks alone rarely +correspond to what users want to do. + +For example, if a user wants to break when and if control reaches a +certain source location, how do you do it? If you install a ``next'' +hook, you get unacceptable overhead for the execution of the entire +program. It would be possible to install an ``apply'' hook, then if the +procedure encompasses those source locations, install a ``next'' hook, +but already you're talking about one concept that might be implemented +by a varying number of lower-level concepts. + +It's best to be clear about things and define one abstraction for all +such conditions: the @dfn{trap}. + +Considering the myriad capabilities offered by the hooks though, there +is only a minimum of functionality shared by all traps. Guile's current +take is to reduce this to the absolute minimum, and have the only +standard interface of a trap be ``turn yourself on'' or ``turn yourself +off''. + +This interface sounds a bit strange, but it is useful to procedurally +compose higher-level traps from lower-level building blocks. For +example, Guile defines a trap that calls one handler when control enters +a procedure, and another when control leaves the procedure. Given that +trap, one can define a trap that adds to the next-hook only when within +a given procedure. Building further, one can define a trap that fires +when control reaches particular instructions within a procedure. + +Or of course you can stop at any of these intermediate levels. For +example, one might only be interested in calls to a given procedure. But +the point is that a simple enable/disable interface is all the +commonality that exists between the various kinds of traps, and +furthermore that such an interface serves to allow ``higher-level'' +traps to be composed from more primitive ones. + +Specifically, a trap, in Guile, is a procedure. When a trap is created, +by convention the trap is enabled; therefore, the procedure that is the +trap will, when called, disable the trap, and return a procedure that +will enable the trap, and so on. + +Trap procedures take one optional argument: the current frame. (A trap +may want to add to different sets of hooks depending on the frame that +is current at enable-time.) + +If this all sounds very complicated, it's because it is. Some of it is +essential, but probably most of it is not. The advantage of using this +minimal interface is that composability is more lexically apparent than +when, for example, using a stateful interface based on GOOPS. But +perhaps this reflects the cognitive limitations of the programmer who +made the current interface more than anything else. + +@node Low-Level Traps +@subsubsection Low-Level Traps + +To summarize the last sections, traps are enabled or disabled, and when +they are enabled, they add to various VM hooks. + +Note, however, that @emph{traps do not increase the VM trace level}. So +if you create a trap, it will be enabled, but unless something else +increases the VM's trace level (@pxref{VM Hooks}), the trap will not +fire. It turns out that getting the VM trace level right is tricky +without a global view of what traps are enabled. @xref{Trap States}, +for Guile's answer to this problem. + +Traps are created by calling procedures. Most of these procedures share +a set of common keyword arguments, so rather than document them +separately, we discuss them all together here: + +@table @code +@item #:vm +The VM to instrument. Defaults to the current thread's VM. +@item #:current-frame +For traps that enable more hooks depending on their dynamic context, +this argument gives the current frame that the trap is running in. +Defaults to @code{#f}. +@end table + +To have access to these procedures, you'll need to have imported the +@code{(system vm traps)} module: + +@lisp +(use-modules (system vm traps)) +@end lisp + +@deffn {Scheme Procedure} trap-at-procedure-call proc handler @ + [#:vm] +A trap that calls @var{handler} when @var{proc} is applied. +@end deffn + +@deffn {Scheme Procedure} trap-in-procedure proc @ + enter-handler exit-handler [#:current-frame] [#:vm] +A trap that calls @var{enter-handler} when control enters @var{proc}, +and @var{exit-handler} when control leaves @var{proc}. + +Control can enter a procedure via: +@itemize +@item +A procedure call. +@item +A return to a procedure's frame on the stack. +@item +A continuation returning directly to an application of this procedure. +@end itemize + +Control can leave a procedure via: +@itemize +@item +A normal return from the procedure. +@item +An application of another procedure. +@item +An invocation of a continuation. +@item +An abort. +@end itemize +@end deffn + +@deffn {Scheme Procedure} trap-instructions-in-procedure proc @ + next-handler exit-handler [#:current-frame] [#:vm] +A trap that calls @var{next-handler} for every instruction executed in +@var{proc}, and @var{exit-handler} when execution leaves @var{proc}. +@end deffn + +@deffn {Scheme Procedure} trap-at-procedure-ip-in-range proc range @ + handler [#:current-frame] [#:vm] +A trap that calls @var{handler} when execution enters a range of +instructions in @var{proc}. @var{range} is a simple of pairs, +@code{((@var{start} . @var{end}) ...)}. The @var{start} addresses are +inclusive, and @var{end} addresses are exclusive. +@end deffn + +@deffn {Scheme Procedure} trap-at-source-location file user-line handler @ + [#:current-frame] [#:vm] +A trap that fires when control reaches a given source location. The +@var{user-line} parameter is one-indexed, as a user counts lines, +instead of zero-indexed, as Guile counts lines. +@end deffn + +@deffn {Scheme Procedure} trap-frame-finish frame @ + return-handler abort-handler [#:vm] +A trap that fires when control leaves the given frame. @var{frame} +should be a live frame in the current continuation. @var{return-handler} +will be called on a normal return, and @var{abort-handler} on a nonlocal +exit. +@end deffn + +@deffn {Scheme Procedure} trap-in-dynamic-extent proc @ + enter-handler return-handler abort-handler [#:vm] +A more traditional dynamic-wind trap, which fires @var{enter-handler} +when control enters @var{proc}, @var{return-handler} on a normal return, +and @var{abort-handler} on a nonlocal exit. + +Note that rewinds are not handled, so there is no rewind handler. +@end deffn + +@deffn {Scheme Procedure} trap-calls-in-dynamic-extent proc @ + apply-handler return-handler [#:current-frame] [#:vm] +A trap that calls @var{apply-handler} every time a procedure is applied, +and @var{return-handler} for returns, but only during the dynamic extent +of an application of @var{proc}. +@end deffn + +@deffn {Scheme Procedure} trap-instructions-in-dynamic-extent proc @ + next-handler [#:current-frame] [#:vm] +A trap that calls @var{next-handler} for all retired instructions within +the dynamic extent of a call to @var{proc}. +@end deffn + +@deffn {Scheme Procedure} trap-calls-to-procedure proc @ + apply-handler return-handler [#:vm] +A trap that calls @var{apply-handler} whenever @var{proc} is applied, +and @var{return-handler} when it returns, but with an additional +argument, the call depth. + +That is to say, the handlers will get two arguments: the frame in +question, and the call depth (a non-negative integer). +@end deffn + +@deffn {Scheme Procedure} trap-matching-instructions frame-pred handler [#:vm] +A trap that calls @var{frame-pred} at every instruction, and if +@var{frame-pred} returns a true value, calls @var{handler} on the +frame. +@end deffn + +@node Tracing Traps +@subsubsection Tracing Traps + +The @code{(system vm trace)} module defines a number of traps for +tracing of procedure applications. When a procedure is @dfn{traced}, it +means that every call to that procedure is reported to the user during a +program run. The idea is that you can mark a collection of procedures +for tracing, and Guile will subsequently print out a line of the form + +@lisp +| | (@var{procedure} @var{args} @dots{}) +@end lisp + +whenever a marked procedure is about to be applied to its arguments. +This can help a programmer determine whether a function is being called +at the wrong time or with the wrong set of arguments. + +In addition, the indentation of the output is useful for demonstrating +how the traced applications are or are not tail recursive with respect +to each other. Thus, a trace of a non-tail recursive factorial +implementation looks like this: + +@lisp +scheme@@(guile-user)> (define (fact1 n) + (if (zero? n) 1 + (* n (fact1 (1- n))))) +scheme@@(guile-user)> ,trace (fact1 4) +trace: (fact1 4) +trace: | (fact1 3) +trace: | | (fact1 2) +trace: | | | (fact1 1) +trace: | | | | (fact1 0) +trace: | | | | 1 +trace: | | | 1 +trace: | | 2 +trace: | 6 +trace: 24 +@end lisp + +While a typical tail recursive implementation would look more like this: + +@lisp +scheme@@(guile-user)> (define (facti acc n) + (if (zero? n) acc + (facti (* n acc) (1- n)))) +scheme@@(guile-user)> (define (fact2 n) (facti 1 n)) +scheme@@(guile-user)> ,trace (fact2 4) +trace: (fact2 4) +trace: (facti 1 4) +trace: (facti 4 3) +trace: (facti 12 2) +trace: (facti 24 1) +trace: (facti 24 0) +trace: 24 +@end lisp + +The low-level traps below (@pxref{Low-Level Traps}) share some common +options: + +@table @code +@item #:width +The maximum width of trace output. Trace printouts will try not to +exceed this column, but for highly nested procedure calls, it may be +unavoidable. Defaults to 80. +@item #:vm +The VM on which to add the traps. Defaults to the current thread's VM. +@item #:prefix +A string to print out before each trace line. As seen above in the +examples, defaults to @code{"trace: "}. +@end table + +To have access to these procedures, you'll need to have imported the +@code{(system vm trace)} module: + +@lisp +(use-modules (system vm trace)) +@end lisp + +@deffn {Scheme Procedure} trace-calls-to-procedure proc @ + [#:width] [#:vm] [#:prefix] +Print a trace at applications of and returns from @var{proc}. +@end deffn + +@deffn {Scheme Procedure} trace-calls-in-procedure proc @ + [#:width] [#:vm] [#:prefix] +Print a trace at all applications and returns within the dynamic extent +of calls to @var{proc}. +@end deffn + +@deffn {Scheme Procedure} trace-instructions-in-procedure proc [#:width] [#:vm] +Print a trace at all instructions executed in the dynamic extent of +calls to @var{proc}. +@end deffn + +In addition, Guile defines a procedure to call a thunk, tracing all +procedure calls and returns within the thunk. + +@deffn {Scheme Procedure} call-with-trace thunk [#:calls?=#t] @ + [#:instructions?=#f] @ + [#:width=80] +Call @var{thunk}, tracing all execution within its dynamic extent. + +If @var{calls?} is true, Guile will print a brief report at each +procedure call and return, as given above. + +If @var{instructions?} is true, Guile will also print a message each +time an instruction is executed. This is a lot of output, but it is +sometimes useful when doing low-level optimization. + +Note that because this procedure manipulates the VM trace level +directly, it doesn't compose well with traps at the REPL. +@end deffn + +@xref{Profile Commands}, for more information on tracing at the REPL. + +@node Trap States +@subsubsection Trap States + +When multiple traps are present in a system, we begin to have a +bookkeeping problem. How are they named? How does one disable, enable, +or delete them? + +Guile's answer to this is to keep an implicit per-thread @dfn{trap +state}. The trap state object is not exposed to the user; rather, API +that works on trap states fetches the current trap state from the +dynamic environment. + +Traps are identified by integers. A trap can be enabled, disabled, or +removed, and can have an associated user-visible name. + +These procedures have their own module: + +@lisp +(use-modules (system vm trap-state)) +@end lisp + +@deffn {Scheme Procedure} add-trap! trap name +Add a trap to the current trap state, associating the given @var{name} +with it. Returns a fresh trap identifier (an integer). + +Note that usually the more specific functions detailed in +@ref{High-Level Traps} are used in preference to this one. +@end deffn + +@deffn {Scheme Procedure} list-traps +List the current set of traps, both enabled and disabled. Returns a list +of integers. +@end deffn + +@deffn {Scheme Procedure} trap-name idx +Returns the name associated with trap @var{idx}, or @code{#f} if there +is no such trap. +@end deffn + +@deffn {Scheme Procedure} trap-enabled? idx +Returns @code{#t} if trap @var{idx} is present and enabled, or @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} enable-trap! idx +Enables trap @var{idx}. +@end deffn + +@deffn {Scheme Procedure} disable-trap! idx +Disables trap @var{idx}. +@end deffn + +@deffn {Scheme Procedure} delete-trap! idx +Removes trap @var{idx}, disabling it first, if necessary. +@end deffn + +@node High-Level Traps +@subsubsection High-Level Traps + +The low-level trap API allows one to make traps that call procedures, +and the trap state API allows one to keep track of what traps are +there. But neither of these APIs directly helps you when you want to +set a breakpoint, because it's unclear what to do when the trap fires. +Do you enter a debugger, or mail a summary of the situation to your +great-aunt, or what? + +So for the common case in which you just want to install breakpoints, +and then have them all result in calls to one parameterizable procedure, +we have the high-level trap interface. + +Perhaps we should have started this section with this interface, as it's +clearly the one most people should use. But as its capabilities and +limitations proceed from the lower layers, we felt that the +character-building exercise of building a mental model might be helpful. + +These procedures share a module with trap states: + +@lisp +(use-modules (system vm trap-state)) +@end lisp + +@deffn {Scheme Procedure} with-default-trap-handler handler thunk +Call @var{thunk} in a dynamic context in which @var{handler} is the +current trap handler. + +Additionally, during the execution of @var{thunk}, the VM trace level +(@pxref{VM Hooks}) is set to the number of enabled traps. This ensures +that traps will in fact fire. + +@var{handler} may be @code{#f}, in which case VM hooks are not enabled +as they otherwise would be, as there is nothing to handle the traps. +@end deffn + +The trace-level-setting behavior of @code{with-default-trap-handler} is +one of its more useful aspects, but if you are willing to forgo that, +and just want to install a global trap handler, there's a function for +that too: + +@deffn {Scheme Procedure} install-trap-handler! handler +Set the current thread's trap handler to @var{handler}. +@end deffn + +Trap handlers are called when traps installed by procedures from this +module fire. The current ``consumer'' of this API is Guile's REPL, but +one might easily imagine other trap handlers being used to integrate +with other debugging tools. + +@cindex Breakpoints +@cindex Setting breakpoints +@deffn {Scheme Procedure} add-trap-at-procedure-call! proc +Install a trap that will fire when @var{proc} is called. + +This is a breakpoint. +@end deffn + +@cindex Tracepoints +@cindex Setting tracepoints +@deffn {Scheme Procedure} add-trace-at-procedure-call! proc +Install a trap that will print a tracing message when @var{proc} is +called. @xref{Tracing Traps}, for more information. + +This is a tracepoint. +@end deffn + +@deffn {Scheme Procedure} add-trap-at-source-location! file user-line +Install a trap that will fire when control reaches the given source +location. @var{user-line} is one-indexed, as users count lines, instead +of zero-indexed, as Guile counts lines. + +This is a source breakpoint. +@end deffn + +@deffn {Scheme Procedure} add-ephemeral-trap-at-frame-finish! frame handler +Install a trap that will call @var{handler} when @var{frame} finishes +executing. The trap will be removed from the trap state after firing, or +on nonlocal exit. + +This is a finish trap, used to implement the ``finish'' REPL command. +@end deffn + +@deffn {Scheme Procedure} add-ephemeral-stepping-trap! frame handler [#:into?] [#:instruction?] +Install a trap that will call @var{handler} after stepping to a +different source line or instruction. The trap will be removed from the +trap state after firing, or on nonlocal exit. + +If @var{instruction?} is false (the default), the trap will fire when +control reaches a new source line. Otherwise it will fire when control +reaches a new instruction. + +Additionally, if @var{into?} is false (not the default), the trap will +only fire for frames at or prior to the given frame. If @var{into?} is +true (the default), the trap may step into nested procedure +invocations. + +This is a stepping trap, used to implement the ``step'', ``next'', +``step-instruction'', and ``next-instruction'' REPL commands. +@end deffn + +@node GDB Support +@subsection GDB Support + +@cindex GDB support + +Sometimes, you may find it necessary to debug Guile applications at the +C level. Doing so can be tedious, in particular because the debugger is +oblivious to Guile's @code{SCM} type, and thus unable to display +@code{SCM} values in any meaningful way: + +@example +(gdb) frame +#0 scm_display (obj=0xf04310, port=0x6f9f30) at print.c:1437 +@end example + +To address that, Guile comes with an extension of the GNU Debugger (GDB) +that contains a ``pretty-printer'' for @code{SCM} values. With this GDB +extension, the C frame in the example above shows up like this: + +@example +(gdb) frame +#0 scm_display (obj=("hello" GDB!), port=#<port file 6f9f30>) at print.c:1437 +@end example + +@noindent +Here GDB was able to decode the list pointed to by @var{obj}, and to +print it using Scheme's read syntax. + +That extension is a @code{.scm} file installed alongside the +@file{libguile} shared library. When GDB 7.8 or later is installed and +compiled with support for extensions written in Guile, the extension is +automatically loaded when debugging a program linked against +@file{libguile} (@pxref{Auto-loading,,, gdb, Debugging with GDB}). Note +that the directory where @file{libguile} is installed must be among +GDB's auto-loading ``safe directories'' (@pxref{Auto-loading safe +path,,, gdb, Debugging with GDB}). + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-deprecated.texi b/doc/ref/api-deprecated.texi new file mode 100644 index 000000000..76f099727 --- /dev/null +++ b/doc/ref/api-deprecated.texi @@ -0,0 +1,29 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Deprecation +@section Deprecation + +From time to time functions and other features of Guile become obsolete. +Guile's @dfn{deprecation} is a mechanism that can help you cope with +this. + +When you use a feature that is deprecated, you will likely get a warning +message at run-time. Also, if you have a new enough toolchain, using a +deprecated function from @code{libguile} will cause a link-time warning. + +The primary source for information about just what interfaces are +deprecated in a given release is the file @file{NEWS}. That file also +documents what you should use instead of the obsoleted things. + +The file @file{README} contains instructions on how to control the +inclusion or removal of the deprecated features from the public API of +Guile, and how to control the deprecation warning messages. + +The idea behind this mechanism is that normally all deprecated +interfaces are available, but you get feedback when compiling and +running code that uses them, so that you can migrate to the newer APIs +at your leisure. diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi new file mode 100644 index 000000000..cfae07fcf --- /dev/null +++ b/doc/ref/api-evaluation.texi @@ -0,0 +1,1599 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +@c 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Read/Load/Eval/Compile +@section Reading and Evaluating Scheme Code + +This chapter describes Guile functions that are concerned with reading, +loading, evaluating, and compiling Scheme code at run time. + +@menu +* Scheme Syntax:: Standard and extended Scheme syntax. +* Scheme Read:: Reading Scheme code. +* Scheme Write:: Writing Scheme values to a port. +* Fly Evaluation:: Procedures for on the fly evaluation. +* Compilation:: How to compile Scheme files and procedures. +* Loading:: Loading Scheme code from file. +* Load Paths:: Where Guile looks for code. +* Character Encoding of Source Files:: Loading non-ASCII Scheme code from file. +* Delayed Evaluation:: Postponing evaluation until it is needed. +* Local Evaluation:: Evaluation in a local lexical environment. +* Local Inclusion:: Compile-time inclusion of one file in another. +* Sandboxed Evaluation:: Evaluation with limited capabilities. +* REPL Servers:: Serving a REPL over a socket. +* Cooperative REPL Servers:: REPL server for single-threaded applications. +@end menu + + +@node Scheme Syntax +@subsection Scheme Syntax: Standard and Guile Extensions + +@menu +* Expression Syntax:: +* Comments:: +* Block Comments:: +* Case Sensitivity:: +* Keyword Syntax:: +* Reader Extensions:: +@end menu + + +@node Expression Syntax +@subsubsection Expression Syntax + +An expression to be evaluated takes one of the following forms. + +@table @nicode + +@item @var{symbol} +A symbol is evaluated by dereferencing. A binding of that symbol is +sought and the value there used. For example, + +@example +(define x 123) +x @result{} 123 +@end example + +@item (@var{proc} @var{args}@dots{}) +A parenthesised expression is a function call. @var{proc} and each +argument are evaluated, then the function (which @var{proc} evaluated +to) is called with those arguments. + +The order in which @var{proc} and the arguments are evaluated is +unspecified, so be careful when using expressions with side effects. + +@example +(max 1 2 3) @result{} 3 + +(define (get-some-proc) min) +((get-some-proc) 1 2 3) @result{} 1 +@end example + +The same sort of parenthesised form is used for a macro invocation, +but in that case the arguments are not evaluated. See the +descriptions of macros for more on this (@pxref{Macros}, and +@pxref{Syntax Rules}). + +@item @var{constant} +Number, string, character and boolean constants evaluate ``to +themselves'', so can appear as literals. + +@example +123 @result{} 123 +99.9 @result{} 99.9 +"hello" @result{} "hello" +#\z @result{} #\z +#t @result{} #t +@end example + +Note that an application must not attempt to modify literal strings, +since they may be in read-only memory. + +@item (quote @var{data}) +@itemx '@var{data} +@findex quote +@findex ' +Quoting is used to obtain a literal symbol (instead of a variable +reference), a literal list (instead of a function call), or a literal +vector. @nicode{'} is simply a shorthand for a @code{quote} form. +For example, + +@example +'x @result{} x +'(1 2 3) @result{} (1 2 3) +'#(1 (2 3) 4) @result{} #(1 (2 3) 4) +(quote x) @result{} x +(quote (1 2 3)) @result{} (1 2 3) +(quote #(1 (2 3) 4)) @result{} #(1 (2 3) 4) +@end example + +Note that an application must not attempt to modify literal lists or +vectors obtained from a @code{quote} form, since they may be in +read-only memory. + +@item (quasiquote @var{data}) +@itemx `@var{data} +@findex quasiquote +@findex ` +Backquote quasi-quotation is like @code{quote}, but selected +sub-expressions are evaluated. This is a convenient way to construct +a list or vector structure most of which is constant, but at certain +points should have expressions substituted. + +The same effect can always be had with suitable @code{list}, +@code{cons} or @code{vector} calls, but quasi-quoting is often easier. + +@table @nicode + +@item (unquote @var{expr}) +@itemx ,@var{expr} +@findex unquote +@findex , +Within the quasiquote @var{data}, @code{unquote} or @code{,} indicates +an expression to be evaluated and inserted. The comma syntax @code{,} +is simply a shorthand for an @code{unquote} form. For example, + +@example +`(1 2 (* 9 9) 3 4) @result{} (1 2 (* 9 9) 3 4) +`(1 2 ,(* 9 9) 3 4) @result{} (1 2 81 3 4) +`(1 (unquote (+ 1 1)) 3) @result{} (1 2 3) +`#(1 ,(/ 12 2)) @result{} #(1 6) +@end example + +@item (unquote-splicing @var{expr}) +@itemx ,@@@var{expr} +@findex unquote-splicing +@findex ,@@ +Within the quasiquote @var{data}, @code{unquote-splicing} or +@code{,@@} indicates an expression to be evaluated and the elements of +the returned list inserted. @var{expr} must evaluate to a list. The +``comma-at'' syntax @code{,@@} is simply a shorthand for an +@code{unquote-splicing} form. + +@example +(define x '(2 3)) +`(1 ,x 4) @result{} (1 (2 3) 4) +`(1 ,@@x 4) @result{} (1 2 3 4) +`(1 (unquote-splicing (map 1+ x))) @result{} (1 3 4) +`#(9 ,@@x 9) @result{} #(9 2 3 9) +@end example + +Notice @code{,@@} differs from plain @code{,} in the way one level of +nesting is stripped. For @code{,@@} the elements of a returned list +are inserted, whereas with @code{,} it would be the list itself +inserted. +@end table + +@c +@c FIXME: What can we say about the mutability of a quasiquote +@c result? R5RS doesn't seem to specify anything, though where it +@c says backquote without commas is the same as plain quote then +@c presumably the "fixed" portions of a quasiquote expression must be +@c treated as immutable. +@c + +@end table + + +@node Comments +@subsubsection Comments + +@c FIXME::martin: Review me! + +Comments in Scheme source files are written by starting them with a +semicolon character (@code{;}). The comment then reaches up to the end +of the line. Comments can begin at any column, and the may be inserted +on the same line as Scheme code. + +@lisp +; Comment +;; Comment too +(define x 1) ; Comment after expression +(let ((y 1)) + ;; Display something. + (display y) +;;; Comment at left margin. + (display (+ y 1))) +@end lisp + +It is common to use a single semicolon for comments following +expressions on a line, to use two semicolons for comments which are +indented like code, and three semicolons for comments which start at +column 0, even if they are inside an indented code block. This +convention is used when indenting code in Emacs' Scheme mode. + + +@node Block Comments +@subsubsection Block Comments +@cindex multiline comments +@cindex block comments +@cindex #! +@cindex !# + +@c FIXME::martin: Review me! + +In addition to the standard line comments defined by R5RS, Guile has +another comment type for multiline comments, called @dfn{block +comments}. This type of comment begins with the character sequence +@code{#!} and ends with the characters @code{!#}. + +These comments are compatible with the block +comments in the Scheme Shell @file{scsh} (@pxref{The Scheme shell +(scsh)}). The characters @code{#!} were chosen because they are the +magic characters used in shell scripts for indicating that the name of +the program for executing the script follows on the same line. + +Thus a Guile script often starts like this. + +@lisp +#! /usr/local/bin/guile -s +!# +@end lisp + +More details on Guile scripting can be found in the scripting section +(@pxref{Guile Scripting}). + +@cindex R6RS block comments +@cindex SRFI-30 block comments +Similarly, Guile (starting from version 2.0) supports nested block +comments as specified by R6RS and +@url{http://srfi.schemers.org/srfi-30/srfi-30.html, SRFI-30}: + +@lisp +(+ 1 #| this is a #| nested |# block comment |# 2) +@result{} 3 +@end lisp + +For backward compatibility, this syntax can be overridden with +@code{read-hash-extend} (@pxref{Reader Extensions, +@code{read-hash-extend}}). + +There is one special case where the contents of a comment can actually +affect the interpretation of code. When a character encoding +declaration, such as @code{coding: utf-8} appears in one of the first +few lines of a source file, it indicates to Guile's default reader +that this source code file is not ASCII. For details see @ref{Character +Encoding of Source Files}. + +@node Case Sensitivity +@subsubsection Case Sensitivity +@cindex fold-case +@cindex no-fold-case + +@c FIXME::martin: Review me! + +Scheme as defined in R5RS is not case sensitive when reading symbols. +Guile, on the contrary is case sensitive by default, so the identifiers + +@lisp +guile-whuzzy +Guile-Whuzzy +@end lisp + +are the same in R5RS Scheme, but are different in Guile. + +It is possible to turn off case sensitivity in Guile by setting the +reader option @code{case-insensitive}. For more information on reader +options, @xref{Scheme Read}. + +@lisp +(read-enable 'case-insensitive) +@end lisp + +It is also possible to disable (or enable) case sensitivity within a +single file by placing the reader directives @code{#!fold-case} (or +@code{#!no-fold-case}) within the file itself. + +@node Keyword Syntax +@subsubsection Keyword Syntax + + +@node Reader Extensions +@subsubsection Reader Extensions + +@deffn {Scheme Procedure} read-hash-extend chr proc +@deffnx {C Function} scm_read_hash_extend (chr, proc) +Install the procedure @var{proc} for reading expressions +starting with the character sequence @code{#} and @var{chr}. +@var{proc} will be called with two arguments: the character +@var{chr} and the port to read further data from. The object +returned will be the return value of @code{read}. +Passing @code{#f} for @var{proc} will remove a previous setting. + +@end deffn + + +@node Scheme Read +@subsection Reading Scheme Code + +@rnindex read +@deffn {Scheme Procedure} read [port] +@deffnx {C Function} scm_read (port) +Read an s-expression from the input port @var{port}, or from +the current input port if @var{port} is not specified. +Any whitespace before the next token is discarded. +@end deffn + +The behaviour of Guile's Scheme reader can be modified by manipulating +its read options. + +@cindex options - read +@cindex read options +@deffn {Scheme Procedure} read-options [setting] +Display the current settings of the global read options. If +@var{setting} is omitted, only a short form of the current read options +is printed. Otherwise if @var{setting} is the symbol @code{help}, a +complete options description is displayed. +@end deffn + +The set of available options, and their default values, may be had by +invoking @code{read-options} at the prompt. + +@smalllisp +scheme@@(guile-user)> (read-options) +(square-brackets keywords #f positions) +scheme@@(guile-user)> (read-options 'help) +copy no Copy source code expressions. +positions yes Record positions of source code expressions. +case-insensitive no Convert symbols to lower case. +keywords #f Style of keyword recognition: #f, 'prefix or 'postfix. +r6rs-hex-escapes no Use R6RS variable-length character and string hex escapes. +square-brackets yes Treat `[' and `]' as parentheses, for R6RS compatibility. +hungry-eol-escapes no In strings, consume leading whitespace after an + escaped end-of-line. +curly-infix no Support SRFI-105 curly infix expressions. +r7rs-symbols no Support R7RS |...| symbol notation. +@end smalllisp + +Note that Guile also includes a preliminary mechanism for setting read +options on a per-port basis. For instance, the @code{case-insensitive} +read option is set (or unset) on the port when the reader encounters the +@code{#!fold-case} or @code{#!no-fold-case} reader directives. +Similarly, the @code{#!curly-infix} reader directive sets the +@code{curly-infix} read option on the port, and +@code{#!curly-infix-and-bracket-lists} sets @code{curly-infix} and +unsets @code{square-brackets} on the port (@pxref{SRFI-105}). There is +currently no other way to access or set the per-port read options. + +The boolean options may be toggled with @code{read-enable} and +@code{read-disable}. The non-boolean @code{keywords} option must be set +using @code{read-set!}. + +@deffn {Scheme Procedure} read-enable option-name +@deffnx {Scheme Procedure} read-disable option-name +@deffnx {Scheme Syntax} read-set! option-name value +Modify the read options. @code{read-enable} should be used with boolean +options and switches them on, @code{read-disable} switches them off. + +@code{read-set!} can be used to set an option to a specific value. Due +to historical oddities, it is a macro that expects an unquoted option +name. +@end deffn + +For example, to make @code{read} fold all symbols to their lower case +(perhaps for compatibility with older Scheme code), you can enter: + +@lisp +(read-enable 'case-insensitive) +@end lisp + +For more information on the effect of the @code{r6rs-hex-escapes} and +@code{hungry-eol-escapes} options, see (@pxref{String Syntax}). + +For more information on the @code{r7rs-symbols} option, see +(@pxref{Symbol Read Syntax}). + + +@node Scheme Write +@subsection Writing Scheme Values + +Any scheme value may be written to a port. Not all values may be read +back in (@pxref{Scheme Read}), however. + +@rnindex write +@rnindex print +@deffn {Scheme Procedure} write obj [port] +Send a representation of @var{obj} to @var{port} or to the current +output port if not given. + +The output is designed to be machine readable, and can be read back +with @code{read} (@pxref{Scheme Read}). Strings are printed in +double quotes, with escapes if necessary, and characters are printed in +@samp{#\} notation. +@end deffn + +@rnindex display +@deffn {Scheme Procedure} display obj [port] +Send a representation of @var{obj} to @var{port} or to the current +output port if not given. + +The output is designed for human readability, it differs from +@code{write} in that strings are printed without double quotes and +escapes, and characters are printed as per @code{write-char}, not in +@samp{#\} form. +@end deffn + +As was the case with the Scheme reader, there are a few options that +affect the behavior of the Scheme printer. + +@cindex options - print +@cindex print options +@deffn {Scheme Procedure} print-options [setting] +Display the current settings of the read options. If @var{setting} is +omitted, only a short form of the current read options is +printed. Otherwise if @var{setting} is the symbol @code{help}, a +complete options description is displayed. +@end deffn + +The set of available options, and their default values, may be had by +invoking @code{print-options} at the prompt. + +@smalllisp +scheme@@(guile-user)> (print-options) +(quote-keywordish-symbols reader highlight-suffix "@}" highlight-prefix "@{") +scheme@@(guile-user)> (print-options 'help) +highlight-prefix @{ The string to print before highlighted values. +highlight-suffix @} The string to print after highlighted values. +quote-keywordish-symbols reader How to print symbols that have a colon + as their first or last character. The + value '#f' does not quote the colons; + '#t' quotes them; 'reader' quotes them + when the reader option 'keywords' is + not '#f'. +escape-newlines yes Render newlines as \n when printing + using `write'. +r7rs-symbols no Escape symbols using R7RS |...| symbol + notation. +@end smalllisp + +These options may be modified with the print-set! syntax. + +@deffn {Scheme Syntax} print-set! option-name value +Modify the print options. Due to historical oddities, @code{print-set!} +is a macro that expects an unquoted option name. +@end deffn + + +@node Fly Evaluation +@subsection Procedures for On the Fly Evaluation + +Scheme has the lovely property that its expressions may be represented +as data. The @code{eval} procedure takes a Scheme datum and evaluates +it as code. + +@rnindex eval +@c ARGFIXME environment/environment specifier +@deffn {Scheme Procedure} eval exp module_or_state +@deffnx {C Function} scm_eval (exp, module_or_state) +Evaluate @var{exp}, a list representing a Scheme expression, +in the top-level environment specified by @var{module_or_state}. +While @var{exp} is evaluated (using @code{primitive-eval}), +@var{module_or_state} is made the current module. The current module +is reset to its previous value when @code{eval} returns. +XXX - dynamic states. +Example: (eval '(+ 1 2) (interaction-environment)) +@end deffn + +@rnindex interaction-environment +@deffn {Scheme Procedure} interaction-environment +@deffnx {C Function} scm_interaction_environment () +Return a specifier for the environment that contains +implementation--defined bindings, typically a superset of those +listed in the report. The intent is that this procedure will +return the environment in which the implementation would +evaluate expressions dynamically typed by the user. +@end deffn + +@xref{Environments}, for other environments. + +One does not always receive code as Scheme data, of course, and this is +especially the case for Guile's other language implementations +(@pxref{Other Languages}). For the case in which all you have is a +string, we have @code{eval-string}. There is a legacy version of this +procedure in the default environment, but you really want the one from +@code{(ice-9 eval-string)}, so load it up: + +@example +(use-modules (ice-9 eval-string)) +@end example + +@deffn {Scheme Procedure} eval-string string [#:module=#f] [#:file=#f] @ + [#:line=#f] [#:column=#f] @ + [#:lang=(current-language)] @ + [#:compile?=#f] +Parse @var{string} according to the current language, normally Scheme. +Evaluate or compile the expressions it contains, in order, returning the +last expression. + +If the @var{module} keyword argument is set, save a module excursion +(@pxref{Module System Reflection}) and set the current module to +@var{module} before evaluation. + +The @var{file}, @var{line}, and @var{column} keyword arguments can be +used to indicate that the source string begins at a particular source +location. + +Finally, @var{lang} is a language, defaulting to the current language, +and the expression is compiled if @var{compile?} is true or there is no +evaluator for the given language. +@end deffn + +@deffn {C Function} scm_eval_string (string) +@deffnx {C Function} scm_eval_string_in_module (string, module) +These C bindings call @code{eval-string} from @code{(ice-9 +eval-string)}, evaluating within @var{module} or the current module. +@end deffn + +@deftypefn {C Function} SCM scm_c_eval_string (const char *string) +@code{scm_eval_string}, but taking a C string in locale encoding instead +of an @code{SCM}. +@end deftypefn + +@deffn {Scheme Procedure} apply proc arg @dots{} arglst +@deffnx {C Function} scm_apply_0 (proc, arglst) +@deffnx {C Function} scm_apply_1 (proc, arg1, arglst) +@deffnx {C Function} scm_apply_2 (proc, arg1, arg2, arglst) +@deffnx {C Function} scm_apply_3 (proc, arg1, arg2, arg3, arglst) +@deffnx {C Function} scm_apply (proc, arg, rest) +@rnindex apply +Call @var{proc} with arguments @var{arg} @dots{} and the +elements of the @var{arglst} list. + +@code{scm_apply} takes parameters corresponding to a Scheme level +@code{(lambda (proc arg1 . rest) ...)}. So @var{arg1} and all but the +last element of the @var{rest} list make up @var{arg} @dots{}, and the +last element of @var{rest} is the @var{arglst} list. Or if @var{rest} +is the empty list @code{SCM_EOL} then there's no @var{arg} @dots{}, and +(@var{arg1}) is the @var{arglst}. + +@var{arglst} is not modified, but the @var{rest} list passed to +@code{scm_apply} is modified. +@end deffn + +@deffn {C Function} scm_call_0 (proc) +@deffnx {C Function} scm_call_1 (proc, arg1) +@deffnx {C Function} scm_call_2 (proc, arg1, arg2) +@deffnx {C Function} scm_call_3 (proc, arg1, arg2, arg3) +@deffnx {C Function} scm_call_4 (proc, arg1, arg2, arg3, arg4) +@deffnx {C Function} scm_call_5 (proc, arg1, arg2, arg3, arg4, arg5) +@deffnx {C Function} scm_call_6 (proc, arg1, arg2, arg3, arg4, arg5, arg6) +@deffnx {C Function} scm_call_7 (proc, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +@deffnx {C Function} scm_call_8 (proc, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +@deffnx {C Function} scm_call_9 (proc, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) +Call @var{proc} with the given arguments. +@end deffn + +@deffn {C Function} scm_call (proc, ...) +Call @var{proc} with any number of arguments. The argument list must be +terminated by @code{SCM_UNDEFINED}. For example: + +@example +scm_call (scm_c_public_ref ("guile", "+"), + scm_from_int (1), + scm_from_int (2), + SCM_UNDEFINED); +@end example +@end deffn + +@deffn {C Function} scm_call_n (proc, argv, nargs) +Call @var{proc} with the array of arguments @var{argv}, as a +@code{SCM*}. The length of the arguments should be passed in +@var{nargs}, as a @code{size_t}. +@end deffn + +@deffn {Scheme Procedure} primitive-eval exp +@deffnx {C Function} scm_primitive_eval (exp) +Evaluate @var{exp} in the top-level environment specified by +the current module. +@end deffn + + +@node Compilation +@subsection Compiling Scheme Code + +The @code{eval} procedure directly interprets the S-expression +representation of Scheme. An alternate strategy for evaluation is to +determine ahead of time what computations will be necessary to +evaluate the expression, and then use that recipe to produce the +desired results. This is known as @dfn{compilation}. + +While it is possible to compile simple Scheme expressions such as +@code{(+ 2 2)} or even @code{"Hello world!"}, compilation is most +interesting in the context of procedures. Compiling a lambda expression +produces a compiled procedure, which is just like a normal procedure +except typically much faster, because it can bypass the generic +interpreter. + +Functions from system modules in a Guile installation are normally +compiled already, so they load and run quickly. + +@cindex automatic compilation +Note that well-written Scheme programs will not typically call the +procedures in this section, for the same reason that it is often bad +taste to use @code{eval}. By default, Guile automatically compiles any +files it encounters that have not been compiled yet (@pxref{Invoking +Guile, @code{--auto-compile}}). The compiler can also be invoked +explicitly from the shell as @code{guild compile foo.scm}. + +(Why are calls to @code{eval} and @code{compile} usually in bad taste? +Because they are limited, in that they can only really make sense for +top-level expressions. Also, most needs for ``compile-time'' +computation are fulfilled by macros and closures. Of course one good +counterexample is the REPL itself, or any code that reads expressions +from a port.) + +Automatic compilation generally works transparently, without any need +for user intervention. However Guile does not yet do proper dependency +tracking, so that if file @file{@var{a}.scm} uses macros from +@file{@var{b}.scm}, and @var{@var{b}.scm} changes, @code{@var{a}.scm} +would not be automatically recompiled. To forcibly invalidate the +auto-compilation cache, pass the @code{--fresh-auto-compile} option to +Guile, or set the @code{GUILE_AUTO_COMPILE} environment variable to +@code{fresh} (instead of to @code{0} or @code{1}). + +For more information on the compiler itself, see @ref{Compiling to the +Virtual Machine}. For information on the virtual machine, see @ref{A +Virtual Machine for Guile}. + +The command-line interface to Guile's compiler is the @command{guild +compile} command: + +@deffn {Command} {guild compile} [@option{option}...] @var{file}... +Compile @var{file}, a source file, and store bytecode in the compilation cache +or in the file specified by the @option{-o} option. The following options are +available: + +@table @option + +@item -L @var{dir} +@itemx --load-path=@var{dir} +Add @var{dir} to the front of the module load path. + +@item -o @var{ofile} +@itemx --output=@var{ofile} +Write output bytecode to @var{ofile}. By convention, bytecode file +names end in @code{.go}. When @option{-o} is omitted, the output file +name is as for @code{compile-file} (see below). + +@item -x @var{extension} +Recognize @var{extension} as a valid source file name extension. + +For example, to compile R6RS code, you might want to pass @command{-x +.sls} so that files ending in @file{.sls} can be found. + +@item -W @var{warning} +@itemx --warn=@var{warning} +@cindex warnings, compiler +Emit warnings of type @var{warning}; use @code{--warn=help} for a list +of available warnings and their description. Currently recognized +warnings include @code{unused-variable}, @code{unused-toplevel}, +@code{shadowed-toplevel}, @code{unbound-variable}, +@code{macro-use-before-definition}, +@code{arity-mismatch}, @code{format}, +@code{duplicate-case-datum}, and @code{bad-case-datum}. + +@item -f @var{lang} +@itemx --from=@var{lang} +Use @var{lang} as the source language of @var{file}. If this option is omitted, +@code{scheme} is assumed. + +@item -t @var{lang} +@itemx --to=@var{lang} +Use @var{lang} as the target language of @var{file}. If this option is omitted, +@code{rtl} is assumed. + +@item -T @var{target} +@itemx --target=@var{target} +Produce code for @var{target} instead of @var{%host-type} (@pxref{Build +Config, %host-type}). Target must be a valid GNU triplet, such as +@code{armv5tel-unknown-linux-gnueabi} (@pxref{Specifying Target +Triplets,,, autoconf, GNU Autoconf Manual}). + +@end table + +Each @var{file} is assumed to be UTF-8-encoded, unless it contains a +coding declaration as recognized by @code{file-encoding} +(@pxref{Character Encoding of Source Files}). +@end deffn + +The compiler can also be invoked directly by Scheme code using the procedures +below: + +@deffn {Scheme Procedure} compile exp [#:env=#f] @ + [#:from=(current-language)] @ + [#:to=value] [#:opts=()] +Compile the expression @var{exp} in the environment @var{env}. If +@var{exp} is a procedure, the result will be a compiled procedure; +otherwise @code{compile} is mostly equivalent to @code{eval}. + +For a discussion of languages and compiler options, @xref{Compiling to +the Virtual Machine}. +@end deffn + +@deffn {Scheme Procedure} compile-file file [#:output-file=#f] @ + [#:from=(current-language)] [#:to='rtl] @ + [#:env=(default-environment from)] @ + [#:opts='()] @ + [#:canonicalization='relative] +Compile the file named @var{file}. + +Output will be written to a @var{output-file}. If you do not supply an +output file name, output is written to a file in the cache directory, as +computed by @code{(compiled-file-name @var{file})}. + +@var{from} and @var{to} specify the source and target languages. +@xref{Compiling to the Virtual Machine}, for more information on these +options, and on @var{env} and @var{opts}. + +As with @command{guild compile}, @var{file} is assumed to be +UTF-8-encoded unless it contains a coding declaration. +@end deffn + +@deffn {Scheme Procedure} compiled-file-name file +Compute a cached location for a compiled version of a Scheme file named +@var{file}. + +This file will usually be below the @file{$HOME/.cache/guile/ccache} +directory, depending on the value of the @env{XDG_CACHE_HOME} +environment variable. The intention is that @code{compiled-file-name} +provides a fallback location for caching auto-compiled files. If you +want to place a compile file in the @code{%load-compiled-path}, you +should pass the @var{output-file} option to @code{compile-file}, +explicitly. +@end deffn + +@defvr {Scheme Variable} %auto-compilation-options +This variable contains the options passed to the @code{compile-file} +procedure when auto-compiling source files. By default, it enables +useful compilation warnings. It can be customized from @file{~/.guile}. +@end defvr + +@node Loading +@subsection Loading Scheme Code from File + +@rnindex load +@deffn {Scheme Procedure} load filename [reader] +Load @var{filename} and evaluate its contents in the top-level +environment. + +@var{reader} if provided should be either @code{#f}, or a procedure with +the signature @code{(lambda (port) @dots{})} which reads the next +expression from @var{port}. If @var{reader} is @code{#f} or absent, +Guile's built-in @code{read} procedure is used (@pxref{Scheme Read}). + +The @var{reader} argument takes effect by setting the value of the +@code{current-reader} fluid (see below) before loading the file, and +restoring its previous value when loading is complete. The Scheme code +inside @var{filename} can itself change the current reader procedure on +the fly by setting @code{current-reader} fluid. + +If the variable @code{%load-hook} is defined, it should be bound to a +procedure that will be called before any code is loaded. See +documentation for @code{%load-hook} later in this section. +@end deffn + +@deffn {Scheme Procedure} load-compiled filename +Load the compiled file named @var{filename}. + +Compiling a source file (@pxref{Read/Load/Eval/Compile}) and then +calling @code{load-compiled} on the resulting file is equivalent to +calling @code{load} on the source file. +@end deffn + +@deffn {Scheme Procedure} primitive-load filename +@deffnx {C Function} scm_primitive_load (filename) +Load the file named @var{filename} and evaluate its contents in the +top-level environment. @var{filename} must either be a full pathname or +be a pathname relative to the current directory. If the variable +@code{%load-hook} is defined, it should be bound to a procedure that +will be called before any code is loaded. See the documentation for +@code{%load-hook} later in this section. +@end deffn + +@deftypefn {C Function} SCM scm_c_primitive_load (const char *filename) +@code{scm_primitive_load}, but taking a C string instead of an +@code{SCM}. +@end deftypefn + +@defvar current-reader +@code{current-reader} holds the read procedure that is currently being +used by the above loading procedures to read expressions (from the file +that they are loading). @code{current-reader} is a fluid, so it has an +independent value in each dynamic root and should be read and set using +@code{fluid-ref} and @code{fluid-set!} (@pxref{Fluids and Dynamic +States}). + +Changing @code{current-reader} is typically useful to introduce local +syntactic changes, such that code following the @code{fluid-set!} call +is read using the newly installed reader. The @code{current-reader} +change should take place at evaluation time when the code is evaluated, +or at compilation time when the code is compiled: + +@findex eval-when +@example +(eval-when (compile eval) + (fluid-set! current-reader my-own-reader)) +@end example + +The @code{eval-when} form above ensures that the @code{current-reader} +change occurs at the right time. +@end defvar + +@defvar %load-hook +A procedure to be called @code{(%load-hook @var{filename})} whenever a +file is loaded, or @code{#f} for no such call. @code{%load-hook} is +used by all of the loading functions (@code{load} and +@code{primitive-load}, and @code{load-from-path} and +@code{primitive-load-path} documented in the next section). + +For example an application can set this to show what's loaded, + +@example +(set! %load-hook (lambda (filename) + (format #t "Loading ~a ...\n" filename))) +(load-from-path "foo.scm") +@print{} Loading /usr/local/share/guile/site/foo.scm ... +@end example +@end defvar + +@deffn {Scheme Procedure} current-load-port +@deffnx {C Function} scm_current_load_port () +Return the current-load-port. +The load port is used internally by @code{primitive-load}. +@end deffn + +@node Load Paths +@subsection Load Paths + +The procedure in the previous section look for Scheme code in the file +system at specific location. Guile also has some procedures to search +the load path for code. + +@defvar %load-path +List of directories which should be searched for Scheme modules and +libraries. When Guile starts up, @code{%load-path} is initialized to +the default load path @code{(list (%library-dir) (%site-dir) +(%global-site-dir) (%package-data-dir))}. The @env{GUILE_LOAD_PATH} +environment variable can be used to prepend or append additional +directories (@pxref{Environment Variables}). + +@xref{Build Config}, for more on @code{%site-dir} and related +procedures. +@end defvar + +@deffn {Scheme Procedure} load-from-path filename +Similar to @code{load}, but searches for @var{filename} in the load +paths. Preferentially loads a compiled version of the file, if it is +available and up-to-date. +@end deffn + +A user can extend the load path by calling @code{add-to-load-path}. + +@deffn {Scheme Syntax} add-to-load-path dir +Add @var{dir} to the load path. +@end deffn + +For example, a script might include this form to add the directory that +it is in to the load path: + +@example +(add-to-load-path (dirname (current-filename))) +@end example + +It's better to use @code{add-to-load-path} than to modify +@code{%load-path} directly, because @code{add-to-load-path} takes care +of modifying the path both at compile-time and at run-time. + +@deffn {Scheme Procedure} primitive-load-path filename [exception-on-not-found] +@deffnx {C Function} scm_primitive_load_path (filename) +Search @code{%load-path} for the file named @var{filename} and +load it into the top-level environment. If @var{filename} is a +relative pathname and is not found in the list of search paths, +an error is signalled. Preferentially loads a compiled version of the +file, if it is available and up-to-date. + +If @var{filename} is a relative pathname and is not found in the list of +search paths, one of three things may happen, depending on the optional +second argument, @var{exception-on-not-found}. If it is @code{#f}, +@code{#f} will be returned. If it is a procedure, it will be called +with no arguments. (This allows a distinction to be made between +exceptions raised by loading a file, and exceptions related to the +loader itself.) Otherwise an error is signalled. + +For compatibility with Guile 1.8 and earlier, the C function takes only +one argument, which can be either a string (the file name) or an +argument list. +@end deffn + +@deffn {Scheme Procedure} %search-load-path filename +@deffnx {C Function} scm_sys_search_load_path (filename) +Search @code{%load-path} for the file named @var{filename}, which must +be readable by the current user. If @var{filename} is found in the list +of paths to search or is an absolute pathname, return its full pathname. +Otherwise, return @code{#f}. Filenames may have any of the optional +extensions in the @code{%load-extensions} list; @code{%search-load-path} +will try each extension automatically. +@end deffn + +@defvar %load-extensions +A list of default file extensions for files containing Scheme code. +@code{%search-load-path} tries each of these extensions when looking for +a file to load. By default, @code{%load-extensions} is bound to the +list @code{("" ".scm")}. +@end defvar + +As mentioned above, when Guile searches the @code{%load-path} for a +source file, it will also search the @code{%load-compiled-path} for a +corresponding compiled file. If the compiled file is as new or newer +than the source file, it will be loaded instead of the source file, +using @code{load-compiled}. + +@defvar %load-compiled-path +Like @code{%load-path}, but for compiled files. By default, this path +has two entries: one for compiled files from Guile itself, and one for +site packages. The @env{GUILE_LOAD_COMPILED_PATH} environment variable +can be used to prepend or append additional directories +(@pxref{Environment Variables}). +@end defvar + +When @code{primitive-load-path} searches the @code{%load-compiled-path} +for a corresponding compiled file for a relative path it does so by +appending @code{.go} to the relative path. For example, searching for +@code{ice-9/popen} could find +@code{/usr/lib/guile/3.0/ccache/ice-9/popen.go}, and use it instead of +@code{/usr/share/guile/3.0/ice-9/popen.scm}. + +If @code{primitive-load-path} does not find a corresponding @code{.go} +file in the @code{%load-compiled-path}, or the @code{.go} file is out of +date, it will search for a corresponding auto-compiled file in the +fallback path, possibly creating one if one does not exist. + +@xref{Installing Site Packages}, for more on how to correctly install +site packages. @xref{Modules and the File System}, for more on the +relationship between load paths and modules. @xref{Compilation}, for +more on the fallback path and auto-compilation. + +Finally, there are a couple of helper procedures for general path +manipulation. + +@deffn {Scheme Procedure} parse-path path [tail] +@deffnx {C Function} scm_parse_path (path, tail) +Parse @var{path}, which is expected to be a colon-separated string, into +a list and return the resulting list with @var{tail} appended. If +@var{path} is @code{#f}, @var{tail} is returned. +@end deffn + +@deffn {Scheme Procedure} parse-path-with-ellipsis path base +@deffnx {C Function} scm_parse_path_with_ellipsis (path, base) +Parse @var{path}, which is expected to be a colon-separated string, into +a list and return the resulting list with @var{base} (a list) spliced in +place of the @code{...} path component, if present, or else @var{base} +is added to the end. If @var{path} is @code{#f}, @var{base} is +returned. +@end deffn + +@deffn {Scheme Procedure} search-path path filename [extensions [require-exts?]] +@deffnx {C Function} scm_search_path (path, filename, rest) +Search @var{path} for a directory containing a file named +@var{filename}. The file must be readable, and not a directory. If we +find one, return its full filename; otherwise, return @code{#f}. If +@var{filename} is absolute, return it unchanged. If given, +@var{extensions} is a list of strings; for each directory in @var{path}, +we search for @var{filename} concatenated with each @var{extension}. If +@var{require-exts?} is true, require that the returned file name have +one of the given extensions; if @var{require-exts?} is not given, it +defaults to @code{#f}. + +For compatibility with Guile 1.8 and earlier, the C function takes only +three arguments. +@end deffn + + +@node Character Encoding of Source Files +@subsection Character Encoding of Source Files + +@cindex source file encoding +@cindex primitive-load +@cindex load +Scheme source code files are usually encoded in ASCII or UTF-8, but the +built-in reader can interpret other character encodings as well. When +Guile loads Scheme source code, it uses the @code{file-encoding} +procedure (described below) to try to guess the encoding of the file. +In the absence of any hints, UTF-8 is assumed. One way to provide a +hint about the encoding of a source file is to place a coding +declaration in the top 500 characters of the file. + +A coding declaration has the form @code{coding: XXXXXX}, where +@code{XXXXXX} is the name of a character encoding in which the source +code file has been encoded. The coding declaration must appear in a +scheme comment. It can either be a semicolon-initiated comment, or the +first block @code{#!} comment in the file. + +The name of the character encoding in the coding declaration is +typically lower case and containing only letters, numbers, and hyphens, +as recognized by @code{set-port-encoding!} (@pxref{Ports, +@code{set-port-encoding!}}). Common examples of character encoding +names are @code{utf-8} and @code{iso-8859-1}, +@url{http://www.iana.org/assignments/character-sets, as defined by +IANA}. Thus, the coding declaration is mostly compatible with Emacs. + +However, there are some differences in encoding names recognized by +Emacs and encoding names defined by IANA, the latter being essentially a +subset of the former. For instance, @code{latin-1} is a valid encoding +name for Emacs, but it's not according to the IANA standard, which Guile +follows; instead, you should use @code{iso-8859-1}, which is both +understood by Emacs and dubbed by IANA (IANA writes it uppercase but +Emacs wants it lowercase and Guile is case insensitive.) + +For source code, only a subset of all possible character encodings can +be interpreted by the built-in source code reader. Only those +character encodings in which ASCII text appears unmodified can be +used. This includes @code{UTF-8} and @code{ISO-8859-1} through +@code{ISO-8859-15}. The multi-byte character encodings @code{UTF-16} +and @code{UTF-32} may not be used because they are not compatible with +ASCII. + +@cindex read +@cindex encoding +@cindex port encoding +@findex set-port-encoding! +There might be a scenario in which one would want to read non-ASCII +code from a port, such as with the function @code{read}, instead of +with @code{load}. If the port's character encoding is the same as the +encoding of the code to be read by the port, not other special +handling is necessary. The port will automatically do the character +encoding conversion. The functions @code{setlocale} or by +@code{set-port-encoding!} are used to set port encodings +(@pxref{Ports}). + +If a port is used to read code of unknown character encoding, it can +accomplish this in three steps. First, the character encoding of the +port should be set to ISO-8859-1 using @code{set-port-encoding!}. +Then, the procedure @code{file-encoding}, described below, is used to +scan for a coding declaration when reading from the port. As a side +effect, it rewinds the port after its scan is complete. After that, +the port's character encoding should be set to the encoding returned +by @code{file-encoding}, if any, again by using +@code{set-port-encoding!}. Then the code can be read as normal. + +Alternatively, one can use the @code{#:guess-encoding} keyword argument +of @code{open-file} and related procedures. @xref{File Ports}. + +@deffn {Scheme Procedure} file-encoding port +@deffnx {C Function} scm_file_encoding (port) +Attempt to scan the first few hundred bytes from the @var{port} for +hints about its character encoding. Return a string containing the +encoding name or @code{#f} if the encoding cannot be determined. The +port is rewound. + +Currently, the only supported method is to look for an Emacs-like +character coding declaration (@pxref{Recognize Coding, how Emacs +recognizes file encoding,, emacs, The GNU Emacs Reference Manual}). The +coding declaration is of the form @code{coding: XXXXX} and must appear +in a Scheme comment. Additional heuristics may be added in the future. +@end deffn + + +@node Delayed Evaluation +@subsection Delayed Evaluation +@cindex delayed evaluation +@cindex promises + +Promises are a convenient way to defer a calculation until its result +is actually needed, and to run such a calculation only once. Also +@pxref{SRFI-45}. + +@deffn syntax delay expr +@rnindex delay +Return a promise object which holds the given @var{expr} expression, +ready to be evaluated by a later @code{force}. +@end deffn + +@deffn {Scheme Procedure} promise? obj +@deffnx {C Function} scm_promise_p (obj) +Return true if @var{obj} is a promise. +@end deffn + +@rnindex force +@deffn {Scheme Procedure} force p +@deffnx {C Function} scm_force (p) +Return the value obtained from evaluating the @var{expr} in the given +promise @var{p}. If @var{p} has previously been forced then its +@var{expr} is not evaluated again, instead the value obtained at that +time is simply returned. + +During a @code{force}, an @var{expr} can call @code{force} again on +its own promise, resulting in a recursive evaluation of that +@var{expr}. The first evaluation to return gives the value for the +promise. Higher evaluations run to completion in the normal way, but +their results are ignored, @code{force} always returns the first +value. +@end deffn + + +@node Local Evaluation +@subsection Local Evaluation + +Guile includes a facility to capture a lexical environment, and later +evaluate a new expression within that environment. This code is +implemented in a module. + +@example +(use-modules (ice-9 local-eval)) +@end example + +@deffn syntax the-environment +Captures and returns a lexical environment for use with +@code{local-eval} or @code{local-compile}. +@end deffn + +@deffn {Scheme Procedure} local-eval exp env +@deffnx {C Function} scm_local_eval (exp, env) +@deffnx {Scheme Procedure} local-compile exp env [opts=()] +Evaluate or compile the expression @var{exp} in the lexical environment +@var{env}. +@end deffn + +Here is a simple example, illustrating that it is the variable +that gets captured, not just its value at one point in time. + +@example +(define e (let ((x 100)) (the-environment))) +(define fetch-x (local-eval '(lambda () x) e)) +(fetch-x) +@result{} 100 +(local-eval '(set! x 42) e) +(fetch-x) +@result{} 42 +@end example + +While @var{exp} is evaluated within the lexical environment of +@code{(the-environment)}, it has the dynamic environment of the call to +@code{local-eval}. + +@code{local-eval} and @code{local-compile} can only evaluate +expressions, not definitions. + +@example +(local-eval '(define foo 42) + (let ((x 100)) (the-environment))) +@result{} syntax error: definition in expression context +@end example + +Note that the current implementation of @code{(the-environment)} only +captures ``normal'' lexical bindings, and pattern variables bound by +@code{syntax-case}. It does not currently capture local syntax +transformers bound by @code{let-syntax}, @code{letrec-syntax} or +non-top-level @code{define-syntax} forms. Any attempt to reference such +captured syntactic keywords via @code{local-eval} or +@code{local-compile} produces an error. + + +@node Local Inclusion +@subsection Local Inclusion + +This section has discussed various means of linking Scheme code +together: fundamentally, loading up files at run-time using @code{load} +and @code{load-compiled}. Guile provides another option to compose +parts of programs together at expansion-time instead of at run-time. + +@deffn {Scheme Syntax} include file-name +Open @var{file-name}, at expansion-time, and read the Scheme forms that +it contains, splicing them into the location of the @code{include}, +within a @code{begin}. + +If @var{file-name} is a relative path, it is searched for relative to +the path that contains the file that the @code{include} form appears in. +@end deffn + +If you are a C programmer, if @code{load} in Scheme is like +@code{dlopen} in C, consider @code{include} to be like the C +preprocessor's @code{#include}. When you use @code{include}, it is as +if the contents of the included file were typed in instead of the +@code{include} form. + +Because the code is included at compile-time, it is available to the +macroexpander. Syntax definitions in the included file are available to +later code in the form in which the @code{include} appears, without the +need for @code{eval-when}. (@xref{Eval When}.) + +For the same reason, compiling a form that uses @code{include} results +in one compilation unit, composed of multiple files. Loading the +compiled file is one @code{stat} operation for the compilation unit, +instead of @code{2*@var{n}} in the case of @code{load} (once for each +loaded source file, and once each corresponding compiled file, in the +best case). + +Unlike @code{load}, @code{include} also works within nested lexical +contexts. It so happens that the optimizer works best within a lexical +context, because all of the uses of bindings in a lexical context are +visible, so composing files by including them within a @code{(let () +...)} can sometimes lead to important speed improvements. + +On the other hand, @code{include} does have all the disadvantages of +early binding: once the code with the @code{include} is compiled, no +change to the included file is reflected in the future behavior of the +including form. + +Also, the particular form of @code{include}, which requires an absolute +path, or a path relative to the current directory at compile-time, is +not very amenable to compiling the source in one place, but then +installing the source to another place. For this reason, Guile provides +another form, @code{include-from-path}, which looks for the source file +to include within a load path. + +@deffn {Scheme Syntax} include-from-path file-name +Like @code{include}, but instead of expecting @code{file-name} to be an +absolute file name, it is expected to be a relative path to search in +the @code{%load-path}. +@end deffn + +@code{include-from-path} is more useful when you want to install all of +the source files for a package (as you should!). It makes it possible +to evaluate an installed file from source, instead of relying on the +@code{.go} file being up to date. + +@node Sandboxed Evaluation +@subsection Sandboxed Evaluation + +Sometimes you would like to evaluate code that comes from an untrusted +party. The safest way to do this is to buy a new computer, evaluate the +code on that computer, then throw the machine away. However if you are +unwilling to take this simple approach, Guile does include a limited +``sandbox'' facility that can allow untrusted code to be evaluated with +some confidence. + +To use the sandboxed evaluator, load its module: + +@example +(use-modules (ice-9 sandbox)) +@end example + +Guile's sandboxing facility starts with the ability to restrict the time +and space used by a piece of code. + +@deffn {Scheme Procedure} call-with-time-limit limit thunk limit-reached +Call @var{thunk}, but cancel it if @var{limit} seconds of wall-clock +time have elapsed. If the computation is cancelled, call +@var{limit-reached} in tail position. @var{thunk} must not disable +interrupts or prevent an abort via a @code{dynamic-wind} unwind handler. +@end deffn + +@deffn {Scheme Procedure} call-with-allocation-limit limit thunk limit-reached +Call @var{thunk}, but cancel it if @var{limit} bytes have been +allocated. If the computation is cancelled, call @var{limit-reached} in +tail position. @var{thunk} must not disable interrupts or prevent an +abort via a @code{dynamic-wind} unwind handler. + +This limit applies to both stack and heap allocation. The computation +will not be aborted before @var{limit} bytes have been allocated, but +for the heap allocation limit, the check may be postponed until the next garbage collection. + +Note that as a current shortcoming, the heap size limit applies to all +threads; concurrent allocation by other unrelated threads counts towards +the allocation limit. +@end deffn + +@deffn {Scheme Procedure} call-with-time-and-allocation-limits time-limit allocation-limit thunk +Invoke @var{thunk} in a dynamic extent in which its execution is limited +to @var{time-limit} seconds of wall-clock time, and its allocation to +@var{allocation-limit} bytes. @var{thunk} must not disable interrupts +or prevent an abort via a @code{dynamic-wind} unwind handler. + +If successful, return all values produced by invoking @var{thunk}. Any +uncaught exception thrown by the thunk will propagate out. If the time +or allocation limit is exceeded, an exception will be thrown to the +@code{limit-exceeded} key. +@end deffn + +The time limit and stack limit are both very precise, but the heap limit +only gets checked asynchronously, after a garbage collection. In +particular, if the heap is already very large, the number of allocated +bytes between garbage collections will be large, and therefore the +precision of the check is reduced. + +Additionally, due to the mechanism used by the allocation limit (the +@code{after-gc-hook}), large single allocations like @code{(make-vector +#e1e7)} are only detected after the allocation completes, even if the +allocation itself causes garbage collection. It's possible therefore +for user code to not only exceed the allocation limit set, but also to +exhaust all available memory, causing out-of-memory conditions at any +allocation site. Failure to allocate memory in Guile itself should be +safe and cause an exception to be thrown, but most systems are not +designed to handle @code{malloc} failures. An allocation failure may +therefore exercise unexpected code paths in your system, so it is a +weakness of the sandbox (and therefore an interesting point of attack). + +The main sandbox interface is @code{eval-in-sandbox}. + +@deffn {Scheme Procedure} eval-in-sandbox exp [#:time-limit 0.1] @ + [#:allocation-limit #e10e6] @ + [#:bindings all-pure-bindings] @ + [#:module (make-sandbox-module bindings)] @ + [#:sever-module? #t] +Evaluate the Scheme expression @var{exp} within an isolated +"sandbox". Limit its execution to @var{time-limit} seconds of +wall-clock time, and limit its allocation to @var{allocation-limit} +bytes. + +The evaluation will occur in @var{module}, which defaults to the result +of calling @code{make-sandbox-module} on @var{bindings}, which itself +defaults to @code{all-pure-bindings}. This is the core of the +sandbox: creating a scope for the expression that is @dfn{safe}. + +A safe sandbox module has two characteristics. Firstly, it will not +allow the expression being evaluated to avoid being cancelled due to +time or allocation limits. This ensures that the expression terminates +in a timely fashion. + +Secondly, a safe sandbox module will prevent the evaluation from +receiving information from previous evaluations, or from affecting +future evaluations. All combinations of binding sets exported by +@code{(ice-9 sandbox)} form safe sandbox modules. + +The @var{bindings} should be given as a list of import sets. One import +set is a list whose car names an interface, like @code{(ice-9 q)}, and +whose cdr is a list of imports. An import is either a bare symbol or a +pair of @code{(@var{out} . @var{in})}, where @var{out} and @var{in} are +both symbols and denote the name under which a binding is exported from +the module, and the name under which to make the binding available, +respectively. Note that @var{bindings} is only used as an input to the +default initializer for the @var{module} argument; if you pass +@code{#:module}, @var{bindings} is unused. If @var{sever-module?} is +true (the default), the module will be unlinked from the global module +tree after the evaluation returns, to allow @var{mod} to be +garbage-collected. + +If successful, return all values produced by @var{exp}. Any uncaught +exception thrown by the expression will propagate out. If the time or +allocation limit is exceeded, an exception will be thrown to the +@code{limit-exceeded} key. +@end deffn + +Constructing a safe sandbox module is tricky in general. Guile defines +an easy way to construct safe modules from predefined sets of bindings. +Before getting to that interface, here are some general notes on safety. + +@enumerate +@item The time and allocation limits rely on the ability to interrupt +and cancel a computation. For this reason, no binding included in a +sandbox module should be able to indefinitely postpone interrupt +handling, nor should a binding be able to prevent an abort. In practice +this second consideration means that @code{dynamic-wind} should not be +included in any binding set. +@item The time and allocation limits apply only to the +@code{eval-in-sandbox} call. If the call returns a procedure which is +later called, no limit is ``automatically'' in place. Users of +@code{eval-in-sandbox} have to be very careful to reimpose limits when +calling procedures that escape from sandboxes. +@item Similarly, the dynamic environment of the @code{eval-in-sandbox} +call is not necessarily in place when any procedure that escapes from +the sandbox is later called. + +This detail prevents us from exposing @code{primitive-eval} to the +sandbox, for two reasons. The first is that it's possible for legacy +code to forge references to any binding, if the +@code{allow-legacy-syntax-objects?} parameter is true. The default for +this parameter is true; @pxref{Syntax Transformer Helpers} for the +details. The parameter is bound to @code{#f} for the duration of the +@code{eval-in-sandbox} call itself, but that will not be in place during +calls to escaped procedures. + +The second reason we don't expose @code{primitive-eval} is that +@code{primitive-eval} implicitly works in the current module, which for +an escaped procedure will probably be different than the module that is +current for the @code{eval-in-sandbox} call itself. + +The common denominator here is that if an interface exposed to the +sandbox relies on dynamic environments, it is easy to mistakenly grant +the sandboxed procedure additional capabilities in the form of bindings +that it should not have access to. For this reason, the default sets of +predefined bindings do not depend on any dynamically scoped value. +@item Mutation may allow a sandboxed evaluation to break some invariant +in users of data supplied to it. A lot of code culturally doesn't +expect mutation, but if you hand mutable data to a sandboxed evaluation +and you also grant mutating capabilities to that evaluation, then the +sandboxed code may indeed mutate that data. The default set of bindings +to the sandbox do not include any mutating primitives. + +Relatedly, @code{set!} may allow a sandbox to mutate a primitive, +invalidating many system-wide invariants. Guile is currently quite +permissive when it comes to imported bindings and mutability. Although +@code{set!} to a module-local or lexically bound variable would be fine, +we don't currently have an easy way to disallow @code{set!} to an +imported binding, so currently no binding set includes @code{set!}. +@item Mutation may allow a sandboxed evaluation to keep state, or +make a communication mechanism with other code. On the one hand this +sounds cool, but on the other hand maybe this is part of your threat +model. Again, the default set of bindings doesn't include mutating +primitives, preventing sandboxed evaluations from keeping state. +@item The sandbox should probably not be able to open a network +connection, or write to a file, or open a file from disk. The default +binding set includes no interaction with the operating system. +@end enumerate + +If you, dear reader, find the above discussion interesting, you will +enjoy Jonathan Rees' dissertation, ``A Security Kernel Based on the +Lambda Calculus''. + +@defvr {Scheme Variable} all-pure-bindings +All ``pure'' bindings that together form a safe subset of those bindings +available by default to Guile user code. +@end defvr + +@defvr {Scheme Variable} all-pure-and-impure-bindings +Like @code{all-pure-bindings}, but additionally including mutating +primitives like @code{vector-set!}. This set is still safe in the sense +mentioned above, with the caveats about mutation. +@end defvr + +The components of these composite sets are as follows: +@defvr {Scheme Variable} alist-bindings +@defvrx {Scheme Variable} array-bindings +@defvrx {Scheme Variable} bit-bindings +@defvrx {Scheme Variable} bitvector-bindings +@defvrx {Scheme Variable} char-bindings +@defvrx {Scheme Variable} char-set-bindings +@defvrx {Scheme Variable} clock-bindings +@defvrx {Scheme Variable} core-bindings +@defvrx {Scheme Variable} error-bindings +@defvrx {Scheme Variable} fluid-bindings +@defvrx {Scheme Variable} hash-bindings +@defvrx {Scheme Variable} iteration-bindings +@defvrx {Scheme Variable} keyword-bindings +@defvrx {Scheme Variable} list-bindings +@defvrx {Scheme Variable} macro-bindings +@defvrx {Scheme Variable} nil-bindings +@defvrx {Scheme Variable} number-bindings +@defvrx {Scheme Variable} pair-bindings +@defvrx {Scheme Variable} predicate-bindings +@defvrx {Scheme Variable} procedure-bindings +@defvrx {Scheme Variable} promise-bindings +@defvrx {Scheme Variable} prompt-bindings +@defvrx {Scheme Variable} regexp-bindings +@defvrx {Scheme Variable} sort-bindings +@defvrx {Scheme Variable} srfi-4-bindings +@defvrx {Scheme Variable} string-bindings +@defvrx {Scheme Variable} symbol-bindings +@defvrx {Scheme Variable} unspecified-bindings +@defvrx {Scheme Variable} variable-bindings +@defvrx {Scheme Variable} vector-bindings +@defvrx {Scheme Variable} version-bindings +The components of @code{all-pure-bindings}. +@end defvr + +@defvr {Scheme Variable} mutating-alist-bindings +@defvrx {Scheme Variable} mutating-array-bindings +@defvrx {Scheme Variable} mutating-bitvector-bindings +@defvrx {Scheme Variable} mutating-fluid-bindings +@defvrx {Scheme Variable} mutating-hash-bindings +@defvrx {Scheme Variable} mutating-list-bindings +@defvrx {Scheme Variable} mutating-pair-bindings +@defvrx {Scheme Variable} mutating-sort-bindings +@defvrx {Scheme Variable} mutating-srfi-4-bindings +@defvrx {Scheme Variable} mutating-string-bindings +@defvrx {Scheme Variable} mutating-variable-bindings +@defvrx {Scheme Variable} mutating-vector-bindings +The additional components of @code{all-pure-and-impure-bindings}. +@end defvr + +Finally, what do you do with a binding set? What is a binding set +anyway? @code{make-sandbox-module} is here for you. + +@deffn {Scheme Procedure} make-sandbox-module bindings +Return a fresh module that only contains @var{bindings}. + +The @var{bindings} should be given as a list of import sets. One import +set is a list whose car names an interface, like @code{(ice-9 q)}, and +whose cdr is a list of imports. An import is either a bare symbol or a +pair of @code{(@var{out} . @var{in})}, where @var{out} and @var{in} are +both symbols and denote the name under which a binding is exported from +the module, and the name under which to make the binding available, +respectively. +@end deffn + +So you see that binding sets are just lists, and +@code{all-pure-and-impure-bindings} is really just the result of +appending all of the component binding sets. + + +@node REPL Servers +@subsection REPL Servers + +@cindex REPL server + +The procedures in this section are provided by +@lisp +(use-modules (system repl server)) +@end lisp + +When an application is written in Guile, it is often convenient to +allow the user to be able to interact with it by evaluating Scheme +expressions in a REPL. + +The procedures of this module allow you to spawn a @dfn{REPL server}, +which permits interaction over a local or TCP connection. Guile itself +uses them internally to implement the @option{--listen} switch, +@ref{Command-line Options}. + +@deffn {Scheme Procedure} make-tcp-server-socket [#:host=#f] @ + [#:addr] [#:port=37146] +Return a stream socket bound to a given address @var{addr} and port +number @var{port}. If the @var{host} is given, and @var{addr} is not, +then the @var{host} string is converted to an address. If neither is +given, we use the loopback address. +@end deffn + +@deffn {Scheme Procedure} make-unix-domain-server-socket [#:path="/tmp/guile-socket"] +Return a UNIX domain socket, bound to a given @var{path}. +@end deffn + +@deffn {Scheme Procedure} run-server [server-socket] +@deffnx {Scheme Procedure} spawn-server [server-socket] +Create and run a REPL, making it available over the given +@var{server-socket}. If @var{server-socket} is not provided, it +defaults to the socket created by calling @code{make-tcp-server-socket} +with no arguments. + +@code{run-server} runs the server in the current thread, whereas +@code{spawn-server} runs the server in a new thread. +@end deffn + +@deffn {Scheme Procedure} stop-server-and-clients! +Closes the connection on all running server sockets. + +Please note that in the current implementation, the REPL threads are +cancelled without unwinding their stacks. If any of them are holding +mutexes or are within a critical section, the results are unspecified. +@end deffn + +@node Cooperative REPL Servers +@subsection Cooperative REPL Servers + +@cindex Cooperative REPL server + +The procedures in this section are provided by +@lisp +(use-modules (system repl coop-server)) +@end lisp + +Whereas ordinary REPL servers run in their own threads (@pxref{REPL +Servers}), sometimes it is more convenient to provide REPLs that run at +specified times within an existing thread, for example in programs +utilizing an event loop or in single-threaded programs. This allows for +safe access and mutation of a program's data structures from the REPL, +without concern for thread synchronization. + +Although the REPLs are run in the thread that calls +@code{spawn-coop-repl-server} and @code{poll-coop-repl-server}, +dedicated threads are spawned so that the calling thread is not blocked. +The spawned threads read input for the REPLs and to listen for new +connections. + +Cooperative REPL servers must be polled periodically to evaluate any +pending expressions by calling @code{poll-coop-repl-server} with the +object returned from @code{spawn-coop-repl-server}. The thread that +calls @code{poll-coop-repl-server} will be blocked for as long as the +expression takes to be evaluated or if the debugger is entered. + +@deffn {Scheme Procedure} spawn-coop-repl-server [server-socket] +Create and return a new cooperative REPL server object, and spawn a new +thread to listen for connections on @var{server-socket}. Proper +functioning of the REPL server requires that +@code{poll-coop-repl-server} be called periodically on the returned +server object. +@end deffn + +@deffn {Scheme Procedure} poll-coop-repl-server coop-server +Poll the cooperative REPL server @var{coop-server} and apply a pending +operation if there is one, such as evaluating an expression typed at the +REPL prompt. This procedure must be called from the same thread that +called @code{spawn-coop-repl-server}. +@end deffn + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-foreign-objects.texi b/doc/ref/api-foreign-objects.texi new file mode 100644 index 000000000..f27f9c154 --- /dev/null +++ b/doc/ref/api-foreign-objects.texi @@ -0,0 +1,125 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2013, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Foreign Objects +@section Foreign Objects + +@cindex foreign object + +This chapter contains reference information related to defining and +working with foreign objects. @xref{Defining New Foreign Object Types}, +for a tutorial-like introduction to foreign objects. + +@deftp {C Type} scm_t_struct_finalize +This function type returns @code{void} and takes one @code{SCM} +argument. +@end deftp + +@deftypefn {C Function} SCM scm_make_foreign_object_type (SCM name, SCM slots, scm_t_struct_finalize finalizer) +Create a fresh foreign object type. @var{name} is a symbol naming the +type. @var{slots} is a list of symbols, each one naming a field in the +foreign object type. @var{finalizer} indicates the finalizer, and may +be @code{NULL}. +@end deftypefn + +@cindex finalizer +@cindex finalization + +We recommend that finalizers be avoided if possible. @xref{Foreign +Object Memory Management}. Finalizers must be async-safe and +thread-safe. Again, @pxref{Foreign Object Memory Management}. If you +are embedding Guile in an application that is not thread-safe, and you +define foreign object types that need finalization, you might want to +disable automatic finalization, and arrange to call +@code{scm_manually_run_finalizers ()} yourself. + +@deftypefn {C Function} int scm_set_automatic_finalization_enabled (int enabled_p) +Enable or disable automatic finalization. By default, Guile arranges to +invoke object finalizers automatically, in a separate thread if +possible. Passing a zero value for @var{enabled_p} will disable +automatic finalization for Guile as a whole. If you disable automatic +finalization, you will have to call @code{scm_run_finalizers ()} +periodically. + +Unlike most other Guile functions, you can call +@code{scm_set_automatic_finalization_enabled} before Guile has been +initialized. + +Return the previous status of automatic finalization. +@end deftypefn + +@deftypefn {C Function} int scm_run_finalizers (void) +Invoke any pending finalizers. Returns the number of finalizers that +were invoked. This function should be called when automatic +finalization is disabled, though it may be called if it is enabled as +well. +@end deftypefn + +@deftypefn {C Function} void scm_assert_foreign_object_type (SCM type, SCM val) +When @var{val} is a foreign object of the given @var{type}, do nothing. +Otherwise, signal an error. +@end deftypefn + +@deftypefn {C Function} SCM scm_make_foreign_object_0 (SCM type) +@deftypefnx {C Function} SCM scm_make_foreign_object_1 (SCM type, void *val0) +@deftypefnx {C Function} SCM scm_make_foreign_object_2 (SCM type, void *val0, void *val1) +@deftypefnx {C Function} SCM scm_make_foreign_object_3 (SCM type, void *val0, void *val1, void *val2) +@deftypefnx {C Function} SCM scm_make_foreign_object_n (SCM type, size_t n, void *vals[]) +Make a new foreign object of the type with type @var{type} and +initialize the first @var{n} fields to the given values, as appropriate. + +The number of fields for objects of a given type is fixed when the type +is created. It is an error to give more initializers than there are +fields in the value. It is perfectly fine to give fewer initializers +than needed; this is convenient when some fields are of non-pointer +types, and would be easier to initialize with the setters described +below. +@end deftypefn + +@deftypefn {C Function} void* scm_foreign_object_ref (SCM obj, size_t n); +@deftypefnx {C Function} scm_t_bits scm_foreign_object_unsigned_ref (SCM obj, size_t n); +@deftypefnx {C Function} scm_t_signed_bits scm_foreign_object_signed_ref (SCM obj, size_t n); +Return the value of the @var{n}th field of the foreign object @var{obj}. +The backing store for the fields is as wide as a @code{scm_t_bits} +value, which is at least as wide as a pointer. The different variants +handle casting in a portable way. +@end deftypefn + +@deftypefn {C Function} void scm_foreign_object_set_x (SCM obj, size_t n, void *val); +@deftypefnx {C Function} void scm_foreign_object_unsigned_set_x (SCM obj, size_t n, scm_t_bits val); +@deftypefnx {C Function} void scm_foreign_object_signed_set_x (SCM obj, size_t n, scm_t_signed_bits val); +Set the value of the @var{n}th field of the foreign object @var{obj} to +@var{val}, after portably converting to a @code{scm_t_bits} value, if +needed. +@end deftypefn + +One can also access foreign objects from Scheme. @xref{Foreign Objects +and Scheme}, for some examples. + +@example +(use-modules (system foreign-object)) +@end example + +@deffn {Scheme Procedure} make-foreign-object-type name slots [#:finalizer=#f] +Make a new foreign object type. See the above documentation for +@code{scm_make_foreign_object_type}; these functions are exactly +equivalent, except for the way in which the finalizer gets attached to +instances (an internal detail). + +The resulting value is a GOOPS class. @xref{GOOPS}, for more on classes +in Guile. +@end deffn + +@deffn {Scheme Syntax} define-foreign-object-type name constructor (slot ...) [#:finalizer=#f] +A convenience macro to define a type, using +@code{make-foreign-object-type}, and bind it to @var{name}. A +constructor will be bound to @var{constructor}, and getters will be +bound to each of @var{slot...}. +@end deffn + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi new file mode 100644 index 000000000..d99a33300 --- /dev/null +++ b/doc/ref/api-foreign.texi @@ -0,0 +1,1001 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2007-2014, 2016-2017 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Foreign Function Interface +@section Foreign Function Interface +@cindex foreign function interface +@cindex ffi + +The more one hacks in Scheme, the more one realizes that there are +actually two computational worlds: one which is warm and alive, that +land of parentheses, and one cold and dead, the land of C and its ilk. + +But yet we as programmers live in both worlds, and Guile itself is half +implemented in C. So it is that Guile's living half pays respect to its +dead counterpart, via a spectrum of interfaces to C ranging from dynamic +loading of Scheme primitives to dynamic binding of stock C library +procedures. + +@menu +* Foreign Libraries:: Dynamically linking to libraries. +* Foreign Functions:: Simple calls to C procedures. +* C Extensions:: Extending Guile in C with loadable modules. +* Modules and Extensions:: Loading C extensions into modules. +* Foreign Pointers:: Accessing global variables. +* Dynamic FFI:: Calling arbitrary C functions. +@end menu + + +@node Foreign Libraries +@subsection Foreign Libraries + +Most modern Unices have something called @dfn{shared libraries}. This +ordinarily means that they have the capability to share the executable +image of a library between several running programs to save memory and +disk space. But generally, shared libraries give a lot of additional +flexibility compared to the traditional static libraries. In fact, +calling them `dynamic' libraries is as correct as calling them `shared'. + +Shared libraries really give you a lot of flexibility in addition to the +memory and disk space savings. When you link a program against a shared +library, that library is not closely incorporated into the final +executable. Instead, the executable of your program only contains +enough information to find the needed shared libraries when the program +is actually run. Only then, when the program is starting, is the final +step of the linking process performed. This means that you need not +recompile all programs when you install a new, only slightly modified +version of a shared library. The programs will pick up the changes +automatically the next time they are run. + +Now, when all the necessary machinery is there to perform part of the +linking at run-time, why not take the next step and allow the programmer +to explicitly take advantage of it from within their program? Of course, +many operating systems that support shared libraries do just that, and +chances are that Guile will allow you to access this feature from within +your Scheme programs. As you might have guessed already, this feature +is called @dfn{dynamic linking}.@footnote{Some people also refer to the +final linking stage at program startup as `dynamic linking', so if you +want to make yourself perfectly clear, it is probably best to use the +more technical term @dfn{dlopening}, as suggested by Gordon Matzigkeit +in his libtool documentation.} + +We titled this section ``foreign libraries'' because although the name +``foreign'' doesn't leak into the API, the world of C really is foreign +to Scheme -- and that estrangement extends to components of foreign +libraries as well, as we see in future sections. + +@deffn {Scheme Procedure} dynamic-link [library] +@deffnx {C Function} scm_dynamic_link (library) +Find the shared library denoted by @var{library} (a string) and link it +into the running Guile application. When everything works out, return a +Scheme object suitable for representing the linked object file. +Otherwise an error is thrown. How object files are searched is system +dependent. + +Normally, @var{library} is just the name of some shared library file +that will be searched for in the places where shared libraries usually +reside, such as in @file{/usr/lib} and @file{/usr/local/lib}. + +@var{library} should not contain an extension such as @code{.so}. The +correct file name extension for the host operating system is provided +automatically, according to libltdl's rules (@pxref{Libltdl interface, +lt_dlopenext, @code{lt_dlopenext}, libtool, Shared Library Support for +GNU}). + +When @var{library} is omitted, a @dfn{global symbol handle} is returned. This +handle provides access to the symbols available to the program at run-time, +including those exported by the program itself and the shared libraries already +loaded. + +Note that on hosts that use dynamic-link libraries (DLLs), the global +symbol handle may not be able to provide access to symbols from +recursively-loaded DLLs. Only exported symbols from those DLLs directly +loaded by the program may be available. +@end deffn + +@deffn {Scheme Procedure} dynamic-object? obj +@deffnx {C Function} scm_dynamic_object_p (obj) +Return @code{#t} if @var{obj} is a dynamic library handle, or @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} dynamic-unlink dobj +@deffnx {C Function} scm_dynamic_unlink (dobj) +Unlink the indicated object file from the application. The +argument @var{dobj} must have been obtained by a call to +@code{dynamic-link}. After @code{dynamic-unlink} has been +called on @var{dobj}, its content is no longer accessible. +@end deffn + +@smallexample +(define libgl-obj (dynamic-link "libGL")) +libgl-obj +@result{} #<dynamic-object "libGL"> +(dynamic-unlink libGL-obj) +libGL-obj +@result{} #<dynamic-object "libGL" (unlinked)> +@end smallexample + +As you can see, after calling @code{dynamic-unlink} on a dynamically +linked library, it is marked as @samp{(unlinked)} and you are no longer +able to use it with @code{dynamic-call}, etc. Whether the library is +really removed from you program is system-dependent and will generally +not happen when some other parts of your program still use it. + +When dynamic linking is disabled or not supported on your system, +the above functions throw errors, but they are still available. + + +@node Foreign Functions +@subsection Foreign Functions + +The most natural thing to do with a dynamic library is to grovel around +in it for a function pointer: a @dfn{foreign function}. +@code{dynamic-func} exists for that purpose. + +@deffn {Scheme Procedure} dynamic-func name dobj +@deffnx {C Function} scm_dynamic_func (name, dobj) +Return a ``handle'' for the func @var{name} in the shared object referred to +by @var{dobj}. The handle can be passed to @code{dynamic-call} to +actually call the function. + +Regardless whether your C compiler prepends an underscore @samp{_} to the global +names in a program, you should @strong{not} include this underscore in +@var{name} since it will be added automatically when necessary. +@end deffn + +Guile has static support for calling functions with no arguments, +@code{dynamic-call}. + +@deffn {Scheme Procedure} dynamic-call func dobj +@deffnx {C Function} scm_dynamic_call (func, dobj) +Call the C function indicated by @var{func} and @var{dobj}. +The function is passed no arguments and its return value is +ignored. When @var{function} is something returned by +@code{dynamic-func}, call that function and ignore @var{dobj}. +When @var{func} is a string , look it up in @var{dynobj}; this +is equivalent to +@smallexample +(dynamic-call (dynamic-func @var{func} @var{dobj}) #f) +@end smallexample +@end deffn + +@code{dynamic-call} is not very powerful. It is mostly intended to be +used for calling specially written initialization functions that will +then add new primitives to Guile. For example, we do not expect that you +will dynamically link @file{libX11} with @code{dynamic-link} and then +construct a beautiful graphical user interface just by using +@code{dynamic-call}. Instead, the usual way would be to write a special +Guile-to-X11 glue library that has intimate knowledge about both Guile +and X11 and does whatever is necessary to make them inter-operate +smoothly. This glue library could then be dynamically linked into a +vanilla Guile interpreter and activated by calling its initialization +function. That function would add all the new types and primitives to +the Guile interpreter that it has to offer. + +(There is actually another, better option: simply to create a +@file{libX11} wrapper in Scheme via the dynamic FFI. @xref{Dynamic FFI}, +for more information.) + +Given some set of C extensions to Guile, the next logical step is to +integrate these glue libraries into the module system of Guile so that +you can load new primitives into a running system just as you can load +new Scheme code. + +@deffn {Scheme Procedure} load-extension lib init +@deffnx {C Function} scm_load_extension (lib, init) +Load and initialize the extension designated by LIB and INIT. +When there is no pre-registered function for LIB/INIT, this is +equivalent to + +@lisp +(dynamic-call INIT (dynamic-link LIB)) +@end lisp + +When there is a pre-registered function, that function is called +instead. + +Normally, there is no pre-registered function. This option exists +only for situations where dynamic linking is unavailable or unwanted. +In that case, you would statically link your program with the desired +library, and register its init function right after Guile has been +initialized. + +As for @code{dynamic-link}, @var{lib} should not contain any suffix such +as @code{.so} (@pxref{Foreign Libraries, dynamic-link}). It +should also not contain any directory components. Libraries that +implement Guile Extensions should be put into the normal locations for +shared libraries. We recommend to use the naming convention +@file{libguile-bla-blum} for a extension related to a module @code{(bla +blum)}. + +The normal way for a extension to be used is to write a small Scheme +file that defines a module, and to load the extension into this +module. When the module is auto-loaded, the extension is loaded as +well. For example, + +@lisp +(define-module (bla blum)) + +(load-extension "libguile-bla-blum" "bla_init_blum") +@end lisp +@end deffn + +@node C Extensions +@subsection C Extensions + +The most interesting application of dynamically linked libraries is +probably to use them for providing @emph{compiled code modules} to +Scheme programs. As much fun as programming in Scheme is, every now and +then comes the need to write some low-level C stuff to make Scheme even +more fun. + +Not only can you put these new primitives into their own module (see the +previous section), you can even put them into a shared library that is +only then linked to your running Guile image when it is actually +needed. + +An example will hopefully make everything clear. Suppose we want to +make the Bessel functions of the C library available to Scheme in the +module @samp{(math bessel)}. First we need to write the appropriate +glue code to convert the arguments and return values of the functions +from Scheme to C and back. Additionally, we need a function that will +add them to the set of Guile primitives. Because this is just an +example, we will only implement this for the @code{j0} function. + +@smallexample +#include <math.h> +#include <libguile.h> + +SCM +j0_wrapper (SCM x) +@{ + return scm_from_double (j0 (scm_to_double (x, "j0"))); +@} + +void +init_math_bessel () +@{ + scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper); +@} +@end smallexample + +We can already try to bring this into action by manually calling the low +level functions for performing dynamic linking. The C source file needs +to be compiled into a shared library. Here is how to do it on +GNU/Linux, please refer to the @code{libtool} documentation for how to +create dynamically linkable libraries portably. + +@smallexample +gcc -shared -o libbessel.so -fPIC bessel.c +@end smallexample + +Now fire up Guile: + +@lisp +(define bessel-lib (dynamic-link "./libbessel.so")) +(dynamic-call "init_math_bessel" bessel-lib) +(j0 2) +@result{} 0.223890779141236 +@end lisp + +The filename @file{./libbessel.so} should be pointing to the shared +library produced with the @code{gcc} command above, of course. The +second line of the Guile interaction will call the +@code{init_math_bessel} function which in turn will register the C +function @code{j0_wrapper} with the Guile interpreter under the name +@code{j0}. This function becomes immediately available and we can call +it from Scheme. + +Fun, isn't it? But we are only half way there. This is what +@code{apropos} has to say about @code{j0}: + +@smallexample +(apropos "j0") +@print{} (guile-user): j0 #<primitive-procedure j0> +@end smallexample + +As you can see, @code{j0} is contained in the root module, where all +the other Guile primitives like @code{display}, etc live. In general, +a primitive is put into whatever module is the @dfn{current module} at +the time @code{scm_c_define_gsubr} is called. + +A compiled module should have a specially named @dfn{module init +function}. Guile knows about this special name and will call that +function automatically after having linked in the shared library. For +our example, we replace @code{init_math_bessel} with the following code in +@file{bessel.c}: + +@smallexample +void +init_math_bessel (void *unused) +@{ + scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper); + scm_c_export ("j0", NULL); +@} + +void +scm_init_math_bessel_module () +@{ + scm_c_define_module ("math bessel", init_math_bessel, NULL); +@} +@end smallexample + +The general pattern for the name of a module init function is: +@samp{scm_init_}, followed by the name of the module where the +individual hierarchical components are concatenated with underscores, +followed by @samp{_module}. + +After @file{libbessel.so} has been rebuilt, we need to place the shared +library into the right place. + +Once the module has been correctly installed, it should be possible to +use it like this: + +@smallexample +guile> (load-extension "./libbessel.so" "scm_init_math_bessel_module") +guile> (use-modules (math bessel)) +guile> (j0 2) +0.223890779141236 +guile> (apropos "j0") +@print{} (math bessel): j0 #<primitive-procedure j0> +@end smallexample + +That's it! + + +@node Modules and Extensions +@subsection Modules and Extensions + +The new primitives that you add to Guile with @code{scm_c_define_gsubr} +(@pxref{Primitive Procedures}) or with any of the other mechanisms are +placed into the module that is current when the +@code{scm_c_define_gsubr} is executed. Extensions loaded from the REPL, +for example, will be placed into the @code{(guile-user)} module, if the +REPL module was not changed. + +To define C primitives within a specific module, the simplest way is: + +@example +(define-module (foo bar)) +(load-extension "foobar-c-code" "foo_bar_init") +@end example + +@cindex extensiondir +When loaded with @code{(use-modules (foo bar))}, the +@code{load-extension} call looks for the @file{foobar-c-code.so} (etc) +object file in Guile's @code{extensiondir}, which is usually a +subdirectory of the @code{libdir}. For example, if your libdir is +@file{/usr/lib}, the @code{extensiondir} for the Guile @value{EFFECTIVE-VERSION}.@var{x} +series will be @file{/usr/lib/guile/@value{EFFECTIVE-VERSION}/}. + +The extension path includes the major and minor version of Guile (the +``effective version''), because Guile guarantees compatibility within a +given effective version. This allows you to install different versions +of the same extension for different versions of Guile. + +If the extension is not found in the @code{extensiondir}, Guile will +also search the standard system locations, such as @file{/usr/lib} or +@file{/usr/local/lib}. It is preferable, however, to keep your extension +out of the system library path, to prevent unintended interference with +other dynamically-linked C libraries. + +If someone installs your module to a non-standard location then the +object file won't be found. You can address this by inserting the +install location in the @file{foo/bar.scm} file. This is convenient +for the user and also guarantees the intended object is read, even if +stray older or newer versions are in the loader's path. + +The usual way to specify an install location is with a @code{prefix} +at the configure stage, for instance @samp{./configure prefix=/opt} +results in library files as say @file{/opt/lib/foobar-c-code.so}. +When using Autoconf (@pxref{Top, , Introduction, autoconf, The GNU +Autoconf Manual}), the library location is in a @code{libdir} +variable. Its value is intended to be expanded by @command{make}, and +can by substituted into a source file like @file{foo.scm.in} + +@example +(define-module (foo bar)) +(load-extension "XXextensiondirXX/foobar-c-code" "foo_bar_init") +@end example + +@noindent +with the following in a @file{Makefile}, using @command{sed} +(@pxref{Top, , Introduction, sed, SED, A Stream Editor}), + +@example +foo.scm: foo.scm.in + sed 's|XXextensiondirXX|$(libdir)/guile/@value{EFFECTIVE-VERSION}|' <foo.scm.in >foo.scm +@end example + +The actual pattern @code{XXextensiondirXX} is arbitrary, it's only something +which doesn't otherwise occur. If several modules need the value, it +can be easier to create one @file{foo/config.scm} with a define of the +@code{extensiondir} location, and use that as required. + +@example +(define-module (foo config)) +(define-public foo-config-extensiondir "XXextensiondirXX"") +@end example + +Such a file might have other locations too, for instance a data +directory for auxiliary files, or @code{localedir} if the module has +its own @code{gettext} message catalogue +(@pxref{Internationalization}). + +It will be noted all of the above requires that the Scheme code to be +found in @code{%load-path} (@pxref{Load Paths}). Presently it's left up +to the system administrator or each user to augment that path when +installing Guile modules in non-default locations. But having reached +the Scheme code, that code should take care of hitting any of its own +private files etc. + + +@node Foreign Pointers +@subsection Foreign Pointers + +The previous sections have shown how Guile can be extended at runtime by +loading compiled C extensions. This approach is all well and good, but +wouldn't it be nice if we didn't have to write any C at all? This +section takes up the problem of accessing C values from Scheme, and the +next discusses C functions. + +@menu +* Foreign Types:: Expressing C types in Scheme. +* Foreign Variables:: Pointers to C symbols. +* Void Pointers and Byte Access:: Pointers into the ether. +* Foreign Structs:: Packing and unpacking structs. +@end menu + +@node Foreign Types +@subsubsection Foreign Types + +The first impedance mismatch that one sees between C and Scheme is that +in C, the storage locations (variables) are typed, but in Scheme types +are associated with values, not variables. @xref{Values and Variables}. + +So when describing a C function or a C structure so that it can be +accessed from Scheme, the data types of the parameters or fields must be +passed explicitly. + +These ``C type values'' may be constructed using the constants and +procedures from the @code{(system foreign)} module, which may be loaded +like this: + +@example +(use-modules (system foreign)) +@end example + +@code{(system foreign)} exports a number of values expressing the basic +C types: + +@defvr {Scheme Variable} int8 +@defvrx {Scheme Variable} uint8 +@defvrx {Scheme Variable} uint16 +@defvrx {Scheme Variable} int16 +@defvrx {Scheme Variable} uint32 +@defvrx {Scheme Variable} int32 +@defvrx {Scheme Variable} uint64 +@defvrx {Scheme Variable} int64 +@defvrx {Scheme Variable} float +@defvrx {Scheme Variable} double +These values represent the C numeric types of the specified sizes and +signednesses. +@end defvr + +In addition there are some convenience bindings for indicating types of +platform-dependent size: + +@defvr {Scheme Variable} int +@defvrx {Scheme Variable} unsigned-int +@defvrx {Scheme Variable} long +@defvrx {Scheme Variable} unsigned-long +@defvrx {Scheme Variable} short +@defvrx {Scheme Variable} unsigned-short +@defvrx {Scheme Variable} size_t +@defvrx {Scheme Variable} ssize_t +@defvrx {Scheme Variable} ptrdiff_t +@defvrx {Scheme Variable} intptr_t +@defvrx {Scheme Variable} uintptr_t +Values exported by the @code{(system foreign)} module, representing C +numeric types. For example, @code{long} may be @code{equal?} to +@code{int64} on a 64-bit platform. +@end defvr + +@defvr {Scheme Variable} void +The @code{void} type. It can be used as the first argument to +@code{pointer->procedure} to wrap a C function that returns nothing. +@end defvr + +In addition, the symbol @code{*} is used by convention to denote pointer +types. Procedures detailed in the following sections, such as +@code{pointer->procedure}, accept it as a type descriptor. + +@node Foreign Variables +@subsubsection Foreign Variables + +Pointers to variables in the current address space may be looked up +dynamically using @code{dynamic-pointer}. + +@deffn {Scheme Procedure} dynamic-pointer name dobj +@deffnx {C Function} scm_dynamic_pointer (name, dobj) +Return a ``wrapped pointer'' for the symbol @var{name} in the shared +object referred to by @var{dobj}. The returned pointer points to a C +object. + +Regardless whether your C compiler prepends an underscore @samp{_} to the global +names in a program, you should @strong{not} include this underscore in +@var{name} since it will be added automatically when necessary. +@end deffn + +For example, currently Guile has a variable, @code{scm_numptob}, as part +of its API. It is declared as a C @code{long}. So, to create a handle +pointing to that foreign value, we do: + +@example +(use-modules (system foreign)) +(define numptob (dynamic-pointer "scm_numptob" (dynamic-link))) +numptob +@result{} #<pointer 0x7fb35b1b4688> +@end example + +(The next section discusses ways to dereference pointers.) + +A value returned by @code{dynamic-pointer} is a Scheme wrapper for a C +pointer. + +@deffn {Scheme Procedure} pointer-address pointer +@deffnx {C Function} scm_pointer_address (pointer) +Return the numerical value of @var{pointer}. + +@example +(pointer-address numptob) +@result{} 139984413364296 ; YMMV +@end example +@end deffn + +@deffn {Scheme Procedure} make-pointer address [finalizer] +Return a foreign pointer object pointing to @var{address}. If +@var{finalizer} is passed, it should be a pointer to a one-argument C +function that will be called when the pointer object becomes +unreachable. +@end deffn + +@deffn {Scheme Procedure} pointer? obj +Return @code{#t} if @var{obj} is a pointer object, @code{#f} otherwise. +@end deffn + +@defvr {Scheme Variable} %null-pointer +A foreign pointer whose value is 0. +@end defvr + +@deffn {Scheme Procedure} null-pointer? pointer +Return @code{#t} if @var{pointer} is the null pointer, @code{#f} otherwise. +@end deffn + +For the purpose of passing SCM values directly to foreign functions, and +allowing them to return SCM values, Guile also supports some unsafe +casting operators. + +@deffn {Scheme Procedure} scm->pointer scm +Return a foreign pointer object with the @code{object-address} +of @var{scm}. +@end deffn + +@deffn {Scheme Procedure} pointer->scm pointer +Unsafely cast @var{pointer} to a Scheme object. +Cross your fingers! +@end deffn + +Sometimes you want to give C extensions access to the dynamic FFI. At +that point, the names get confusing, because ``pointer'' can refer to a +@code{SCM} object that wraps a pointer, or to a @code{void*} value. We +will try to use ``pointer object'' to refer to Scheme objects, and +``pointer value'' to refer to @code{void *} values. + +@deftypefn {C Function} SCM scm_from_pointer (void *ptr, void (*finalizer) (void*)) +Create a pointer object from a pointer value. + +If @var{finalizer} is non-null, Guile arranges to call it on the pointer +value at some point after the pointer object becomes collectable. +@end deftypefn + +@deftypefn {C Function} void* scm_to_pointer (SCM obj) +Unpack the pointer value from a pointer object. +@end deftypefn + +@node Void Pointers and Byte Access +@subsubsection Void Pointers and Byte Access + +Wrapped pointers are untyped, so they are essentially equivalent to C +@code{void} pointers. As in C, the memory region pointed to by a +pointer can be accessed at the byte level. This is achieved using +@emph{bytevectors} (@pxref{Bytevectors}). The @code{(rnrs bytevectors)} +module contains procedures that can be used to convert byte sequences to +Scheme objects such as strings, floating point numbers, or integers. + +@deffn {Scheme Procedure} pointer->bytevector pointer len [offset [uvec_type]] +@deffnx {C Function} scm_pointer_to_bytevector (pointer, len, offset, uvec_type) +Return a bytevector aliasing the @var{len} bytes pointed to by +@var{pointer}. + +The user may specify an alternate default interpretation for the memory +by passing the @var{uvec_type} argument, to indicate that the memory is +an array of elements of that type. @var{uvec_type} should be something +that @code{array-type} would return, like @code{f32} or @code{s16}. + +When @var{offset} is passed, it specifies the offset in bytes relative +to @var{pointer} of the memory region aliased by the returned +bytevector. + +Mutating the returned bytevector mutates the memory pointed to by +@var{pointer}, so buckle your seatbelts. +@end deffn + +@deffn {Scheme Procedure} bytevector->pointer bv [offset] +@deffnx {C Function} scm_bytevector_to_pointer (bv, offset) +Return a pointer pointer aliasing the memory pointed to by @var{bv} or +@var{offset} bytes after @var{bv} when @var{offset} is passed. +@end deffn + +In addition to these primitives, convenience procedures are available: + +@deffn {Scheme Procedure} dereference-pointer pointer +Assuming @var{pointer} points to a memory region that holds a pointer, +return this pointer. +@end deffn + +@deffn {Scheme Procedure} string->pointer string [encoding] +Return a foreign pointer to a nul-terminated copy of @var{string} in the +given @var{encoding}, defaulting to the current locale encoding. The C +string is freed when the returned foreign pointer becomes unreachable. + +This is the Scheme equivalent of @code{scm_to_stringn}. +@end deffn + +@deffn {Scheme Procedure} pointer->string pointer [length] [encoding] +Return the string representing the C string pointed to by @var{pointer}. +If @var{length} is omitted or @code{-1}, the string is assumed to be +nul-terminated. Otherwise @var{length} is the number of bytes in memory +pointed to by @var{pointer}. The C string is assumed to be in the given +@var{encoding}, defaulting to the current locale encoding. + +This is the Scheme equivalent of @code{scm_from_stringn}. +@end deffn + +@cindex wrapped pointer types +Most object-oriented C libraries use pointers to specific data +structures to identify objects. It is useful in such cases to reify the +different pointer types as disjoint Scheme types. The +@code{define-wrapped-pointer-type} macro simplifies this. + +@deffn {Scheme Syntax} define-wrapped-pointer-type type-name pred wrap unwrap print +Define helper procedures to wrap pointer objects into Scheme objects +with a disjoint type. Specifically, this macro defines: + +@itemize +@item @var{pred}, a predicate for the new Scheme type; +@item @var{wrap}, a procedure that takes a pointer object and returns an +object that satisfies @var{pred}; +@item @var{unwrap}, which does the reverse. +@end itemize + +@var{wrap} preserves pointer identity, for two pointer objects @var{p1} +and @var{p2} that are @code{equal?}, @code{(eq? (@var{wrap} @var{p1}) +(@var{wrap} @var{p2})) @result{} #t}. + +Finally, @var{print} should name a user-defined procedure to print such +objects. The procedure is passed the wrapped object and a port to write +to. + +For example, assume we are wrapping a C library that defines a type, +@code{bottle_t}, and functions that can be passed @code{bottle_t *} +pointers to manipulate them. We could write: + +@example +(define-wrapped-pointer-type bottle + bottle? + wrap-bottle unwrap-bottle + (lambda (b p) + (format p "#<bottle of ~a ~x>" + (bottle-contents b) + (pointer-address (unwrap-bottle b))))) + +(define grab-bottle + ;; Wrapper for `bottle_t *grab (void)'. + (let ((grab (pointer->procedure '* + (dynamic-func "grab_bottle" libbottle) + '()))) + (lambda () + "Return a new bottle." + (wrap-bottle (grab))))) + +(define bottle-contents + ;; Wrapper for `const char *bottle_contents (bottle_t *)'. + (let ((contents (pointer->procedure '* + (dynamic-func "bottle_contents" + libbottle) + '(*)))) + (lambda (b) + "Return the contents of B." + (pointer->string (contents (unwrap-bottle b)))))) + +(write (grab-bottle)) +@result{} #<bottle of Ch@^ateau Haut-Brion 803d36> +@end example + +In this example, @code{grab-bottle} is guaranteed to return a genuine +@code{bottle} object satisfying @code{bottle?}. Likewise, +@code{bottle-contents} errors out when its argument is not a genuine +@code{bottle} object. +@end deffn + +Going back to the @code{scm_numptob} example above, here is how we can +read its value as a C @code{long} integer: + +@example +(use-modules (rnrs bytevectors)) + +(bytevector-uint-ref (pointer->bytevector numptob (sizeof long)) + 0 (native-endianness) + (sizeof long)) +@result{} 8 +@end example + +If we wanted to corrupt Guile's internal state, we could set +@code{scm_numptob} to another value; but we shouldn't, because that +variable is not meant to be set. Indeed this point applies more widely: +the C API is a dangerous place to be. Not only might setting a value +crash your program, simply accessing the data pointed to by a dangling +pointer or similar can prove equally disastrous. + +@node Foreign Structs +@subsubsection Foreign Structs + +Finally, one last note on foreign values before moving on to actually +calling foreign functions. Sometimes you need to deal with C structs, +which requires interpreting each element of the struct according to the +its type, offset, and alignment. Guile has some primitives to support +this. + +@deffn {Scheme Procedure} sizeof type +@deffnx {C Function} scm_sizeof (type) +Return the size of @var{type}, in bytes. + +@var{type} should be a valid C type, like @code{int}. +Alternately @var{type} may be the symbol @code{*}, in which +case the size of a pointer is returned. @var{type} may +also be a list of types, in which case the size of a +@code{struct} with ABI-conventional packing is returned. +@end deffn + +@deffn {Scheme Procedure} alignof type +@deffnx {C Function} scm_alignof (type) +Return the alignment of @var{type}, in bytes. + +@var{type} should be a valid C type, like @code{int}. +Alternately @var{type} may be the symbol @code{*}, in which +case the alignment of a pointer is returned. @var{type} may +also be a list of types, in which case the alignment of a +@code{struct} with ABI-conventional packing is returned. +@end deffn + +Guile also provides some convenience methods to pack and unpack foreign +pointers wrapping C structs. + +@deffn {Scheme Procedure} make-c-struct types vals +Create a foreign pointer to a C struct containing @var{vals} with types +@code{types}. + +@var{vals} and @code{types} should be lists of the same length. +@end deffn + +@deffn {Scheme Procedure} parse-c-struct foreign types +Parse a foreign pointer to a C struct, returning a list of values. + +@code{types} should be a list of C types. +@end deffn + +For example, to create and parse the equivalent of a @code{struct @{ +int64_t a; uint8_t b; @}}: + +@example +(parse-c-struct (make-c-struct (list int64 uint8) + (list 300 43)) + (list int64 uint8)) +@result{} (300 43) +@end example + +As yet, Guile only has convenience routines to support +conventionally-packed structs. But given the @code{bytevector->pointer} +and @code{pointer->bytevector} routines, one can create and parse +tightly packed structs and unions by hand. See the code for +@code{(system foreign)} for details. + + +@node Dynamic FFI +@subsection Dynamic FFI + +Of course, the land of C is not all nouns and no verbs: there are +functions too, and Guile allows you to call them. + +@deffn {Scheme Procedure} pointer->procedure return_type func_ptr arg_types @ + [#:return-errno?=#f] +@deffnx {C Function} scm_pointer_to_procedure (return_type, func_ptr, arg_types) +@deffnx {C Function} scm_pointer_to_procedure_with_errno (return_type, func_ptr, arg_types) + +Make a foreign function. + +Given the foreign void pointer @var{func_ptr}, its argument and +return types @var{arg_types} and @var{return_type}, return a +procedure that will pass arguments to the foreign function +and return appropriate values. + +@var{arg_types} should be a list of foreign types. +@code{return_type} should be a foreign type. @xref{Foreign Types}, for +more information on foreign types. + +If @var{return-errno?} is true, or when calling +@code{scm_pointer_to_procedure_with_errno}, the returned procedure will +return two values, with @code{errno} as the second value. +@end deffn + +Here is a better definition of @code{(math bessel)}: + +@example +(define-module (math bessel) + #:use-module (system foreign) + #:export (j0)) + +(define libm (dynamic-link "libm")) + +(define j0 + (pointer->procedure double + (dynamic-func "j0" libm) + (list double))) +@end example + +That's it! No C at all. + +Numeric arguments and return values from foreign functions are +represented as Scheme values. For example, @code{j0} in the above +example takes a Scheme number as its argument, and returns a Scheme +number. + +Pointers may be passed to and returned from foreign functions as well. +In that case the type of the argument or return value should be the +symbol @code{*}, indicating a pointer. For example, the following +code makes @code{memcpy} available to Scheme: + +@example +(define memcpy + (let ((this (dynamic-link))) + (pointer->procedure '* + (dynamic-func "memcpy" this) + (list '* '* size_t)))) +@end example + +To invoke @code{memcpy}, one must pass it foreign pointers: + +@example +(use-modules (rnrs bytevectors)) + +(define src-bits + (u8-list->bytevector '(0 1 2 3 4 5 6 7))) +(define src + (bytevector->pointer src-bits)) +(define dest + (bytevector->pointer (make-bytevector 16 0))) + +(memcpy dest src (bytevector-length src-bits)) + +(bytevector->u8-list (pointer->bytevector dest 16)) +@result{} (0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0) +@end example + +One may also pass structs as values, passing structs as foreign +pointers. @xref{Foreign Structs}, for more information on how to express +struct types and struct values. + +``Out'' arguments are passed as foreign pointers. The memory pointed to +by the foreign pointer is mutated in place. + +@example +;; struct timeval @{ +;; time_t tv_sec; /* seconds */ +;; suseconds_t tv_usec; /* microseconds */ +;; @}; +;; assuming fields are of type "long" + +(define gettimeofday + (let ((f (pointer->procedure + int + (dynamic-func "gettimeofday" (dynamic-link)) + (list '* '*))) + (tv-type (list long long))) + (lambda () + (let* ((timeval (make-c-struct tv-type (list 0 0))) + (ret (f timeval %null-pointer))) + (if (zero? ret) + (apply values (parse-c-struct timeval tv-type)) + (error "gettimeofday returned an error" ret)))))) + +(gettimeofday) +@result{} 1270587589 +@result{} 499553 +@end example + +As you can see, this interface to foreign functions is at a very low, +somewhat dangerous level@footnote{A contribution to Guile in the form of +a high-level FFI would be most welcome.}. + +@cindex callbacks +The FFI can also work in the opposite direction: making Scheme +procedures callable from C. This makes it possible to use Scheme +procedures as ``callbacks'' expected by C function. + +@deffn {Scheme Procedure} procedure->pointer return-type proc arg-types +@deffnx {C Function} scm_procedure_to_pointer (return_type, proc, arg_types) +Return a pointer to a C function of type @var{return-type} +taking arguments of types @var{arg-types} (a list) and +behaving as a proxy to procedure @var{proc}. Thus +@var{proc}'s arity, supported argument types, and return +type should match @var{return-type} and @var{arg-types}. +@end deffn + +As an example, here's how the C library's @code{qsort} array sorting +function can be made accessible to Scheme (@pxref{Array Sort Function, +@code{qsort},, libc, The GNU C Library Reference Manual}): + +@example +(define qsort! + (let ((qsort (pointer->procedure void + (dynamic-func "qsort" + (dynamic-link)) + (list '* size_t size_t '*)))) + (lambda (bv compare) + ;; Sort bytevector BV in-place according to comparison + ;; procedure COMPARE. + (let ((ptr (procedure->pointer int + (lambda (x y) + ;; X and Y are pointers so, + ;; for convenience, dereference + ;; them before calling COMPARE. + (compare (dereference-uint8* x) + (dereference-uint8* y))) + (list '* '*)))) + (qsort (bytevector->pointer bv) + (bytevector-length bv) 1 ;; we're sorting bytes + ptr))))) + +(define (dereference-uint8* ptr) + ;; Helper function: dereference the byte pointed to by PTR. + (let ((b (pointer->bytevector ptr 1))) + (bytevector-u8-ref b 0))) + +(define bv + ;; An unsorted array of bytes. + (u8-list->bytevector '(7 1 127 3 5 4 77 2 9 0))) + +;; Sort BV. +(qsort! bv (lambda (x y) (- x y))) + +;; Let's see what the sorted array looks like: +(bytevector->u8-list bv) +@result{} (0 1 2 3 4 5 7 9 77 127) +@end example + +And voil@`a! + +Note that @code{procedure->pointer} is not supported (and not defined) +on a few exotic architectures. Thus, user code may need to check +@code{(defined? 'procedure->pointer)}. Nevertheless, it is available on +many architectures, including (as of libffi 3.0.9) x86, ia64, SPARC, +PowerPC, ARM, and MIPS, to name a few. + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-i18n.texi b/doc/ref/api-i18n.texi new file mode 100644 index 000000000..0a27285b1 --- /dev/null +++ b/doc/ref/api-i18n.texi @@ -0,0 +1,629 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, +@c 2009, 2010, 2017 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Internationalization +@section Support for Internationalization + +@cindex internationalization +@cindex i18n + +Guile provides internationalization@footnote{For concision and style, +programmers often like to refer to internationalization as ``i18n''.} +support for Scheme programs in two ways. First, procedures to +manipulate text and data in a way that conforms to particular cultural +conventions (i.e., in a ``locale-dependent'' way) are provided in the +@code{(ice-9 i18n)}. Second, Guile allows the use of GNU +@code{gettext} to translate program message strings. + +@menu +* i18n Introduction:: Introduction to Guile's i18n support. +* Text Collation:: Sorting strings and characters. +* Character Case Mapping:: Case mapping. +* Number Input and Output:: Parsing and printing numbers. +* Accessing Locale Information:: Detailed locale information. +* Gettext Support:: Translating message strings. +@end menu + + +@node i18n Introduction, Text Collation, Internationalization, Internationalization +@subsection Internationalization with Guile + +In order to make use of the functions described thereafter, the +@code{(ice-9 i18n)} module must be imported in the usual way: + +@example +(use-modules (ice-9 i18n)) +@end example + +@cindex cultural conventions + +The @code{(ice-9 i18n)} module provides procedures to manipulate text +and other data in a way that conforms to the cultural conventions +chosen by the user. Each region of the world or language has its own +customs to, for instance, represent real numbers, classify characters, +collate text, etc. All these aspects comprise the so-called +``cultural conventions'' of that region or language. + +@cindex locale +@cindex locale category + +Computer systems typically refer to a set of cultural conventions as a +@dfn{locale}. For each particular aspect that comprise those cultural +conventions, a @dfn{locale category} is defined. For instance, the +way characters are classified is defined by the @code{LC_CTYPE} +category, while the language in which program messages are issued to +the user is defined by the @code{LC_MESSAGES} category +(@pxref{Locales, General Locale Information} for details). + +@cindex locale object + +The procedures provided by this module allow the development of +programs that adapt automatically to any locale setting. As we will +see later, many of these procedures can optionally take a @dfn{locale +object} argument. This additional argument defines the locale +settings that must be followed by the invoked procedure. When it is +omitted, then the current locale settings of the process are followed +(@pxref{Locales, @code{setlocale}}). + +The following procedures allow the manipulation of such locale +objects. + +@deffn {Scheme Procedure} make-locale category-list locale-name [base-locale] +@deffnx {C Function} scm_make_locale (category_list, locale_name, base_locale) +Return a reference to a data structure representing a set of locale +datasets. @var{locale-name} should be a string denoting a particular +locale (e.g., @code{"aa_DJ"}) and @var{category-list} should be either +a list of locale categories or a single category as used with +@code{setlocale} (@pxref{Locales, @code{setlocale}}). Optionally, if +@code{base-locale} is passed, it should be a locale object denoting +settings for categories not listed in @var{category-list}. + +The following invocation creates a locale object that combines the use +of Swedish for messages and character classification with the +default settings for the other categories (i.e., the settings of the +default @code{C} locale which usually represents conventions in use in +the USA): + +@example +(make-locale (list LC_MESSAGES LC_CTYPE) "sv_SE") +@end example + +The following example combines the use of Esperanto messages and +conventions with monetary conventions from Croatia: + +@example +(make-locale LC_MONETARY "hr_HR" + (make-locale LC_ALL "eo_EO")) +@end example + +A @code{system-error} exception (@pxref{Handling Errors}) is raised by +@code{make-locale} when @var{locale-name} does not match any of the +locales compiled on the system. Note that on non-GNU systems, this +error may be raised later, when the locale object is actually used. + +@end deffn + +@deffn {Scheme Procedure} locale? obj +@deffnx {C Function} scm_locale_p (obj) +Return true if @var{obj} is a locale object. +@end deffn + +@defvr {Scheme Variable} %global-locale +@defvrx {C Variable} scm_global_locale +This variable is bound to a locale object denoting the current process +locale as installed using @code{setlocale ()} (@pxref{Locales}). It +may be used like any other locale object, including as a third +argument to @code{make-locale}, for instance. +@end defvr + + +@node Text Collation, Character Case Mapping, i18n Introduction, Internationalization +@subsection Text Collation + +The following procedures provide support for text collation, i.e., +locale-dependent string and character sorting. + +@deffn {Scheme Procedure} string-locale<? s1 s2 [locale] +@deffnx {C Function} scm_string_locale_lt (s1, s2, locale) +@deffnx {Scheme Procedure} string-locale>? s1 s2 [locale] +@deffnx {C Function} scm_string_locale_gt (s1, s2, locale) +@deffnx {Scheme Procedure} string-locale-ci<? s1 s2 [locale] +@deffnx {C Function} scm_string_locale_ci_lt (s1, s2, locale) +@deffnx {Scheme Procedure} string-locale-ci>? s1 s2 [locale] +@deffnx {C Function} scm_string_locale_ci_gt (s1, s2, locale) +Compare strings @var{s1} and @var{s2} in a locale-dependent way. If +@var{locale} is provided, it should be locale object (as returned by +@code{make-locale}) and will be used to perform the comparison; +otherwise, the current system locale is used. For the @code{-ci} +variants, the comparison is made in a case-insensitive way. +@end deffn + +@deffn {Scheme Procedure} string-locale-ci=? s1 s2 [locale] +@deffnx {C Function} scm_string_locale_ci_eq (s1, s2, locale) +Compare strings @var{s1} and @var{s2} in a case-insensitive, and +locale-dependent way. If @var{locale} is provided, it should be +a locale object (as returned by @code{make-locale}) and will be used to +perform the comparison; otherwise, the current system locale is used. +@end deffn + +@deffn {Scheme Procedure} char-locale<? c1 c2 [locale] +@deffnx {C Function} scm_char_locale_lt (c1, c2, locale) +@deffnx {Scheme Procedure} char-locale>? c1 c2 [locale] +@deffnx {C Function} scm_char_locale_gt (c1, c2, locale) +@deffnx {Scheme Procedure} char-locale-ci<? c1 c2 [locale] +@deffnx {C Function} scm_char_locale_ci_lt (c1, c2, locale) +@deffnx {Scheme Procedure} char-locale-ci>? c1 c2 [locale] +@deffnx {C Function} scm_char_locale_ci_gt (c1, c2, locale) +Compare characters @var{c1} and @var{c2} according to either +@var{locale} (a locale object as returned by @code{make-locale}) or +the current locale. For the @code{-ci} variants, the comparison is +made in a case-insensitive way. +@end deffn + +@deffn {Scheme Procedure} char-locale-ci=? c1 c2 [locale] +@deffnx {C Function} scm_char_locale_ci_eq (c1, c2, locale) +Return true if character @var{c1} is equal to @var{c2}, in a case +insensitive way according to @var{locale} or to the current locale. +@end deffn + +@node Character Case Mapping, Number Input and Output, Text Collation, Internationalization +@subsection Character Case Mapping + +The procedures below provide support for ``character case mapping'', +i.e., to convert characters or strings to their upper-case or +lower-case equivalent. Note that SRFI-13 provides procedures that +look similar (@pxref{Alphabetic Case Mapping}). However, the SRFI-13 +procedures are locale-independent. Therefore, they do not take into +account specificities of the customs in use in a particular language +or region of the world. For instance, while most languages using the +Latin alphabet map lower-case letter ``i'' to upper-case letter ``I'', +Turkish maps lower-case ``i'' to ``Latin capital letter I with dot +above''. The following procedures allow programmers to provide +idiomatic character mapping. + +@deffn {Scheme Procedure} char-locale-downcase chr [locale] +@deffnx {C Function} scm_char_locale_upcase (chr, locale) +Return the lowercase character that corresponds to @var{chr} according +to either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} char-locale-upcase chr [locale] +@deffnx {C Function} scm_char_locale_downcase (chr, locale) +Return the uppercase character that corresponds to @var{chr} according +to either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} char-locale-titlecase chr [locale] +@deffnx {C Function} scm_char_locale_titlecase (chr, locale) +Return the titlecase character that corresponds to @var{chr} according +to either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} string-locale-upcase str [locale] +@deffnx {C Function} scm_string_locale_upcase (str, locale) +Return a new string that is the uppercase version of @var{str} +according to either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} string-locale-downcase str [locale] +@deffnx {C Function} scm_string_locale_downcase (str, locale) +Return a new string that is the down-case version of @var{str} +according to either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} string-locale-titlecase str [locale] +@deffnx {C Function} scm_string_locale_titlecase (str, locale) +Return a new string that is the titlecase version of @var{str} +according to either @var{locale} or the current locale. +@end deffn + +@node Number Input and Output, Accessing Locale Information, Character Case Mapping, Internationalization +@subsection Number Input and Output + +The following procedures allow programs to read and write numbers +written according to a particular locale. As an example, in English, +``ten thousand and a half'' is usually written @code{10,000.5} while +in French it is written @code{10 000,5}. These procedures allow such +differences to be taken into account. + +@findex strtod +@deffn {Scheme Procedure} locale-string->integer str [base [locale]] +@deffnx {C Function} scm_locale_string_to_integer (str, base, locale) +Convert string @var{str} into an integer according to either +@var{locale} (a locale object as returned by @code{make-locale}) or +the current process locale. If @var{base} is specified, then it +determines the base of the integer being read (e.g., @code{16} for an +hexadecimal number, @code{10} for a decimal number); by default, +decimal numbers are read. Return two values (@pxref{Multiple +Values}): an integer (on success) or @code{#f}, and the number of +characters read from @var{str} (@code{0} on failure). + +This function is based on the C library's @code{strtol} function +(@pxref{Parsing of Integers, @code{strtol},, libc, The GNU C Library +Reference Manual}). +@end deffn + +@findex strtod +@deffn {Scheme Procedure} locale-string->inexact str [locale] +@deffnx {C Function} scm_locale_string_to_inexact (str, locale) +Convert string @var{str} into an inexact number according to either +@var{locale} (a locale object as returned by @code{make-locale}) or +the current process locale. Return two values (@pxref{Multiple +Values}): an inexact number (on success) or @code{#f}, and the number +of characters read from @var{str} (@code{0} on failure). + +This function is based on the C library's @code{strtod} function +(@pxref{Parsing of Floats, @code{strtod},, libc, The GNU C Library +Reference Manual}). +@end deffn + +@deffn {Scheme Procedure} number->locale-string number [fraction-digits [locale]] +Convert @var{number} (an inexact) into a string according to the +cultural conventions of either @var{locale} (a locale object) or the +current locale. By default, print as many fractional digits as +necessary, up to an upper bound. Optionally, @var{fraction-digits} may +be bound to an integer specifying the number of fractional digits to be +displayed. +@end deffn + +@deffn {Scheme Procedure} monetary-amount->locale-string amount intl? [locale] +Convert @var{amount} (an inexact denoting a monetary amount) into a +string according to the cultural conventions of either @var{locale} (a +locale object) or the current locale. If @var{intl?} is true, then +the international monetary format for the given locale is used +(@pxref{Currency Symbol, international and locale monetary formats,, +libc, The GNU C Library Reference Manual}). +@end deffn + + +@node Accessing Locale Information, Gettext Support, Number Input and Output, Internationalization +@subsection Accessing Locale Information + +@findex nl_langinfo +@cindex low-level locale information +It is sometimes useful to obtain very specific information about a +locale such as the word it uses for days or months, its format for +representing floating-point figures, etc. The @code{(ice-9 i18n)} +module provides support for this in a way that is similar to the libc +functions @code{nl_langinfo ()} and @code{localeconv ()} +(@pxref{Locale Information, accessing locale information from C,, +libc, The GNU C Library Reference Manual}). The available functions +are listed below. + +@deffn {Scheme Procedure} locale-encoding [locale] +Return the name of the encoding (a string whose interpretation is +system-dependent) of either @var{locale} or the current locale. +@end deffn + +The following functions deal with dates and times. + +@deffn {Scheme Procedure} locale-day day [locale] +@deffnx {Scheme Procedure} locale-day-short day [locale] +@deffnx {Scheme Procedure} locale-month month [locale] +@deffnx {Scheme Procedure} locale-month-short month [locale] +Return the word (a string) used in either @var{locale} or the current +locale to name the day (or month) denoted by @var{day} (or +@var{month}), an integer between 1 and 7 (or 1 and 12). The +@code{-short} variants provide an abbreviation instead of a full name. +@end deffn + +@deffn {Scheme Procedure} locale-am-string [locale] +@deffnx {Scheme Procedure} locale-pm-string [locale] +Return a (potentially empty) string that is used to denote @i{ante +meridiem} (or @i{post meridiem}) hours in 12-hour format. +@end deffn + +@deffn {Scheme Procedure} locale-date+time-format [locale] +@deffnx {Scheme Procedure} locale-date-format [locale] +@deffnx {Scheme Procedure} locale-time-format [locale] +@deffnx {Scheme Procedure} locale-time+am/pm-format [locale] +@deffnx {Scheme Procedure} locale-era-date-format [locale] +@deffnx {Scheme Procedure} locale-era-date+time-format [locale] +@deffnx {Scheme Procedure} locale-era-time-format [locale] +These procedures return format strings suitable to @code{strftime} +(@pxref{Time}) that may be used to display (part of) a date/time +according to certain constraints and to the conventions of either +@var{locale} or the current locale (@pxref{The Elegant and Fast Way, +the @code{nl_langinfo ()} items,, libc, The GNU C Library Reference +Manual}). +@end deffn + +@deffn {Scheme Procedure} locale-era [locale] +@deffnx {Scheme Procedure} locale-era-year [locale] +These functions return, respectively, the era and the year of the +relevant era used in @var{locale} or the current locale. Most locales +do not define this value. In this case, the empty string is returned. +An example of a locale that does define this value is the Japanese +one. +@end deffn + +The following procedures give information about number representation. + +@deffn {Scheme Procedure} locale-decimal-point [locale] +@deffnx {Scheme Procedure} locale-thousands-separator [locale] +These functions return a string denoting the representation of the +decimal point or that of the thousand separator (respectively) for +either @var{locale} or the current locale. +@end deffn + +@deffn {Scheme Procedure} locale-digit-grouping [locale] +Return a (potentially circular) list of integers denoting how digits +of the integer part of a number are to be grouped, starting at the +decimal point and going to the left. The list contains integers +indicating the size of the successive groups, from right to left. If +the list is non-circular, then no grouping occurs for digits beyond +the last group. + +For instance, if the returned list is a circular list that contains +only @code{3} and the thousand separator is @code{","} (as is the case +with English locales), then the number @code{12345678} should be +printed @code{12,345,678}. +@end deffn + +The following procedures deal with the representation of monetary +amounts. Some of them take an additional @var{intl?} argument (a +boolean) that tells whether the international or local monetary +conventions for the given locale are to be used. + +@deffn {Scheme Procedure} locale-monetary-decimal-point [locale] +@deffnx {Scheme Procedure} locale-monetary-thousands-separator [locale] +@deffnx {Scheme Procedure} locale-monetary-grouping [locale] +These are the monetary counterparts of the above procedures. These +procedures apply to monetary amounts. +@end deffn + +@deffn {Scheme Procedure} locale-currency-symbol intl? [locale] +Return the currency symbol (a string) of either @var{locale} or the +current locale. + +The following example illustrates the difference between the local and +international monetary formats: + +@example +(define us (make-locale LC_MONETARY "en_US")) +(locale-currency-symbol #f us) +@result{} "-$" +(locale-currency-symbol #t us) +@result{} "USD " +@end example +@end deffn + +@deffn {Scheme Procedure} locale-monetary-fractional-digits intl? [locale] +Return the number of fractional digits to be used when printing +monetary amounts according to either @var{locale} or the current +locale. If the locale does not specify it, then @code{#f} is +returned. +@end deffn + +@deffn {Scheme Procedure} locale-currency-symbol-precedes-positive? intl? [locale] +@deffnx {Scheme Procedure} locale-currency-symbol-precedes-negative? intl? [locale] +@deffnx {Scheme Procedure} locale-positive-separated-by-space? intl? [locale] +@deffnx {Scheme Procedure} locale-negative-separated-by-space? intl? [locale] +These procedures return a boolean indicating whether the currency +symbol should precede a positive/negative number, and whether a +whitespace should be inserted between the currency symbol and a +positive/negative amount. +@end deffn + +@deffn {Scheme Procedure} locale-monetary-positive-sign [locale] +@deffnx {Scheme Procedure} locale-monetary-negative-sign [locale] +Return a string denoting the positive (respectively negative) sign +that should be used when printing a monetary amount. +@end deffn + +@deffn {Scheme Procedure} locale-positive-sign-position +@deffnx {Scheme Procedure} locale-negative-sign-position +These functions return a symbol telling where a sign of a +positive/negative monetary amount is to appear when printing it. The +possible values are: + +@table @code +@item parenthesize +The currency symbol and quantity should be surrounded by parentheses. +@item sign-before +Print the sign string before the quantity and currency symbol. +@item sign-after +Print the sign string after the quantity and currency symbol. +@item sign-before-currency-symbol +Print the sign string right before the currency symbol. +@item sign-after-currency-symbol +Print the sign string right after the currency symbol. +@item unspecified +Unspecified. We recommend you print the sign after the currency +symbol. +@end table + +@end deffn + +Finally, the two following procedures may be helpful when programming +user interfaces: + +@deffn {Scheme Procedure} locale-yes-regexp [locale] +@deffnx {Scheme Procedure} locale-no-regexp [locale] +Return a string that can be used as a regular expression to recognize +a positive (respectively, negative) response to a yes/no question. +For the C locale, the default values are typically @code{"^[yY]"} and +@code{"^[nN]"}, respectively. + +Here is an example: + +@example +(use-modules (ice-9 rdelim)) +(format #t "Does Guile rock?~%") +(let lp ((answer (read-line))) + (cond ((string-match (locale-yes-regexp) answer) + (format #t "High fives!~%")) + ((string-match (locale-no-regexp) answer) + (format #t "How about now? Does it rock yet?~%") + (lp (read-line))) + (else + (format #t "What do you mean?~%") + (lp (read-line))))) +@end example + +For an internationalized yes/no string output, @code{gettext} should +be used (@pxref{Gettext Support}). +@end deffn + +Example uses of some of these functions are the implementation of the +@code{number->locale-string} and @code{monetary-amount->locale-string} +procedures (@pxref{Number Input and Output}), as well as that the +SRFI-19 date and time conversion to/from strings (@pxref{SRFI-19}). + + +@node Gettext Support, , Accessing Locale Information, Internationalization +@subsection Gettext Support + +Guile provides an interface to GNU @code{gettext} for translating +message strings (@pxref{Introduction,,, gettext, GNU @code{gettext} +utilities}). + +Messages are collected in domains, so different libraries and programs +maintain different message catalogues. The @var{domain} parameter in +the functions below is a string (it becomes part of the message +catalog filename). + +When @code{gettext} is not available, or if Guile was configured +@samp{--without-nls}, dummy functions doing no translation are +provided. When @code{gettext} support is available in Guile, the +@code{i18n} feature is provided (@pxref{Feature Tracking}). + +@deffn {Scheme Procedure} gettext msg [domain [category]] +@deffnx {C Function} scm_gettext (msg, domain, category) +Return the translation of @var{msg} in @var{domain}. @var{domain} is +optional and defaults to the domain set through @code{textdomain} +below. @var{category} is optional and defaults to @code{LC_MESSAGES} +(@pxref{Locales}). + +Normal usage is for @var{msg} to be a literal string. +@command{xgettext} can extract those from the source to form a message +catalogue ready for translators (@pxref{xgettext Invocation,, Invoking +the @command{xgettext} Program, gettext, GNU @code{gettext} +utilities}). + +@example +(display (gettext "You are in a maze of twisty passages.")) +@end example + +@code{_} is a commonly used shorthand, an application can make that an +alias for @code{gettext}. Or a library can make a definition that +uses its specific @var{domain} (so an application can change the +default without affecting the library). + +@example +(define (_ msg) (gettext msg "mylibrary")) +(display (_ "File not found.")) +@end example + +@code{_} is also a good place to perhaps strip disambiguating extra +text from the message string, as for instance in @ref{GUI program +problems,, How to use @code{gettext} in GUI programs, gettext, GNU +@code{gettext} utilities}. +@end deffn + +@deffn {Scheme Procedure} ngettext msg msgplural n [domain [category]] +@deffnx {C Function} scm_ngettext (msg, msgplural, n, domain, category) +Return the translation of @var{msg}/@var{msgplural} in @var{domain}, +with a plural form chosen appropriately for the number @var{n}. +@var{domain} is optional and defaults to the domain set through +@code{textdomain} below. @var{category} is optional and defaults to +@code{LC_MESSAGES} (@pxref{Locales}). + +@var{msg} is the singular form, and @var{msgplural} the plural. When +no translation is available, @var{msg} is used if @math{@var{n} = 1}, +or @var{msgplural} otherwise. When translated, the message catalogue +can have a different rule, and can have more than two possible forms. + +As per @code{gettext} above, normal usage is for @var{msg} and +@var{msgplural} to be literal strings, since @command{xgettext} can +extract them from the source to build a message catalogue. For +example, + +@example +(define (done n) + (format #t (ngettext "~a file processed\n" + "~a files processed\n" n) + n)) + +(done 1) @print{} 1 file processed +(done 3) @print{} 3 files processed +@end example + +It's important to use @code{ngettext} rather than plain @code{gettext} +for plurals, since the rules for singular and plural forms in English +are not the same in other languages. Only @code{ngettext} will allow +translators to give correct forms (@pxref{Plural forms,, Additional +functions for plural forms, gettext, GNU @code{gettext} utilities}). +@end deffn + +@deffn {Scheme Procedure} textdomain [domain] +@deffnx {C Function} scm_textdomain (domain) +Get or set the default gettext domain. When called with no parameter +the current domain is returned. When called with a parameter, +@var{domain} is set as the current domain, and that new value +returned. For example, + +@example +(textdomain "myprog") +@result{} "myprog" +@end example +@end deffn + +@deffn {Scheme Procedure} bindtextdomain domain [directory] +@deffnx {C Function} scm_bindtextdomain (domain, directory) +Get or set the directory under which to find message files for +@var{domain}. When called without a @var{directory} the current +setting is returned. When called with a @var{directory}, +@var{directory} is set for @var{domain} and that new setting returned. +For example, + +@example +(bindtextdomain "myprog" "/my/tree/share/locale") +@result{} "/my/tree/share/locale" +@end example + +When using Autoconf/Automake, an application should arrange for the +configured @code{localedir} to get into the program (by substituting, +or by generating a config file) and set that for its domain. This +ensures the catalogue can be found even when installed in a +non-standard location. +@end deffn + +@deffn {Scheme Procedure} bind-textdomain-codeset domain [encoding] +@deffnx {C Function} scm_bind_textdomain_codeset (domain, encoding) +Get or set the text encoding to be used by @code{gettext} for messages +from @var{domain}. @var{encoding} is a string, the name of a coding +system, for instance @nicode{"8859_1"}. (On a Unix/POSIX system the +@command{iconv} program can list all available encodings.) + +When called without an @var{encoding} the current setting is returned, +or @code{#f} if none yet set. When called with an @var{encoding}, it +is set for @var{domain} and that new setting returned. For example, + +@example +(bind-textdomain-codeset "myprog") +@result{} #f +(bind-textdomain-codeset "myprog" "latin-9") +@result{} "latin-9" +@end example + +The encoding requested can be different from the translated data file, +messages will be recoded as necessary. But note that when there is no +translation, @code{gettext} returns its @var{msg} unchanged, ie.@: +without any recoding. For that reason source message strings are best +as plain ASCII. + +Currently Guile has no understanding of multi-byte characters, and +string functions won't recognise character boundaries in multi-byte +strings. An application will at least be able to pass such strings +through to some output though. Perhaps this will change in the +future. +@end deffn + +@c Local Variables: +@c TeX-master: "guile.texi" +@c ispell-local-dictionary: "american" +@c End: diff --git a/doc/ref/api-init.texi b/doc/ref/api-init.texi new file mode 100644 index 000000000..f9714c3b6 --- /dev/null +++ b/doc/ref/api-init.texi @@ -0,0 +1,110 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + + +@node Initialization +@section Initializing Guile +@cindex Initializing Guile + +Each thread that wants to use functions from the Guile API needs to +put itself into guile mode with either @code{scm_with_guile} or +@code{scm_init_guile}. The global state of Guile is initialized +automatically when the first thread enters guile mode. + +When a thread wants to block outside of a Guile API function, it +should leave guile mode temporarily with @code{scm_without_guile}, +@xref{Blocking}. + +Threads that are created by @code{call-with-new-thread} or +@code{scm_spawn_thread} start out in guile mode so you don't need to +initialize them. + +@deftypefn {C Function} {void *} scm_with_guile (void *(*func)(void *), void *data) +Call @var{func}, passing it @var{data} and return what @var{func} +returns. While @var{func} is running, the current thread is in guile +mode and can thus use the Guile API. + +When @code{scm_with_guile} is called from guile mode, the thread remains +in guile mode when @code{scm_with_guile} returns. + +Otherwise, it puts the current thread into guile mode and, if needed, +gives it a Scheme representation that is contained in the list returned +by @code{all-threads}, for example. This Scheme representation is not +removed when @code{scm_with_guile} returns so that a given thread is +always represented by the same Scheme value during its lifetime, if at +all. + +When this is the first thread that enters guile mode, the global state +of Guile is initialized before calling @code{func}. + +The function @var{func} is called via +@code{scm_with_continuation_barrier}; thus, @code{scm_with_guile} +returns exactly once. + +When @code{scm_with_guile} returns, the thread is no longer in guile +mode (except when @code{scm_with_guile} was called from guile mode, see +above). Thus, only @code{func} can store @code{SCM} variables on the +stack and be sure that they are protected from the garbage collector. +See @code{scm_init_guile} for another approach at initializing Guile +that does not have this restriction. + +It is OK to call @code{scm_with_guile} while a thread has temporarily +left guile mode via @code{scm_without_guile}. It will then simply +temporarily enter guile mode again. +@end deftypefn + +@deftypefn {C Function} void scm_init_guile () +Arrange things so that all of the code in the current thread executes as +if from within a call to @code{scm_with_guile}. That is, all functions +called by the current thread can assume that @code{SCM} values on their +stack frames are protected from the garbage collector (except when the +thread has explicitly left guile mode, of course). + +When @code{scm_init_guile} is called from a thread that already has been +in guile mode once, nothing happens. This behavior matters when you +call @code{scm_init_guile} while the thread has only temporarily left +guile mode: in that case the thread will not be in guile mode after +@code{scm_init_guile} returns. Thus, you should not use +@code{scm_init_guile} in such a scenario. + +When a uncaught throw happens in a thread that has been put into guile +mode via @code{scm_init_guile}, a short message is printed to the +current error port and the thread is exited via @code{scm_pthread_exit +(NULL)}. No restrictions are placed on continuations. + +The function @code{scm_init_guile} might not be available on all +platforms since it requires some stack-bounds-finding magic that might +not have been ported to all platforms that Guile runs on. Thus, if you +can, it is better to use @code{scm_with_guile} or its variation +@code{scm_boot_guile} instead of this function. +@end deftypefn + +@deftypefn {C Function} void scm_boot_guile (int @var{argc}, char **@var{argv}, void (*@var{main_func}) (void *@var{data}, int @var{argc}, char **@var{argv}), void *@var{data}) +Enter guile mode as with @code{scm_with_guile} and call @var{main_func}, +passing it @var{data}, @var{argc}, and @var{argv} as indicated. When +@var{main_func} returns, @code{scm_boot_guile} calls @code{exit (0)}; +@code{scm_boot_guile} never returns. If you want some other exit value, +have @var{main_func} call @code{exit} itself. If you don't want to exit +at all, use @code{scm_with_guile} instead of @code{scm_boot_guile}. + +The function @code{scm_boot_guile} arranges for the Scheme +@code{command-line} function to return the strings given by @var{argc} +and @var{argv}. If @var{main_func} modifies @var{argc} or @var{argv}, +it should call @code{scm_set_program_arguments} with the final list, so +Scheme code will know which arguments have been processed +(@pxref{Runtime Environment}). +@end deftypefn + +@deftypefn {C Function} void scm_shell (int @var{argc}, char **@var{argv}) +Process command-line arguments in the manner of the @code{guile} +executable. This includes loading the normal Guile initialization +files, interacting with the user or running any scripts or expressions +specified by @code{-s} or @code{-e} options, and then exiting. +@xref{Invoking Guile}, for more details. + +Since this function does not return, you must do all +application-specific initialization before calling this function. +@end deftypefn diff --git a/doc/ref/api-io.texi b/doc/ref/api-io.texi new file mode 100644 index 000000000..24890a12e --- /dev/null +++ b/doc/ref/api-io.texi @@ -0,0 +1,1905 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, +@c 2010, 2011, 2013, 2016 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Input and Output +@section Input and Output + +@menu +* Ports:: What's a port? +* Binary I/O:: Reading and writing bytes. +* Encoding:: Characters as bytes. +* Textual I/O:: Reading and writing characters. +* Simple Output:: Simple syntactic sugar solution. +* Buffering:: Controlling when data is written to ports. +* Random Access:: Moving around a random access port. +* Line/Delimited:: Read and write lines or delimited text. +* Default Ports:: Defaults for input, output and errors. +* Port Types:: Types of port and how to make them. +* Venerable Port Interfaces:: Procedures from the last millenium. +* Using Ports from C:: Nice interfaces for C. +* I/O Extensions:: Implementing new port types in C. +* Non-Blocking I/O:: How Guile deals with EWOULDBLOCK. +* BOM Handling:: Handling of Unicode byte order marks. +@end menu + + +@node Ports +@subsection Ports +@cindex Port + +Ports are the way that Guile performs input and output. Guile can read +in characters or bytes from an @dfn{input port}, or write them out to an +@dfn{output port}. Some ports support both interfaces. + +There are a number of different port types implemented in Guile. File +ports provide input and output over files, as you might imagine. For +example, we might display a string to a file like this: + +@example +(let ((port (open-output-file "foo.txt"))) + (display "Hello, world!\n" port) + (close-port port)) +@end example + +There are also string ports, for taking input from a string, or +collecting output to a string; bytevector ports, for doing the same but +using a bytevector as a source or sink of data; and soft ports, for +arranging to call Scheme functions to provide input or handle output. +@xref{Port Types}. + +Ports should be @dfn{closed} when they are not needed by calling +@code{close-port} on them, as in the example above. This will make sure +that any pending output is successfully written out to disk, in the case +of a file port, or otherwise to whatever mutable store is backed by the +port. Any error that occurs while writing out that buffered data would +also be raised promptly at the @code{close-port}, and not later when the +port is closed by the garbage collector. @xref{Buffering}, for more on +buffered output. + +Closing a port also releases any precious resource the file might have. +Usually in Scheme a programmer doesn't have to clean up after their data +structures (@pxref{Memory Management}), but most systems have strict +limits on how many files can be open, both on a per-process and a +system-wide basis. A program that uses many files should take care not +to hit those limits. The same applies to similar system resources such +as pipes and sockets. + +Indeed for these reasons the above example is not the most idiomatic way +to use ports. It is more common to acquire ports via procedures like +@code{call-with-output-file}, which handle the @code{close-port} +automatically: + +@example +(call-with-output-file "foo.txt" + (lambda (port) + (display "Hello, world!\n" port))) +@end example + +Finally, all ports have associated input and output buffers, as +appropriate. Buffering is a common strategy to limit the overhead of +small reads and writes: without buffering, each character fetched from a +file would involve at least one call into the kernel, and maybe more +depending on the character and the encoding. Instead, Guile will batch +reads and writes into internal buffers. However, sometimes you want to +make output on a port show up immediately. @xref{Buffering}, for more +on interfaces to control port buffering. + +@deffn {Scheme Procedure} port? x +@deffnx {C Function} scm_port_p (x) +Return a boolean indicating whether @var{x} is a port. +@end deffn + +@rnindex input-port? +@deffn {Scheme Procedure} input-port? x +@deffnx {C Function} scm_input_port_p (x) +Return @code{#t} if @var{x} is an input port, otherwise return +@code{#f}. Any object satisfying this predicate also satisfies +@code{port?}. +@end deffn + +@rnindex output-port? +@deffn {Scheme Procedure} output-port? x +@deffnx {C Function} scm_output_port_p (x) +Return @code{#t} if @var{x} is an output port, otherwise return +@code{#f}. Any object satisfying this predicate also satisfies +@code{port?}. +@end deffn + +@cindex Closing ports +@cindex Port, close +@deffn {Scheme Procedure} close-port port +@deffnx {C Function} scm_close_port (port) +Close the specified port object. Return @code{#t} if it successfully +closes a port or @code{#f} if it was already closed. An exception may +be raised if an error occurs, for example when flushing buffered output. +@xref{Buffering}, for more on buffered output. @xref{Ports and File +Descriptors, close}, for a procedure which can close file descriptors. +@end deffn + +@deffn {Scheme Procedure} port-closed? port +@deffnx {C Function} scm_port_closed_p (port) +Return @code{#t} if @var{port} is closed or @code{#f} if it is +open. +@end deffn + + +@node Binary I/O +@subsection Binary I/O + +Guile's ports are fundamentally binary in nature: at the lowest level, +they work on bytes. This section describes Guile's core binary I/O +operations. @xref{Textual I/O}, for input and output of strings and +characters. + +To use these routines, first include the binary I/O module: + +@example +(use-modules (ice-9 binary-ports)) +@end example + +Note that although this module's name suggests that binary ports are +some different kind of port, that's not the case: all ports in Guile are +both binary and textual ports. + +@cindex binary input +@deffn {Scheme Procedure} get-u8 port +@deffnx {C Function} scm_get_u8 (port) +Return an octet read from @var{port}, an input port, blocking as +necessary, or the end-of-file object. +@end deffn + +@deffn {Scheme Procedure} lookahead-u8 port +@deffnx {C Function} scm_lookahead_u8 (port) +Like @code{get-u8} but does not update @var{port}'s position to point +past the octet. +@end deffn + +The end-of-file object is unlike any other kind of object: it's not a +pair, a symbol, or anything else. To check if a value is the +end-of-file object, use the @code{eof-object?} predicate. + +@rnindex eof-object? +@cindex End of file object +@deffn {Scheme Procedure} eof-object? x +@deffnx {C Function} scm_eof_object_p (x) +Return @code{#t} if @var{x} is an end-of-file object, or @code{#f} +otherwise. +@end deffn + +Note that unlike other procedures in this module, @code{eof-object?} is +defined in the default environment. + +@deffn {Scheme Procedure} get-bytevector-n port count +@deffnx {C Function} scm_get_bytevector_n (port, count) +Read @var{count} octets from @var{port}, blocking as necessary and +return a bytevector containing the octets read. If fewer bytes are +available, a bytevector smaller than @var{count} is returned. +@end deffn + +@deffn {Scheme Procedure} get-bytevector-n! port bv start count +@deffnx {C Function} scm_get_bytevector_n_x (port, bv, start, count) +Read @var{count} bytes from @var{port} and store them in @var{bv} +starting at index @var{start}. Return either the number of bytes +actually read or the end-of-file object. +@end deffn + +@deffn {Scheme Procedure} get-bytevector-some port +@deffnx {C Function} scm_get_bytevector_some (port) +Read from @var{port}, blocking as necessary, until bytes are available +or an end-of-file is reached. Return either the end-of-file object or a +new bytevector containing some of the available bytes (at least one), +and update the port position to point just past these bytes. +@end deffn + +@deffn {Scheme Procedure} get-bytevector-all port +@deffnx {C Function} scm_get_bytevector_all (port) +Read from @var{port}, blocking as necessary, until the end-of-file is +reached. Return either a new bytevector containing the data read or the +end-of-file object (if no data were available). +@end deffn + +@deffn {Scheme Procedure} unget-bytevector port bv [start [count]] +@deffnx {C Function} scm_unget_bytevector (port, bv, start, count) +Place the contents of @var{bv} in @var{port}, optionally starting at +index @var{start} and limiting to @var{count} octets, so that its bytes +will be read from left-to-right as the next bytes from @var{port} during +subsequent read operations. If called multiple times, the unread bytes +will be read again in last-in first-out order. +@end deffn + +@cindex binary output +To perform binary output on a port, use @code{put-u8} or +@code{put-bytevector}. + +@deffn {Scheme Procedure} put-u8 port octet +@deffnx {C Function} scm_put_u8 (port, octet) +Write @var{octet}, an integer in the 0--255 range, to @var{port}, a +binary output port. +@end deffn + +@deffn {Scheme Procedure} put-bytevector port bv [start [count]] +@deffnx {C Function} scm_put_bytevector (port, bv, start, count) +Write the contents of @var{bv} to @var{port}, optionally starting at +index @var{start} and limiting to @var{count} octets. +@end deffn + +@node Encoding +@subsection Encoding + +Textual input and output on Guile ports is layered on top of binary +operations. To this end, each port has an associated character encoding +that controls how bytes read from the port are converted to characters, +and how characters written to the port are converted to bytes. + +@deffn {Scheme Procedure} port-encoding port +@deffnx {C Function} scm_port_encoding (port) +Returns, as a string, the character encoding that @var{port} uses to +interpret its input and output. +@end deffn + +@deffn {Scheme Procedure} set-port-encoding! port enc +@deffnx {C Function} scm_set_port_encoding_x (port, enc) +Sets the character encoding that will be used to interpret I/O to +@var{port}. @var{enc} is a string containing the name of an encoding. +Valid encoding names are those +@url{http://www.iana.org/assignments/character-sets, defined by IANA}, +for example @code{"UTF-8"} or @code{"ISO-8859-1"}. +@end deffn + +When ports are created, they are assigned an encoding. The usual +process to determine the initial encoding for a port is to take the +value of the @code{%default-port-encoding} fluid. + +@defvr {Scheme Variable} %default-port-encoding +A fluid containing name of the encoding to be used by default for newly +created ports (@pxref{Fluids and Dynamic States}). As a special case, +the value @code{#f} is equivalent to @code{"ISO-8859-1"}. +@end defvr + +The @code{%default-port-encoding} itself defaults to the encoding +appropriate for the current locale, if @code{setlocale} has been called. +@xref{Locales}, for more on locales and when you might need to call +@code{setlocale} explicitly. + +Some port types have other ways of determining their initial locales. +String ports, for example, default to the UTF-8 encoding, in order to be +able to represent all characters regardless of the current locale. File +ports can optionally sniff their file for a @code{coding:} declaration; +@xref{File Ports}. Binary ports might be initialized to the ISO-8859-1 +encoding in which each codepoint between 0 and 255 corresponds to a byte +with that value. + +Currently, the ports only work with @emph{non-modal} encodings. Most +encodings are non-modal, meaning that the conversion of bytes to a +string doesn't depend on its context: the same byte sequence will always +return the same string. A couple of modal encodings are in common use, +like ISO-2022-JP and ISO-2022-KR, and they are not yet supported. + +@cindex port conversion strategy +@cindex conversion strategy, port +@cindex decoding error +@cindex encoding error +Each port also has an associated conversion strategy, which determines +what to do when a Guile character can't be converted to the port's +encoded character representation for output. There are three possible +strategies: to raise an error, to replace the character with a hex +escape, or to replace the character with a substitute character. Port +conversion strategies are also used when decoding characters from an +input port. + +@deffn {Scheme Procedure} port-conversion-strategy port +@deffnx {C Function} scm_port_conversion_strategy (port) +Returns the behavior of the port when outputting a character that is not +representable in the port's current encoding. + +If @var{port} is @code{#f}, then the current default behavior will be +returned. New ports will have this default behavior when they are +created. +@end deffn + +@deffn {Scheme Procedure} set-port-conversion-strategy! port sym +@deffnx {C Function} scm_set_port_conversion_strategy_x (port, sym) +Sets the behavior of Guile when outputting a character that is not +representable in the port's current encoding, or when Guile encounters a +decoding error when trying to read a character. @var{sym} can be either +@code{error}, @code{substitute}, or @code{escape}. + +If @var{port} is an open port, the conversion error behavior is set for +that port. If it is @code{#f}, it is set as the default behavior for +any future ports that get created in this thread. +@end deffn + +As with port encodings, there is a fluid which determines the initial +conversion strategy for a port. + +@deffn {Scheme Variable} %default-port-conversion-strategy +The fluid that defines the conversion strategy for newly created ports, +and also for other conversion routines such as @code{scm_to_stringn}, +@code{scm_from_stringn}, @code{string->pointer}, and +@code{pointer->string}. + +Its value must be one of the symbols described above, with the same +semantics: @code{error}, @code{substitute}, or @code{escape}. + +When Guile starts, its value is @code{substitute}. + +Note that @code{(set-port-conversion-strategy! #f @var{sym})} is +equivalent to @code{(fluid-set! %default-port-conversion-strategy +@var{sym})}. +@end deffn + +As mentioned above, for an output port there are three possible port +conversion strategies. The @code{error} strategy will throw an error +when a nonconvertible character is encountered. The @code{substitute} +strategy will replace nonconvertible characters with a question mark +(@samp{?}). Finally the @code{escape} strategy will print +nonconvertible characters as a hex escape, using the escaping that is +recognized by Guile's string syntax. Note that if the port's encoding +is a Unicode encoding, like @code{UTF-8}, then encoding errors are +impossible. + +For an input port, the @code{error} strategy will cause Guile to throw +an error if it encounters an invalid encoding, such as might happen if +you tried to read @code{ISO-8859-1} as @code{UTF-8}. The error is +thrown before advancing the read position. The @code{substitute} +strategy will replace the bad bytes with a U+FFFD replacement character, +in accordance with Unicode recommendations. When reading from an input +port, the @code{escape} strategy is treated as if it were @code{error}. + + +@node Textual I/O +@subsection Textual I/O +@cindex textual input +@cindex textual output + +This section describes Guile's core textual I/O operations on characters +and strings. @xref{Binary I/O}, for input and output of bytes and +bytevectors. @xref{Encoding}, for more on how characters relate to +bytes. To read general S-expressions from ports, @xref{Scheme Read}. +@xref{Scheme Write}, for interfaces that write generic Scheme datums. + +To use these routines, first include the textual I/O module: + +@example +(use-modules (ice-9 textual-ports)) +@end example + +Note that although this module's name suggests that textual ports are +some different kind of port, that's not the case: all ports in Guile are +both binary and textual ports. + +@deffn {Scheme Procedure} get-char input-port +Reads from @var{input-port}, blocking as necessary, until a +complete character is available from @var{input-port}, +or until an end of file is reached. + +If a complete character is available before the next end of file, +@code{get-char} returns that character and updates the input port to +point past the character. If an end of file is reached before any +character is read, @code{get-char} returns the end-of-file object. +@end deffn + +@deffn {Scheme Procedure} lookahead-char input-port +The @code{lookahead-char} procedure is like @code{get-char}, but it does +not update @var{input-port} to point past the character. +@end deffn + +In the same way that it's possible to "unget" a byte or bytes, it's +possible to "unget" the bytes corresponding to an encoded character. + +@deffn {Scheme Procedure} unget-char port char +Place character @var{char} in @var{port} so that it will be read by the +next read operation. If called multiple times, the unread characters +will be read again in last-in first-out order. +@end deffn + +@deffn {Scheme Procedure} unget-string port str +Place the string @var{str} in @var{port} so that its characters will +be read from left-to-right as the next characters from @var{port} +during subsequent read operations. If called multiple times, the +unread characters will be read again in last-in first-out order. +@end deffn + +Reading in a character at a time can be inefficient. If it's possible +to perform I/O over multiple characters at a time, via strings, that +might be faster. + +@deffn {Scheme Procedure} get-string-n input-port count +The @code{get-string-n} procedure reads from @var{input-port}, blocking +as necessary, until @var{count} characters are available, or until an +end of file is reached. @var{count} must be an exact, non-negative +integer, representing the number of characters to be read. + +If @var{count} characters are available before end of file, +@code{get-string-n} returns a string consisting of those @var{count} +characters. If fewer characters are available before an end of file, but +one or more characters can be read, @code{get-string-n} returns a string +containing those characters. In either case, the input port is updated +to point just past the characters read. If no characters can be read +before an end of file, the end-of-file object is returned. +@end deffn + +@deffn {Scheme Procedure} get-string-n! input-port string start count +The @code{get-string-n!} procedure reads from @var{input-port} in the +same manner as @code{get-string-n}. @var{start} and @var{count} must be +exact, non-negative integer objects, with @var{count} representing the +number of characters to be read. @var{string} must be a string with at +least $@var{start} + @var{count}$ characters. + +If @var{count} characters are available before an end of file, they are +written into @var{string} starting at index @var{start}, and @var{count} +is returned. If fewer characters are available before an end of file, +but one or more can be read, those characters are written into +@var{string} starting at index @var{start} and the number of characters +actually read is returned as an exact integer object. If no characters +can be read before an end of file, the end-of-file object is returned. +@end deffn + +@deffn {Scheme Procedure} get-string-all input-port +Reads from @var{input-port} until an end of file, decoding characters in +the same manner as @code{get-string-n} and @code{get-string-n!}. + +If characters are available before the end of file, a string containing +all the characters decoded from that data are returned. If no character +precedes the end of file, the end-of-file object is returned. +@end deffn + +@deffn {Scheme Procedure} get-line input-port +Reads from @var{input-port} up to and including the linefeed +character or end of file, decoding characters in the same manner as +@code{get-string-n} and @code{get-string-n!}. + +If a linefeed character is read, a string containing all of the text up +to (but not including) the linefeed character is returned, and the port +is updated to point just past the linefeed character. If an end of file +is encountered before any linefeed character is read, but some +characters have been read and decoded as characters, a string containing +those characters is returned. If an end of file is encountered before +any characters are read, the end-of-file object is returned. +@end deffn + +Finally, there are just two core procedures to write characters to a +port. + +@deffn {Scheme Procedure} put-char port char +Writes @var{char} to the port. The @code{put-char} procedure returns +an unspecified value. +@end deffn + +@deffn {Scheme Procedure} put-string port string +@deffnx {Scheme Procedure} put-string port string start +@deffnx {Scheme Procedure} put-string port string start count +Write the @var{count} characters of @var{string} starting at index +@var{start} to the port. + +@var{start} and @var{count} must be non-negative exact integer objects. +@var{string} must have a length of at least @math{@var{start} + +@var{count}}. @var{start} defaults to 0. @var{count} defaults to +@math{@code{(string-length @var{string})} - @var{start}}$. + +Calling @code{put-string} is equivalent in all respects to calling +@code{put-char} on the relevant sequence of characters, except that it +will attempt to write multiple characters to the port at a time, even if +the port is unbuffered. + +The @code{put-string} procedure returns an unspecified value. +@end deffn + +Textual ports have a textual position associated with them: a line and a +column. Reading in characters or writing them out advances the line and +the column appropriately. + +@deffn {Scheme Procedure} port-column port +@deffnx {Scheme Procedure} port-line port +@deffnx {C Function} scm_port_column (port) +@deffnx {C Function} scm_port_line (port) +Return the current column number or line number of @var{port}. +@end deffn + +Port lines and positions are represented as 0-origin integers, which is +to say that the the first character of the first line is line 0, column +0. However, when you display a line number, for example in an error +message, we recommend you add 1 to get 1-origin integers. This is +because lines numbers traditionally start with 1, and that is what +non-programmers will find most natural. + +@deffn {Scheme Procedure} set-port-column! port column +@deffnx {Scheme Procedure} set-port-line! port line +@deffnx {C Function} scm_set_port_column_x (port, column) +@deffnx {C Function} scm_set_port_line_x (port, line) +Set the current column or line number of @var{port}. +@end deffn + +@node Simple Output +@subsection Simple Textual Output + +Guile exports a simple formatted output function, @code{simple-format}. +For a more capable formatted output facility, @xref{Formatted Output}. + +@deffn {Scheme Procedure} simple-format destination message . args +@deffnx {C Function} scm_simple_format (destination, message, args) +Write @var{message} to @var{destination}, defaulting to the current +output port. @var{message} can contain @code{~A} and @code{~S} escapes. +When printed, the escapes are replaced with corresponding members of +@var{args}: @code{~A} formats using @code{display} and @code{~S} formats +using @code{write}. If @var{destination} is @code{#t}, then use the +current output port, if @var{destination} is @code{#f}, then return a +string containing the formatted text. Does not add a trailing newline. +@end deffn + +Somewhat confusingly, Guile binds the @code{format} identifier to +@code{simple-format} at startup. Once @code{(ice-9 format)} loads, it +actually replaces the core @code{format} binding, so depending on +whether you or a module you use has loaded @code{(ice-9 format)}, you +may be using the simple or the more capable version. + +@node Buffering +@subsection Buffering +@cindex Port, buffering + +Every port has associated input and output buffers. You can think of +ports as being backed by some mutable store, and that store might be far +away. For example, ports backed by file descriptors have to go all the +way to the kernel to read and write their data. To avoid this +round-trip cost, Guile usually reads in data from the mutable store in +chunks, and then services small requests like @code{get-char} out of +that intermediate buffer. Similarly, small writes like +@code{write-char} first go to a buffer, and are sent to the store when +the buffer is full (or when port is flushed). Buffered ports speed up +your program by reducing the number of round-trips to the mutable store, +and they do so in a way that is mostly transparent to the user. + +There are two major ways, however, in which buffering affects program +semantics. Building correct, performant programs requires understanding +these situations. + +The first case is in random-access read/write ports (@pxref{Random +Access}). These ports, usually backed by a file, logically operate over +the same mutable store when both reading and writing. So, if you read a +character, causing the buffer to fill, then write a character, the bytes +you filled in your read buffer are now invalid. Every time you switch +between reading and writing, Guile has to flush any pending buffer. If +this happens frequently, the cost can be high. In that case you should +reduce the amount that you buffer, in both directions. Similarly, Guile +has to flush buffers before seeking. None of these considerations apply +to sockets, which don't logically read from and write to the same +mutable store, and are not seekable. Note also that sockets are +unbuffered by default. @xref{Network Sockets and Communication}. + +The second case is the more pernicious one. If you write data to a +buffered port, it probably doesn't go out to the mutable store directly. +(This ``probably'' introduces some indeterminism in your program: what +goes to the store, and when, depends on how full the buffer is. It is +something that the user needs to explicitly be aware of.) The data is +written to the store later -- when the buffer fills up due to another +write, or when @code{force-output} is called, or when @code{close-port} +is called, or when the program exits, or even when the garbage collector +runs. The salient point is, @emph{the errors are signalled then too}. +Buffered writes defer error detection (and defer the side effects to the +mutable store), perhaps indefinitely if the port type does not need to +be closed at GC. + +One common heuristic that works well for textual ports is to flush +output when a newline (@code{\n}) is written. This @dfn{line buffering} +mode is on by default for TTY ports. Most other ports are @dfn{block +buffered}, meaning that once the output buffer reaches the block size, +which depends on the port and its configuration, the output is flushed +as a block, without regard to what is in the block. Likewise reads are +read in at the block size, though if there are fewer bytes available to +read, the buffer may not be entirely filled. + +Note that binary reads or writes that are larger than the buffer size go +directly to the mutable store without passing through the buffers. If +your access pattern involves many big reads or writes, buffering might +not matter so much to you. + +To control the buffering behavior of a port, use @code{setvbuf}. + +@deffn {Scheme Procedure} setvbuf port mode [size] +@deffnx {C Function} scm_setvbuf (port, mode, size) +@cindex port buffering +Set the buffering mode for @var{port}. @var{mode} can be one of the +following symbols: + +@table @code +@item none +non-buffered +@item line +line buffered +@item block +block buffered, using a newly allocated buffer of @var{size} bytes. +If @var{size} is omitted, a default size will be used. +@end table +@end deffn + +Another way to set the buffering, for file ports, is to open the file +with @code{0} or @code{l} as part of the mode string, for unbuffered or +line-buffered ports, respectively. @xref{File Ports}, for more. + +Any buffered output data will be written out when the port is closed. +To make sure to flush it at specific points in your program, use +@code{force-otput}. + +@findex fflush +@deffn {Scheme Procedure} force-output [port] +@deffnx {C Function} scm_force_output (port) +Flush the specified output port, or the current output port if +@var{port} is omitted. The current output buffer contents, if any, are +passed to the underlying port implementation. + +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} flush-all-ports +@deffnx {C Function} scm_flush_all_ports () +Equivalent to calling @code{force-output} on all open output ports. The +return value is unspecified. +@end deffn + +Similarly, sometimes you might want to switch from using Guile's ports +to working directly on file descriptors. In that case, for input ports +use @code{drain-input} to get any buffered input from that port. + +@deffn {Scheme Procedure} drain-input port +@deffnx {C Function} scm_drain_input (port) +This procedure clears a port's input buffers, similar +to the way that force-output clears the output buffer. The +contents of the buffers are returned as a single string, e.g., + +@lisp +(define p (open-input-file ...)) +(drain-input p) => empty string, nothing buffered yet. +(unread-char (read-char p) p) +(drain-input p) => initial chars from p, up to the buffer size. +@end lisp +@end deffn + +All of these considerations are very similar to those of streams in the +C library, although Guile's ports are not built on top of C streams. +Still, it is useful to read what other systems do. +@xref{Streams,,,libc,The GNU C Library Reference Manual}, for more +discussion on C streams. + + +@node Random Access +@subsection Random Access +@cindex Random access, ports +@cindex Port, random access + +@deffn {Scheme Procedure} seek fd_port offset whence +@deffnx {C Function} scm_seek (fd_port, offset, whence) +Sets the current position of @var{fd_port} to the integer +@var{offset}. For a file port, @var{offset} is expressed +as a number of bytes; for other types of ports, such as string +ports, @var{offset} is an abstract representation of the +position within the port's data, not necessarily expressed +as a number of bytes. @var{offset} is interpreted according to +the value of @var{whence}. + +One of the following variables should be supplied for +@var{whence}: +@defvar SEEK_SET +Seek from the beginning of the file. +@end defvar +@defvar SEEK_CUR +Seek from the current position. +@end defvar +@defvar SEEK_END +Seek from the end of the file. +@end defvar +If @var{fd_port} is a file descriptor, the underlying system +call is @code{lseek}. @var{port} may be a string port. + +The value returned is the new position in @var{fd_port}. This means +that the current position of a port can be obtained using: +@lisp +(seek port 0 SEEK_CUR) +@end lisp +@end deffn + +@deffn {Scheme Procedure} ftell fd_port +@deffnx {C Function} scm_ftell (fd_port) +Return an integer representing the current position of +@var{fd_port}, measured from the beginning. Equivalent to: + +@lisp +(seek port 0 SEEK_CUR) +@end lisp +@end deffn + +@findex truncate +@findex ftruncate +@deffn {Scheme Procedure} truncate-file file [length] +@deffnx {C Function} scm_truncate_file (file, length) +Truncate @var{file} to @var{length} bytes. @var{file} can be a +filename string, a port object, or an integer file descriptor. The +return value is unspecified. + +For a port or file descriptor @var{length} can be omitted, in which +case the file is truncated at the current position (per @code{ftell} +above). + +On most systems a file can be extended by giving a length greater than +the current size, but this is not mandatory in the POSIX standard. +@end deffn + +@node Line/Delimited +@subsection Line Oriented and Delimited Text +@cindex Line input/output +@cindex Port, line input/output + +The delimited-I/O module can be accessed with: + +@lisp +(use-modules (ice-9 rdelim)) +@end lisp + +It can be used to read or write lines of text, or read text delimited by +a specified set of characters. + +@deffn {Scheme Procedure} read-line [port] [handle-delim] +Return a line of text from @var{port} if specified, otherwise from the +value returned by @code{(current-input-port)}. Under Unix, a line of text +is terminated by the first end-of-line character or by end-of-file. + +If @var{handle-delim} is specified, it should be one of the following +symbols: +@table @code +@item trim +Discard the terminating delimiter. This is the default, but it will +be impossible to tell whether the read terminated with a delimiter or +end-of-file. +@item concat +Append the terminating delimiter (if any) to the returned string. +@item peek +Push the terminating delimiter (if any) back on to the port. +@item split +Return a pair containing the string read from the port and the +terminating delimiter or end-of-file object. +@end table +@end deffn + +@deffn {Scheme Procedure} read-line! buf [port] +Read a line of text into the supplied string @var{buf} and return the +number of characters added to @var{buf}. If @var{buf} is filled, then +@code{#f} is returned. Read from @var{port} if specified, otherwise +from the value returned by @code{(current-input-port)}. +@end deffn + +@deffn {Scheme Procedure} read-delimited delims [port] [handle-delim] +Read text until one of the characters in the string @var{delims} is +found or end-of-file is reached. Read from @var{port} if supplied, +otherwise from the value returned by @code{(current-input-port)}. +@var{handle-delim} takes the same values as described for +@code{read-line}. +@end deffn + +@c begin (scm-doc-string "rdelim.scm" "read-delimited!") +@deffn {Scheme Procedure} read-delimited! delims buf [port] [handle-delim] [start] [end] +Read text into the supplied string @var{buf}. + +If a delimiter was found, return the number of characters written, +except if @var{handle-delim} is @code{split}, in which case the return +value is a pair, as noted above. + +As a special case, if @var{port} was already at end-of-stream, the EOF +object is returned. Also, if no characters were written because the +buffer was full, @code{#f} is returned. + +It's something of a wacky interface, to be honest. +@end deffn + +@deffn {Scheme Procedure} %read-delimited! delims str gobble [port [start [end]]] +@deffnx {C Function} scm_read_delimited_x (delims, str, gobble, port, start, end) +Read characters from @var{port} into @var{str} until one of the +characters in the @var{delims} string is encountered. If +@var{gobble} is true, discard the delimiter character; +otherwise, leave it in the input stream for the next read. If +@var{port} is not specified, use the value of +@code{(current-input-port)}. If @var{start} or @var{end} are +specified, store data only into the substring of @var{str} +bounded by @var{start} and @var{end} (which default to the +beginning and end of the string, respectively). + + Return a pair consisting of the delimiter that terminated the +string and the number of characters read. If reading stopped +at the end of file, the delimiter returned is the +@var{eof-object}; if the string was filled without encountering +a delimiter, this value is @code{#f}. +@end deffn + +@deffn {Scheme Procedure} %read-line [port] +@deffnx {C Function} scm_read_line (port) +Read a newline-terminated line from @var{port}, allocating storage as +necessary. The newline terminator (if any) is removed from the string, +and a pair consisting of the line and its delimiter is returned. The +delimiter may be either a newline or the @var{eof-object}; if +@code{%read-line} is called at the end of file, it returns the pair +@code{(#<eof> . #<eof>)}. +@end deffn + +@node Default Ports +@subsection Default Ports for Input, Output and Errors +@cindex Default ports +@cindex Port, default + +@rnindex current-input-port +@deffn {Scheme Procedure} current-input-port +@deffnx {C Function} scm_current_input_port () +@cindex standard input +Return the current input port. This is the default port used +by many input procedures. + +Initially this is the @dfn{standard input} in Unix and C terminology. +When the standard input is a tty the port is unbuffered, otherwise +it's fully buffered. + +Unbuffered input is good if an application runs an interactive +subprocess, since any type-ahead input won't go into Guile's buffer +and be unavailable to the subprocess. + +Note that Guile buffering is completely separate from the tty ``line +discipline''. In the usual cooked mode on a tty Guile only sees a +line of input once the user presses @key{Return}. +@end deffn + +@rnindex current-output-port +@deffn {Scheme Procedure} current-output-port +@deffnx {C Function} scm_current_output_port () +@cindex standard output +Return the current output port. This is the default port used +by many output procedures. + +Initially this is the @dfn{standard output} in Unix and C terminology. +When the standard output is a tty this port is unbuffered, otherwise +it's fully buffered. + +Unbuffered output to a tty is good for ensuring progress output or a +prompt is seen. But an application which always prints whole lines +could change to line buffered, or an application with a lot of output +could go fully buffered and perhaps make explicit @code{force-output} +calls (@pxref{Buffering}) at selected points. +@end deffn + +@deffn {Scheme Procedure} current-error-port +@deffnx {C Function} scm_current_error_port () +@cindex standard error output +Return the port to which errors and warnings should be sent. + +Initially this is the @dfn{standard error} in Unix and C terminology. +When the standard error is a tty this port is unbuffered, otherwise +it's fully buffered. +@end deffn + +@deffn {Scheme Procedure} set-current-input-port port +@deffnx {Scheme Procedure} set-current-output-port port +@deffnx {Scheme Procedure} set-current-error-port port +@deffnx {C Function} scm_set_current_input_port (port) +@deffnx {C Function} scm_set_current_output_port (port) +@deffnx {C Function} scm_set_current_error_port (port) +Change the ports returned by @code{current-input-port}, +@code{current-output-port} and @code{current-error-port}, respectively, +so that they use the supplied @var{port} for input or output. +@end deffn + +@deffn {Scheme Procedure} with-input-from-port port thunk +@deffnx {Scheme Procedure} with-output-to-port port thunk +@deffnx {Scheme Procedure} with-error-to-port port thunk +Call @var{thunk} in a dynamic environment in which +@code{current-input-port}, @code{current-output-port} or +@code{current-error-port} is rebound to the given @var{port}. +@end deffn + +@deftypefn {C Function} void scm_dynwind_current_input_port (SCM port) +@deftypefnx {C Function} void scm_dynwind_current_output_port (SCM port) +@deftypefnx {C Function} void scm_dynwind_current_error_port (SCM port) +These functions must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). During the dynwind context, the indicated port is set to +@var{port}. + +More precisely, the current port is swapped with a `backup' value +whenever the dynwind context is entered or left. The backup value is +initialized with the @var{port} argument. +@end deftypefn + +@node Port Types +@subsection Types of Port +@cindex Types of ports +@cindex Port, types + +@menu +* File Ports:: Ports on an operating system file. +* Bytevector Ports:: Ports on a bytevector. +* String Ports:: Ports on a Scheme string. +* Custom Ports:: Ports whose implementation you control. +* Soft Ports:: An older version of custom ports. +* Void Ports:: Ports on nothing at all. +@end menu + + +@node File Ports +@subsubsection File Ports +@cindex File port +@cindex Port, file + +The following procedures are used to open file ports. +See also @ref{Ports and File Descriptors, open}, for an interface +to the Unix @code{open} system call. + +All file access uses the ``LFS'' large file support functions when +available, so files bigger than 2 Gbytes (@math{2^31} bytes) can be +read and written on a 32-bit system. + +Most systems have limits on how many files can be open, so it's +strongly recommended that file ports be closed explicitly when no +longer required (@pxref{Ports}). + +@deffn {Scheme Procedure} open-file filename mode @ + [#:guess-encoding=#f] [#:encoding=#f] +@deffnx {C Function} scm_open_file_with_encoding @ + (filename, mode, guess_encoding, encoding) +@deffnx {C Function} scm_open_file (filename, mode) +Open the file whose name is @var{filename}, and return a port +representing that file. The attributes of the port are +determined by the @var{mode} string. The way in which this is +interpreted is similar to C stdio. The first character must be +one of the following: + +@table @samp +@item r +Open an existing file for input. +@item w +Open a file for output, creating it if it doesn't already exist +or removing its contents if it does. +@item a +Open a file for output, creating it if it doesn't already +exist. All writes to the port will go to the end of the file. +The "append mode" can be turned off while the port is in use +@pxref{Ports and File Descriptors, fcntl} +@end table + +The following additional characters can be appended: + +@table @samp +@item + +Open the port for both input and output. E.g., @code{r+}: open +an existing file for both input and output. +@item 0 +Create an "unbuffered" port. In this case input and output +operations are passed directly to the underlying port +implementation without additional buffering. This is likely to +slow down I/O operations. The buffering mode can be changed +while a port is in use (@pxref{Buffering}). +@item l +Add line-buffering to the port. The port output buffer will be +automatically flushed whenever a newline character is written. +@item b +Use binary mode, ensuring that each byte in the file will be read as one +Scheme character. + +To provide this property, the file will be opened with the 8-bit +character encoding "ISO-8859-1", ignoring the default port encoding. +@xref{Ports}, for more information on port encodings. + +Note that while it is possible to read and write binary data as +characters or strings, it is usually better to treat bytes as octets, +and byte sequences as bytevectors. @xref{Binary I/O}, for more. + +This option had another historical meaning, for DOS compatibility: in +the default (textual) mode, DOS reads a CR-LF sequence as one LF byte. +The @code{b} flag prevents this from happening, adding @code{O_BINARY} +to the underlying @code{open} call. Still, the flag is generally useful +because of its port encoding ramifications. +@end table + +Unless binary mode is requested, the character encoding of the new port +is determined as follows: First, if @var{guess-encoding} is true, the +@code{file-encoding} procedure is used to guess the encoding of the file +(@pxref{Character Encoding of Source Files}). If @var{guess-encoding} +is false or if @code{file-encoding} fails, @var{encoding} is used unless +it is also false. As a last resort, the default port encoding is used. +@xref{Ports}, for more information on port encodings. It is an error to +pass a non-false @var{guess-encoding} or @var{encoding} if binary mode +is requested. + +If a file cannot be opened with the access requested, @code{open-file} +throws an exception. +@end deffn + +@rnindex open-input-file +@deffn {Scheme Procedure} open-input-file filename @ + [#:guess-encoding=#f] [#:encoding=#f] [#:binary=#f] + +Open @var{filename} for input. If @var{binary} is true, open the port +in binary mode, otherwise use text mode. @var{encoding} and +@var{guess-encoding} determine the character encoding as described above +for @code{open-file}. Equivalent to +@lisp +(open-file @var{filename} + (if @var{binary} "rb" "r") + #:guess-encoding @var{guess-encoding} + #:encoding @var{encoding}) +@end lisp +@end deffn + +@rnindex open-output-file +@deffn {Scheme Procedure} open-output-file filename @ + [#:encoding=#f] [#:binary=#f] + +Open @var{filename} for output. If @var{binary} is true, open the port +in binary mode, otherwise use text mode. @var{encoding} specifies the +character encoding as described above for @code{open-file}. Equivalent +to +@lisp +(open-file @var{filename} + (if @var{binary} "wb" "w") + #:encoding @var{encoding}) +@end lisp +@end deffn + +@deffn {Scheme Procedure} call-with-input-file filename proc @ + [#:guess-encoding=#f] [#:encoding=#f] [#:binary=#f] +@deffnx {Scheme Procedure} call-with-output-file filename proc @ + [#:encoding=#f] [#:binary=#f] +@rnindex call-with-input-file +@rnindex call-with-output-file +Open @var{filename} for input or output, and call @code{(@var{proc} +port)} with the resulting port. Return the value returned by +@var{proc}. @var{filename} is opened as per @code{open-input-file} or +@code{open-output-file} respectively, and an error is signaled if it +cannot be opened. + +When @var{proc} returns, the port is closed. If @var{proc} does not +return (e.g.@: if it throws an error), then the port might not be +closed automatically, though it will be garbage collected in the usual +way if not otherwise referenced. +@end deffn + +@deffn {Scheme Procedure} with-input-from-file filename thunk @ + [#:guess-encoding=#f] [#:encoding=#f] [#:binary=#f] +@deffnx {Scheme Procedure} with-output-to-file filename thunk @ + [#:encoding=#f] [#:binary=#f] +@deffnx {Scheme Procedure} with-error-to-file filename thunk @ + [#:encoding=#f] [#:binary=#f] +@rnindex with-input-from-file +@rnindex with-output-to-file +Open @var{filename} and call @code{(@var{thunk})} with the new port +setup as respectively the @code{current-input-port}, +@code{current-output-port}, or @code{current-error-port}. Return the +value returned by @var{thunk}. @var{filename} is opened as per +@code{open-input-file} or @code{open-output-file} respectively, and an +error is signaled if it cannot be opened. + +When @var{thunk} returns, the port is closed and the previous setting +of the respective current port is restored. + +The current port setting is managed with @code{dynamic-wind}, so the +previous value is restored no matter how @var{thunk} exits (eg.@: an +exception), and if @var{thunk} is re-entered (via a captured +continuation) then it's set again to the @var{filename} port. + +The port is closed when @var{thunk} returns normally, but not when +exited via an exception or new continuation. This ensures it's still +ready for use if @var{thunk} is re-entered by a captured continuation. +Of course the port is always garbage collected and closed in the usual +way when no longer referenced anywhere. +@end deffn + +@deffn {Scheme Procedure} port-mode port +@deffnx {C Function} scm_port_mode (port) +Return the port modes associated with the open port @var{port}. +These will not necessarily be identical to the modes used when +the port was opened, since modes such as "append" which are +used only during port creation are not retained. +@end deffn + +@deffn {Scheme Procedure} port-filename port +@deffnx {C Function} scm_port_filename (port) +Return the filename associated with @var{port}, or @code{#f} if no +filename is associated with the port. + +@var{port} must be open; @code{port-filename} cannot be used once the +port is closed. +@end deffn + +@deffn {Scheme Procedure} set-port-filename! port filename +@deffnx {C Function} scm_set_port_filename_x (port, filename) +Change the filename associated with @var{port}, using the current input +port if none is specified. Note that this does not change the port's +source of data, but only the value that is returned by +@code{port-filename} and reported in diagnostic output. +@end deffn + +@deffn {Scheme Procedure} file-port? obj +@deffnx {C Function} scm_file_port_p (obj) +Determine whether @var{obj} is a port that is related to a file. +@end deffn + + +@node Bytevector Ports +@subsubsection Bytevector Ports + +@deffn {Scheme Procedure} open-bytevector-input-port bv [transcoder] +@deffnx {C Function} scm_open_bytevector_input_port (bv, transcoder) +Return an input port whose contents are drawn from bytevector @var{bv} +(@pxref{Bytevectors}). + +@c FIXME: Update description when implemented. +The @var{transcoder} argument is currently not supported. +@end deffn + +@deffn {Scheme Procedure} open-bytevector-output-port [transcoder] +@deffnx {C Function} scm_open_bytevector_output_port (transcoder) +Return two values: a binary output port and a procedure. The latter +should be called with zero arguments to obtain a bytevector containing +the data accumulated by the port, as illustrated below. + +@lisp +(call-with-values + (lambda () + (open-bytevector-output-port)) + (lambda (port get-bytevector) + (display "hello" port) + (get-bytevector))) + +@result{} #vu8(104 101 108 108 111) +@end lisp + +@c FIXME: Update description when implemented. +The @var{transcoder} argument is currently not supported. +@end deffn + + +@node String Ports +@subsubsection String Ports +@cindex String port +@cindex Port, string + +@deffn {Scheme Procedure} call-with-output-string proc +@deffnx {C Function} scm_call_with_output_string (proc) +Calls the one-argument procedure @var{proc} with a newly created output +port. When the function returns, the string composed of the characters +written into the port is returned. @var{proc} should not close the port. +@end deffn + +@deffn {Scheme Procedure} call-with-input-string string proc +@deffnx {C Function} scm_call_with_input_string (string, proc) +Calls the one-argument procedure @var{proc} with a newly +created input port from which @var{string}'s contents may be +read. The value yielded by the @var{proc} is returned. +@end deffn + +@deffn {Scheme Procedure} with-output-to-string thunk +Calls the zero-argument procedure @var{thunk} with the current output +port set temporarily to a new string port. It returns a string +composed of the characters written to the current output. +@end deffn + +@deffn {Scheme Procedure} with-input-from-string string thunk +Calls the zero-argument procedure @var{thunk} with the current input +port set temporarily to a string port opened on the specified +@var{string}. The value yielded by @var{thunk} is returned. +@end deffn + +@deffn {Scheme Procedure} open-input-string str +@deffnx {C Function} scm_open_input_string (str) +Take a string and return an input port that delivers characters +from the string. The port can be closed by +@code{close-input-port}, though its storage will be reclaimed +by the garbage collector if it becomes inaccessible. +@end deffn + +@deffn {Scheme Procedure} open-output-string +@deffnx {C Function} scm_open_output_string () +Return an output port that will accumulate characters for +retrieval by @code{get-output-string}. The port can be closed +by the procedure @code{close-output-port}, though its storage +will be reclaimed by the garbage collector if it becomes +inaccessible. +@end deffn + +@deffn {Scheme Procedure} get-output-string port +@deffnx {C Function} scm_get_output_string (port) +Given an output port created by @code{open-output-string}, +return a string consisting of the characters that have been +output to the port so far. + +@code{get-output-string} must be used before closing @var{port}, once +closed the string cannot be obtained. +@end deffn + +With string ports, the port-encoding is treated differently than other +types of ports. When string ports are created, they do not inherit a +character encoding from the current locale. They are given a +default locale that allows them to handle all valid string characters. +Typically one should not modify a string port's character encoding +away from its default. @xref{Encoding}. + + +@node Custom Ports +@subsubsection Custom Ports + +Custom ports allow the user to provide input and handle output via +user-supplied procedures. Guile currently only provides custom binary +ports, not textual ports; for custom textual ports, @xref{Soft Ports}. +We should add the R6RS custom textual port interfaces though. +Contributions are appreciated. + +@cindex custom binary input ports +@deffn {Scheme Procedure} make-custom-binary-input-port id read! get-position set-position! close +Return a new custom binary input port@footnote{This is similar in spirit +to Guile's @dfn{soft ports} (@pxref{Soft Ports}).} named @var{id} (a +string) whose input is drained by invoking @var{read!} and passing it a +bytevector, an index where bytes should be written, and the number of +bytes to read. The @code{read!} procedure must return an integer +indicating the number of bytes read, or @code{0} to indicate the +end-of-file. + +Optionally, if @var{get-position} is not @code{#f}, it must be a thunk +that will be called when @code{port-position} is invoked on the custom +binary port and should return an integer indicating the position within +the underlying data stream; if @var{get-position} was not supplied, the +returned port does not support @code{port-position}. + +Likewise, if @var{set-position!} is not @code{#f}, it should be a +one-argument procedure. When @code{set-port-position!} is invoked on the +custom binary input port, @var{set-position!} is passed an integer +indicating the position of the next byte is to read. + +Finally, if @var{close} is not @code{#f}, it must be a thunk. It is +invoked when the custom binary input port is closed. + +The returned port is fully buffered by default, but its buffering mode +can be changed using @code{setvbuf} (@pxref{Buffering}). + +Using a custom binary input port, the @code{open-bytevector-input-port} +procedure (@pxref{Bytevector Ports}) could be implemented as follows: + +@lisp +(define (open-bytevector-input-port source) + (define position 0) + (define length (bytevector-length source)) + + (define (read! bv start count) + (let ((count (min count (- length position)))) + (bytevector-copy! source position + bv start count) + (set! position (+ position count)) + count)) + + (define (get-position) position) + + (define (set-position! new-position) + (set! position new-position)) + + (make-custom-binary-input-port "the port" read! + get-position set-position! + #f)) + +(read (open-bytevector-input-port (string->utf8 "hello"))) +@result{} hello +@end lisp +@end deffn + +@cindex custom binary output ports +@deffn {Scheme Procedure} make-custom-binary-output-port id write! get-position set-position! close +Return a new custom binary output port named @var{id} (a string) whose +output is sunk by invoking @var{write!} and passing it a bytevector, an +index where bytes should be read from this bytevector, and the number of +bytes to be ``written''. The @code{write!} procedure must return an +integer indicating the number of bytes actually written; when it is +passed @code{0} as the number of bytes to write, it should behave as +though an end-of-file was sent to the byte sink. + +The other arguments are as for @code{make-custom-binary-input-port}. +@end deffn + +@cindex custom binary input/output ports +@deffn {Scheme Procedure} make-custom-binary-input/output-port id read! write! get-position set-position! close +Return a new custom binary input/output port named @var{id} (a string). +The various arguments are the same as for The other arguments are as for +@code{make-custom-binary-input-port} and +@code{make-custom-binary-output-port}. If buffering is enabled on the +port, as is the case by default, input will be buffered in both +directions; @xref{Buffering}. If the @var{set-position!} function is +provided and not @code{#f}, then the port will also be marked as +random-access, causing the buffer to be flushed between reads and +writes. +@end deffn + +@node Soft Ports +@subsubsection Soft Ports +@cindex Soft port +@cindex Port, soft + +A @dfn{soft port} is a port based on a vector of procedures capable of +accepting or delivering characters. It allows emulation of I/O ports. + +@deffn {Scheme Procedure} make-soft-port pv modes +Return a port capable of receiving or delivering characters as +specified by the @var{modes} string (@pxref{File Ports, +open-file}). @var{pv} must be a vector of length 5 or 6. Its +components are as follows: + +@enumerate 0 +@item +procedure accepting one character for output +@item +procedure accepting a string for output +@item +thunk for flushing output +@item +thunk for getting one character +@item +thunk for closing port (not by garbage collection) +@item +(if present and not @code{#f}) thunk for computing the number of +characters that can be read from the port without blocking. +@end enumerate + +For an output-only port only elements 0, 1, 2, and 4 need be +procedures. For an input-only port only elements 3 and 4 need +be procedures. Thunks 2 and 4 can instead be @code{#f} if +there is no useful operation for them to perform. + +If thunk 3 returns @code{#f} or an @code{eof-object} +(@pxref{Input, eof-object?, ,r5rs, The Revised^5 Report on +Scheme}) it indicates that the port has reached end-of-file. +For example: + +@lisp +(define stdout (current-output-port)) +(define p (make-soft-port + (vector + (lambda (c) (write c stdout)) + (lambda (s) (display s stdout)) + (lambda () (display "." stdout)) + (lambda () (char-upcase (read-char))) + (lambda () (display "@@" stdout))) + "rw")) + +(write p p) @result{} #<input-output: soft 8081e20> +@end lisp +@end deffn + + +@node Void Ports +@subsubsection Void Ports +@cindex Void port +@cindex Port, void + +This kind of port causes any data to be discarded when written to, and +always returns the end-of-file object when read from. + +@deffn {Scheme Procedure} %make-void-port mode +@deffnx {C Function} scm_sys_make_void_port (mode) +Create and return a new void port. A void port acts like +@file{/dev/null}. The @var{mode} argument +specifies the input/output modes for this port: see the +documentation for @code{open-file} in @ref{File Ports}. +@end deffn + + +@node Venerable Port Interfaces +@subsection Venerable Port Interfaces + +Over the 25 years or so that Guile has been around, its port system has +evolved, adding many useful features. At the same time there have been +four major Scheme standards released in those 25 years, which also +evolve the common Scheme understanding of what a port interface should +be. Alas, it would be too much to ask for all of these evolutionary +branches to be consistent. Some of Guile's original interfaces don't +mesh with the later Scheme standards, and yet Guile can't just drop old +interfaces. Sadly as well, the R6RS and R7RS standards both part from a +base of R5RS, but end up in different and somewhat incompatible designs. + +Guile's approach is to pick a set of port primitives that make sense +together. We document that set of primitives, design our internal +interfaces around them, and recommend them to users. As the R6RS I/O +system is the most capable standard that Scheme has yet produced in this +domain, we mostly recommend that; @code{(ice-9 binary-ports)} and +@code{(ice-9 textual-ports)} are wholly modelled on @code{(rnrs io +ports)}. Guile does not wholly copy R6RS, however; @xref{R6RS +Incompatibilities}. + +At the same time, we have many venerable port interfaces, lore handed +down to us from our hacker ancestors. Most of these interfaces even +predate the expectation that Scheme should have modules, so they are +present in the default environment. In Guile we support them as well +and we have no plans to remove them, but again we don't recommend them +for new users. + +@rnindex char-ready? +@deffn {Scheme Procedure} char-ready? [port] +Return @code{#t} if a character is ready on input @var{port} +and return @code{#f} otherwise. If @code{char-ready?} returns +@code{#t} then the next @code{read-char} operation on +@var{port} is guaranteed not to hang. If @var{port} is a file +port at end of file then @code{char-ready?} returns @code{#t}. + +@code{char-ready?} exists to make it possible for a +program to accept characters from interactive ports without +getting stuck waiting for input. Any input editors associated +with such ports must make sure that characters whose existence +has been asserted by @code{char-ready?} cannot be rubbed out. +If @code{char-ready?} were to return @code{#f} at end of file, +a port at end of file would be indistinguishable from an +interactive port that has no ready characters. + +Note that @code{char-ready?} only works reliably for terminals and +sockets with one-byte encodings. Under the hood it will return +@code{#t} if the port has any input buffered, or if the file descriptor +that backs the port polls as readable, indicating that Guile can fetch +more bytes from the kernel. However being able to fetch one byte +doesn't mean that a full character is available; @xref{Encoding}. Also, +on many systems it's possible for a file descriptor to poll as readable, +but then block when it comes time to read bytes. Note also that on +Linux kernels, all file ports backed by files always poll as readable. +For non-file ports, this procedure always returns @code{#t}, except for +soft ports, which have a @code{char-ready?} handler. @xref{Soft Ports}. + +In short, this is a legacy procedure whose semantics are hard to +provide. However it is a useful check to see if any input is buffered. +@xref{Non-Blocking I/O}. +@end deffn + +@rnindex read-char +@deffn {Scheme Procedure} read-char [port] +The same as @code{get-char}, except that @var{port} defaults to the +current input port. @xref{Textual I/O}. +@end deffn + +@rnindex peek-char +@deffn {Scheme Procedure} peek-char [port] +The same as @code{lookahead-char}, except that @var{port} defaults to +the current input port. @xref{Textual I/O}. +@end deffn + +@deffn {Scheme Procedure} unread-char cobj [port] +The same as @code{unget-char}, except that @var{port} defaults to the +current input port, and the arguments are swapped. @xref{Textual I/O}. +@end deffn + +@deffn {Scheme Procedure} unread-string str port +@deffnx {C Function} scm_unread_string (str, port) +The same as @code{unget-string}, except that @var{port} defaults to the +current input port, and the arguments are swapped. @xref{Textual I/O}. +@end deffn + +@rnindex newline +@deffn {Scheme Procedure} newline [port] +Send a newline to @var{port}. If @var{port} is omitted, send to the +current output port. Equivalent to @code{(put-char port #\newline)}. +@end deffn + +@rnindex write-char +@deffn {Scheme Procedure} write-char chr [port] +The same as @code{put-char}, except that @var{port} defaults to the +current input port, and the arguments are swapped. @xref{Textual I/O}. +@end deffn + +@node Using Ports from C +@subsection Using Ports from C + +Guile's C interfaces provides some niceties for sending and receiving +bytes and characters in a way that works better with C. + +@deftypefn {C Function} size_t scm_c_read (SCM port, void *buffer, size_t size) +Read up to @var{size} bytes from @var{port} and store them in +@var{buffer}. The return value is the number of bytes actually read, +which can be less than @var{size} if end-of-file has been reached. + +Note that as this is a binary input procedure, this function does not +update @code{port-line} and @code{port-column} (@pxref{Textual I/O}). +@end deftypefn + +@deftypefn {C Function} void scm_c_write (SCM port, const void *buffer, size_t size) +Write @var{size} bytes at @var{buffer} to @var{port}. + +Note that as this is a binary output procedure, this function does not +update @code{port-line} and @code{port-column} (@pxref{Textual I/O}). +@end deftypefn + +@deftypefn {C Function} size_t scm_c_read_bytes (SCM port, SCM bv, size_t start, size_t count) +@deftypefnx {C Function} void scm_c_write_bytes (SCM port, SCM bv, size_t start, size_t count) +Like @code{scm_c_read} and @code{scm_c_write}, but reading into or +writing from the bytevector @var{bv}. @var{count} indicates the byte +index at which to start in the bytevector, and the read or write will +continue for @var{count} bytes. +@end deftypefn + +@deftypefn {C Function} void scm_unget_bytes (const unsigned char *buf, size_t len, SCM port) +@deftypefnx {C Function} void scm_unget_byte (int c, SCM port) +@deftypefnx {C Function} void scm_ungetc (scm_t_wchar c, SCM port) +Like @code{unget-bytevector}, @code{unget-byte}, and @code{unget-char}, +respectively. @xref{Textual I/O}. +@end deftypefn + +@deftypefn {C Function} void scm_c_put_latin1_chars (SCM port, const scm_t_uint8 *buf, size_t len) +@deftypefnx {C Function} void scm_c_put_utf32_chars (SCM port, const scm_t_uint32 *buf, size_t len); +Write a string to @var{port}. In the first case, the +@code{scm_t_uint8*} buffer is a string in the latin-1 encoding. In the +second, the @code{scm_t_uint32*} buffer is a string in the UTF-32 +encoding. These routines will update the port's line and column. +@end deftypefn + +@node I/O Extensions +@subsection Implementing New Port Types in C + +This section describes how to implement a new port type in C. Although +ports support many operations, as a data structure they present an +opaque interface to the user. To the port implementor, you have two +pieces of information to work with: the port type, and the port's +``stream''. The port type is an opaque pointer allocated when defining +your port type. It is your key into the port API, and it helps you +identify which ports are actually yours. The ``stream'' is a pointer +you control, and which you set when you create a port. Get a stream +from a port using the @code{SCM_STREAM} macro. Note that your port +methods are only ever called with ports of your type. + +A port type is created by calling @code{scm_make_port_type}. Once you +have your port type, you can create ports with @code{scm_c_make_port}, +or @code{scm_c_make_port_with_encoding}. + +@deftypefun scm_t_port_type* scm_make_port_type (char *name, size_t (*read) (SCM port, SCM dst, size_t start, size_t count), size_t (*write) (SCM port, SCM src, size_t start, size_t count)) +Define a new port type. The @var{name}, @var{read} and @var{write} +parameters are initial values for those port type fields, as described +below. The other fields are initialized with default values and can be +changed later. +@end deftypefun + +@deftypefun SCM scm_c_make_port_with_encoding (scm_t_port_type *type, unsigned long mode_bits, SCM encoding, SCM conversion_strategy, scm_t_bits stream) +@deftypefunx SCM scm_c_make_port (scm_t_port_type *type, unsigned long mode_bits, scm_t_bits stream) +Make a port with the given @var{type}. The @var{stream} indicates the +private data associated with the port, which your port implementation +may later retrieve with @code{SCM_STREAM}. The mode bits should include +one or more of the flags @code{SCM_RDNG} or @code{SCM_WRTNG}, indicating +that the port is an input and/or an output port, respectively. The mode +bits may also include @code{SCM_BUF0} or @code{SCM_BUFLINE}, indicating +that the port should be unbuffered or line-buffered, respectively. The +default is that the port will be block-buffered. @xref{Buffering}. + +As you would imagine, @var{encoding} and @var{conversion_strategy} +specify the port's initial textual encoding and conversion strategy. +Both are symbols. @code{scm_c_make_port} is the same as +@code{scm_c_make_port_with_encoding}, except it uses the default port +encoding and conversion strategy. +@end deftypefun + +The port type has a number of associate procedures and properties which +collectively implement the port's behavior. Creating a new port type +mostly involves writing these procedures. + +@table @code +@item name +A pointer to a NUL terminated string: the name of the port type. This +property is initialized via the first argument to +@code{scm_make_port_type}. + +@item read +A port's @code{read} implementation fills read buffers. It should copy +bytes to the supplied bytevector @code{dst}, starting at offset +@code{start} and continuing for @code{count} bytes, returning the number +of bytes read. + +@item write +A port's @code{write} implementation flushes write buffers to the +mutable store. A port's @code{read} implementation fills read buffers. +It should write out bytes from the supplied bytevector @code{src}, +starting at offset @code{start} and continuing for @code{count} bytes, +and return the number of bytes that were written. + +@item read_wait_fd +@itemx write_wait_fd +If a port's @code{read} or @code{write} function returns @code{(size_t) +-1}, that indicates that reading or writing would block. In that case +to preserve the illusion of a blocking read or write operation, Guile's +C port run-time will @code{poll} on the file descriptor returned by +either the port's @code{read_wait_fd} or @code{write_wait_fd} function. +Set using + +@deftypefun void scm_set_port_read_wait_fd (scm_t_port_type *type, int (*wait_fd) (SCM port)) +@deftypefunx void scm_set_port_write_wait_fd (scm_t_port_type *type, int (*wait_fd) (SCM port)) +@end deftypefun + +Only a port type which implements the @code{read_wait_fd} or +@code{write_wait_fd} port methods can usefully return @code{(size_t) -1} +from a read or write function. @xref{Non-Blocking I/O}, for more on +non-blocking I/O in Guile. + +@item print +Called when @code{write} is called on the port, to print a port +description. For example, for a file port it may produce something +like: @code{#<input: /etc/passwd 3>}. Set using + +@deftypefun void scm_set_port_print (scm_t_port_type *type, int (*print) (SCM port, SCM dest_port, scm_print_state *pstate)) +The first argument @var{port} is the port being printed, the second +argument @var{dest_port} is where its description should go. +@end deftypefun + +@item close +Called when the port is closed. It should free any resources used by +the port. Set using + +@deftypefun void scm_set_port_close (scm_t_port_type *type, void (*close) (SCM port)) +@end deftypefun + +By default, ports that are garbage collected just go away without +closing. If your port type needs to release some external resource like +a file descriptor, or needs to make sure that its internal buffers are +flushed even if the port is collected while it was open, then mark the +port type as needing a close on GC. + +@deftypefun void scm_set_port_needs_close_on_gc (scm_t_port_type *type, int needs_close_p) +@end deftypefun + +@item seek +Set the current position of the port. Guile will flush read and/or +write buffers before seeking, as appropriate. + +@deftypefun void scm_set_port_seek (scm_t_port_type *type, scm_t_off (*seek) (SCM port, scm_t_off offset, int whence)) +@end deftypefun + +@item truncate +Truncate the port data to be specified length. Guile will flush buffers +before hand, as appropriate. Set using + +@deftypefun void scm_set_port_truncate (scm_t_port_type *type, void (*truncate) (SCM port, scm_t_off length)) +@end deftypefun + +@item random_access_p +Determine whether this port is a random-access port. + +@cindex random access +Seeking on a random-access port with buffered input, or switching to +writing after reading, will cause the buffered input to be discarded and +Guile will seek the port back the buffered number of bytes. Likewise +seeking on a random-access port with buffered output, or switching to +reading after writing, will flush pending bytes with a call to the +@code{write} procedure. @xref{Buffering}. + +Indicate to Guile that your port needs this behavior by returning a +nonzero value from your @code{random_access_p} function. The default +implementation of this function returns nonzero if the port type +supplies a seek implementation. + +@deftypefun void scm_set_port_random_access_p (scm_t_port_type *type, int (*random_access_p) (SCM port)); +@end deftypefun + +@item get_natural_buffer_sizes +Guile will internally attach buffers to ports. An input port always has +a read buffer and an output port always has a write buffer. +@xref{Buffering}. A port buffer consists of a bytevector, along with +some cursors into that bytevector denoting where to get and put data. + +Port implementations generally don't have to be concerned with +buffering: a port type's @code{read} or @code{write} function will +receive the buffer's bytevector as an argument, along with an offset and +a length into that bytevector, and should then either fill or empty that +bytevector. However in some cases, port implementations may be able to +provide an appropriate default buffer size to Guile. + +@deftypefun void scm_set_port_get_natural_buffer_sizes @ + (scm_t_port_type *type, void (*get_natural_buffer_sizes) (SCM, size_t *read_buf_size, size_t *write_buf_size)) +Fill in @var{read_buf_size} and @var{write_buf_size} with an appropriate buffer size for this port, if one is known. +@end deftypefun + +File ports implement a @code{get_natural_buffer_sizes} to let the +operating system inform Guile about the appropriate buffer sizes for the +particular file opened by the port. +@end table + +Note that calls to all of these methods can proceed in parallel and +concurrently and from any thread up until the point that the port is +closed. The call to @code{close} will happen when no other method is +running, and no method will be called after the @code{close} method is +called. If your port implementation needs mutual exclusion to prevent +concurrency, it is responsible for locking appropriately. + +@node Non-Blocking I/O +@subsection Non-Blocking I/O + +Most ports in Guile are @dfn{blocking}: when you try to read a character +from a port, Guile will block on the read until a character is ready, or +end-of-stream is detected. Likewise whenever Guile goes to write +(possibly buffered) data to an output port, Guile will block until all +the data is written. + +Interacting with ports in blocking mode is very convenient: you can +write straightforward, sequential algorithms whose code flow reflects +the flow of data. However, blocking I/O has two main limitations. + +The first is that it's easy to get into a situation where code is +waiting on data. Time spent waiting on data when code could be doing +something else is wasteful and prevents your program from reaching its +peak throughput. If you implement a web server that sequentially +handles requests from clients, it's very easy for the server to end up +waiting on a client to finish its HTTP request, or waiting on it to +consume the response. The end result is that you are able to serve +fewer requests per second than you'd like to serve. + +The second limitation is related: a blocking parser over user-controlled +input is a denial-of-service vulnerability. Indeed the so-called ``slow +loris'' attack of the early 2010s was just that: an attack on common web +servers that drip-fed HTTP requests, one character at a time. All it +took was a handful of slow loris connections to occupy an entire web +server. + +In Guile we would like to preserve the ability to write straightforward +blocking networking processes of all kinds, but under the hood to allow +those processes to suspend their requests if they would block. + +To do this, the first piece is to allow Guile ports to declare +themselves as being nonblocking. This is currently supported only for +file ports, which also includes sockets, terminals, or any other port +that is backed by a file descriptor. To do that, we use an arcane UNIX +incantation: + +@example +(let ((flags (fcntl socket F_GETFL))) + (fcntl socket F_SETFL (logior O_NONBLOCK flags))) +@end example + +Now the file descriptor is open in non-blocking mode. If Guile tries to +read or write from this file and the read or write returns a result +indicating that more data can only be had by doing a blocking read or +write, Guile will block by polling on the socket's @code{read-wait-fd} +or @code{write-wait-fd}, to preserve the illusion of a blocking read or +write. @xref{I/O Extensions} for more on those internal interfaces. + +So far we have just reproduced the status quo: the file descriptor is +non-blocking, but the operations on the port do block. To go farther, +it would be nice if we could suspend the ``thread'' using delimited +continuations, and only resume the thread once the file descriptor is +readable or writable. (@xref{Prompts}). + +But here we run into a difficulty. The ports code is implemented in C, +which means that although we can suspend the computation to some outer +prompt, we can't resume it because Guile can't resume delimited +continuations that capture the C stack. + +To overcome this difficulty we have created a compatible but entirely +parallel implementation of port operations. To use this implementation, +do the following: + +@example +(use-modules (ice-9 suspendable-ports)) +(install-suspendable-ports!) +@end example + +This will replace the core I/O primitives like @code{get-char} and +@code{put-bytevector} with new versions that are exactly the same as the +ones in the standard library, but with two differences. One is that +when a read or a write would block, the suspendable port operations call +out the value of the @code{current-read-waiter} or +@code{current-write-waiter} parameter, as appropriate. +@xref{Parameters}. The default read and write waiters do the same thing +that the C read and write waiters do, which is to poll. User code can +parameterize the waiters, though, enabling the computation to suspend +and allow the program to process other I/O operations. Because the new +suspendable ports implementation is written in Scheme, that suspended +computation can resume again later when it is able to make progress. +Success! + +The other main difference is that because the new ports implementation +is written in Scheme, it is slower than C, currently by a factor of 3 or +4, though it depends on many factors. For this reason we have to keep +the C implementations as the default ones. One day when Guile's +compiler is better, we can close this gap and have only one port +operation implementation again. + +Note that Guile does not currently include an implementation of the +facility to suspend the current thread and schedule other threads in the +meantime. Before adding such a thing, we want to make sure that we're +providing the right primitives that can be used to build schedulers and +other user-space concurrency patterns, and that the patterns that we +settle on are the right patterns. In the meantime, have a look at 8sync +(@url{https://gnu.org/software/8sync}) for a prototype of an +asynchronous I/O and concurrency facility. + +@deffn {Scheme Procedure} install-suspendable-ports! +Replace the core ports implementation with suspendable ports, as +described above. This will mutate the values of the bindings like +@code{get-char}, @code{put-u8}, and so on in place. +@end deffn + +@deffn {Scheme Procedure} uninstall-suspendable-ports! +Restore the original core ports implementation, un-doing the effect of +@code{install-suspendable-ports!}. +@end deffn + +@deffn {Scheme Parameter} current-read-waiter +@deffnx {Scheme Parameter} current-write-waiter +Parameters whose values are procedures of one argument, called when a +suspendable port operation would block on a port while reading or +writing, respectively. The default values of these parameters do a +blocking @code{poll} on the port's file descriptor. The procedures are +passed the port in question as their one argument. +@end deffn + + +@node BOM Handling +@subsection Handling of Unicode Byte Order Marks +@cindex BOM +@cindex byte order mark + +This section documents the finer points of Guile's handling of Unicode +byte order marks (BOMs). A byte order mark (U+FEFF) is typically found +at the start of a UTF-16 or UTF-32 stream, to allow readers to reliably +determine the byte order. Occasionally, a BOM is found at the start of +a UTF-8 stream, but this is much less common and not generally +recommended. + +Guile attempts to handle BOMs automatically, and in accordance with the +recommendations of the Unicode Standard, when the port encoding is set +to @code{UTF-8}, @code{UTF-16}, or @code{UTF-32}. In brief, Guile +automatically writes a BOM at the start of a UTF-16 or UTF-32 stream, +and automatically consumes one from the start of a UTF-8, UTF-16, or +UTF-32 stream. + +As specified in the Unicode Standard, a BOM is only handled specially at +the start of a stream, and only if the port encoding is set to +@code{UTF-8}, @code{UTF-16} or @code{UTF-32}. If the port encoding is +set to @code{UTF-16BE}, @code{UTF-16LE}, @code{UTF-32BE}, or +@code{UTF-32LE}, then BOMs are @emph{not} handled specially, and none of +the special handling described in this section applies. + +@itemize @bullet +@item +To ensure that Guile will properly detect the byte order of a UTF-16 or +UTF-32 stream, you must perform a textual read before any writes, seeks, +or binary I/O. Guile will not attempt to read a BOM unless a read is +explicitly requested at the start of the stream. + +@item +If a textual write is performed before the first read, then an arbitrary +byte order will be chosen. Currently, big endian is the default on all +platforms, but that may change in the future. If you wish to explicitly +control the byte order of an output stream, set the port encoding to +@code{UTF-16BE}, @code{UTF-16LE}, @code{UTF-32BE}, or @code{UTF-32LE}, +and explicitly write a BOM (@code{#\xFEFF}) if desired. + +@item +If @code{set-port-encoding!} is called in the middle of a stream, Guile +treats this as a new logical ``start of stream'' for purposes of BOM +handling, and will forget about any BOMs that had previously been seen. +Therefore, it may choose a different byte order than had been used +previously. This is intended to support multiple logical text streams +embedded within a larger binary stream. + +@item +Binary I/O operations are not guaranteed to update Guile's notion of +whether the port is at the ``start of the stream'', nor are they +guaranteed to produce or consume BOMs. + +@item +For ports that support seeking (e.g. normal files), the input and output +streams are considered linked: if the user reads first, then a BOM will +be consumed (if appropriate), but later writes will @emph{not} produce a +BOM. Similarly, if the user writes first, then later reads will +@emph{not} consume a BOM. + +@item +For ports that are not random access (e.g. pipes, sockets, and +terminals), the input and output streams are considered +@emph{independent} for purposes of BOM handling: the first read will +consume a BOM (if appropriate), and the first write will @emph{also} +produce a BOM (if appropriate). However, the input and output streams +will always use the same byte order. + +@item +Seeks to the beginning of a file will set the ``start of stream'' flags. +Therefore, a subsequent textual read or write will consume or produce a +BOM. However, unlike @code{set-port-encoding!}, if a byte order had +already been chosen for the port, it will remain in effect after a seek, +and cannot be changed by the presence of a BOM. Seeks anywhere other +than the beginning of a file clear the ``start of stream'' flags. +@end itemize + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-lalr.texi b/doc/ref/api-lalr.texi new file mode 100644 index 000000000..0d47aac85 --- /dev/null +++ b/doc/ref/api-lalr.texi @@ -0,0 +1,35 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2017 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node LALR(1) Parsing +@section LALR(1) Parsing + +The @code{(system base lalr)} module provides the +@uref{https://github.com/schemeway/lalr-scm/, @code{lalr-scm} LALR(1) parser +generator by Dominique Boucher}. @code{lalr-scm} uses the same algorithm as GNU +Bison (@pxref{Introduction, Introduction to Bison,, bison, Bison@comma{} The +Yacc-compatible Parser Generator}). Parsers are defined using the +@code{lalr-parser} macro. + +@deffn {Scheme Syntax} lalr-parser [@var{options}] @var{tokens} @var{rules}... +Generate an LALR(1) syntax analyzer. @var{tokens} is a list of symbols +representing the terminal symbols of the grammar. @var{rules} are the grammar +production rules. + +Each rule has the form @code{(@var{non-terminal} (@var{rhs} ...) : @var{action} +...)}, where @var{non-terminal} is the name of the rule, @var{rhs} are the +right-hand sides, i.e., the production rule, and @var{action} is a semantic +action associated with the rule. + +The generated parser is a two-argument procedure that takes a +@dfn{tokenizer} and a @dfn{syntax error procedure}. The tokenizer +should be a thunk that returns lexical tokens as produced by +@code{make-lexical-token}. The syntax error procedure may be called +with at least an error message (a string), and optionally the lexical +token that caused the error. +@end deffn + +Please refer to the @code{lalr-scm} documentation for details. diff --git a/doc/ref/api-languages.texi b/doc/ref/api-languages.texi new file mode 100644 index 000000000..839e6eae2 --- /dev/null +++ b/doc/ref/api-languages.texi @@ -0,0 +1,276 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Other Languages +@section Support for Other Languages + +In addition to Scheme, a user may write a Guile program in an increasing +number of other languages. Currently supported languages include Emacs +Lisp and ECMAScript. + +Guile is still fundamentally a Scheme, but it tries to support a wide +variety of language building-blocks, so that other languages can be +implemented on top of Guile. This allows users to write or extend +applications in languages other than Scheme, too. This section describes +the languages that have been implemented. + +(For details on how to implement a language, @xref{Compiling to the +Virtual Machine}.) + +@menu +* Using Other Languages:: How to use other languages. +* Emacs Lisp:: The dialect of Lisp used in Emacs. +* ECMAScript:: As seen on television. +@end menu + + +@node Using Other Languages +@subsection Using Other Languages + +There are currently only two ways to access other languages from within +Guile: at the REPL, and programmatically, via @code{compile}, +@code{read-and-compile}, and @code{compile-file}. + +The REPL is Guile's command prompt (@pxref{Using Guile Interactively}). +The REPL has a concept of the ``current language'', which defaults to +Scheme. The user may change that language, via the meta-command +@code{,language}. + +For example, the following meta-command enables Emacs Lisp input: + +@example +scheme@@(guile-user)> ,language elisp +Happy hacking with Emacs Lisp! To switch back, type `,L scheme'. +elisp@@(guile-user)> (eq 1 2) +$1 = #nil +@end example + +Each language has its short name: for example, @code{elisp}, for Elisp. +The same short name may be used to compile source code programmatically, +via @code{compile}: + +@example +elisp@@(guile-user)> ,L scheme +Happy hacking with Guile Scheme! To switch back, type `,L elisp'. +scheme@@(guile-user)> (compile '(eq 1 2) #:from 'elisp) +$2 = #nil +@end example + +Granted, as the input to @code{compile} is a datum, this works best for +Lispy languages, which have a straightforward datum representation. +Other languages that need more parsing are better dealt with as strings. + +The easiest way to deal with syntax-heavy language is with files, via +@code{compile-file} and friends. However it is possible to invoke a +language's reader on a port, and then compile the resulting expression +(which is a datum at that point). For more information, +@xref{Compilation}. + +For more details on introspecting aspects of different languages, +@xref{Compiler Tower}. + +@node Emacs Lisp +@subsection Emacs Lisp + +Emacs Lisp (Elisp) is a dynamically-scoped Lisp dialect used in the +Emacs editor. @xref{top,,Overview,elisp,Emacs Lisp}, for more +information on Emacs Lisp. + +We hope that eventually Guile's implementation of Elisp will be good +enough to replace Emacs' own implementation of Elisp. For that reason, +we have thought long and hard about how to support the various features +of Elisp in a performant and compatible manner. + +Readers familiar with Emacs Lisp might be curious about how exactly +these various Elisp features are supported in Guile. The rest of this +section focuses on addressing these concerns of the Elisp elect. + +@menu +* Nil:: A third boolean. +* Dynamic Binding:: Threadsafe bindings with fluids. +* Other Elisp Features:: Miscellany. +@end menu + + +@node Nil +@subsubsection Nil + +@code{nil} in ELisp is an amalgam of Scheme's @code{#f} and @code{'()}. +It is false, and it is the end-of-list; thus it is a boolean, and a list +as well. + +Guile has chosen to support @code{nil} as a separate value, distinct +from @code{#f} and @code{'()}. This allows existing Scheme and Elisp +code to maintain their current semantics. @code{nil}, which in Elisp +would just be written and read as @code{nil}, in Scheme has the external +representation @code{#nil}. + +This decision to have @code{nil} as a low-level distinct value +facilitates interoperability between the two languages. Guile has chosen +to have Scheme deal with @code{nil} as follows: + +@example +(boolean? #nil) @result{} #t +(not #nil) @result{} #t +(null? #nil) @result{} #t +@end example + +And in C, one has: + +@example +scm_is_bool (SCM_ELISP_NIL) @result{} 1 +scm_is_false (SCM_ELISP_NIL) @result{} 1 +scm_is_null (SCM_ELISP_NIL) @result{} 1 +@end example + +In this way, a version of @code{fold} written in Scheme can correctly +fold a function written in Elisp (or in fact any other language) over a +nil-terminated list, as Elisp makes. The converse holds as well; a +version of @code{fold} written in Elisp can fold over a +@code{'()}-terminated list, as made by Scheme. + +On a low level, the bit representations for @code{#f}, @code{#t}, +@code{nil}, and @code{'()} are made in such a way that they differ by +only one bit, and so a test for, for example, @code{#f}-or-@code{nil} +may be made very efficiently. See @code{libguile/boolean.h}, for more +information. + +@subsubheading Equality + +Since Scheme's @code{equal?} must be transitive, and @code{'()} +is not @code{equal?} to @code{#f}, to Scheme @code{nil} is not +@code{equal?} to @code{#f} or @code{'()}. + +@example +(eq? #f '()) @result{} #f +(eq? #nil '()) @result{} #f +(eq? #nil #f) @result{} #f +(eqv? #f '()) @result{} #f +(eqv? #nil '()) @result{} #f +(eqv? #nil #f) @result{} #f +(equal? #f '()) @result{} #f +(equal? #nil '()) @result{} #f +(equal? #nil #f) @result{} #f +@end example + +However, in Elisp, @code{'()}, @code{#f}, and @code{nil} are all +@code{equal} (though not @code{eq}). + +@example +(defvar f (make-scheme-false)) +(defvar eol (make-scheme-null)) +(eq f eol) @result{} nil +(eq nil eol) @result{} nil +(eq nil f) @result{} nil +(equal f eol) @result{} t +(equal nil eol) @result{} t +(equal nil f) @result{} t +@end example + +These choices facilitate interoperability between Elisp and Scheme code, +but they are not perfect. Some code that is correct standard Scheme is +not correct in the presence of a second false and null value. For +example: + +@example +(define (truthiness x) + (if (eq? x #f) + #f + #t)) +@end example + +This code seems to be meant to test a value for truth, but now that +there are two false values, @code{#f} and @code{nil}, it is no longer +correct. + +Similarly, there is the loop: + +@example +(define (my-length l) + (let lp ((l l) (len 0)) + (if (eq? l '()) + len + (lp (cdr l) (1+ len))))) +@end example + +Here, @code{my-length} will raise an error if @var{l} is a +@code{nil}-terminated list. + +Both of these examples are correct standard Scheme, but, depending on +what they really want to do, they are not correct Guile Scheme. +Correctly written, they would test the @emph{properties} of falsehood or +nullity, not the individual members of that set. That is to say, they +should use @code{not} or @code{null?} to test for falsehood or nullity, +not @code{eq?} or @code{memv} or the like. + +Fortunately, using @code{not} and @code{null?} is in good style, so all +well-written standard Scheme programs are correct, in Guile Scheme. + +Here are correct versions of the above examples: + +@example +(define (truthiness* x) + (if (not x) + #f + #t)) +;; or: (define (t* x) (not (not x))) +;; or: (define (t** x) x) + +(define (my-length* l) + (let lp ((l l) (len 0)) + (if (null? l) + len + (lp (cdr l) (1+ len))))) +@end example + +This problem has a mirror-image case in Elisp: + +@example +(defun my-falsep (x) + (if (eq x nil) + t + nil)) +@end example + +Guile can warn when compiling code that has equality comparisons with +@code{#f}, @code{'()}, or @code{nil}. @xref{Compilation}, for details. + +@node Dynamic Binding +@subsubsection Dynamic Binding + +In contrast to Scheme, which uses ``lexical scoping'', Emacs Lisp scopes +its variables dynamically. Guile supports dynamic scoping with its +``fluids'' facility. @xref{Fluids and Dynamic States}, for more +information. + +@node Other Elisp Features +@subsubsection Other Elisp Features + +Buffer-local and mode-local variables should be mentioned here, along +with buckybits on characters, Emacs primitive data types, the +Lisp-2-ness of Elisp, and other things. Contributions to the +documentation are most welcome! + +@node ECMAScript +@subsection ECMAScript + +@url{http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf,ECMAScript} +was not the first non-Schemey language implemented by Guile, but it was +the first implemented for Guile's bytecode compiler. The goal was to +support ECMAScript version 3.1, a relatively small language, but the +implementor was completely irresponsible and got distracted by other +things before finishing the standard library, and even some bits of the +syntax. So, ECMAScript does deserve a mention in the manual, but it +doesn't deserve an endorsement until its implementation is completed, +perhaps by some more responsible hacker. + +In the meantime, the charitable user might investigate such invocations +as @code{,L ecmascript} and @code{cat test-suite/tests/ecmascript.test}. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-macros.texi b/doc/ref/api-macros.texi new file mode 100644 index 000000000..2e0036932 --- /dev/null +++ b/doc/ref/api-macros.texi @@ -0,0 +1,1452 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2009-2015, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Macros +@section Macros + +At its best, programming in Lisp is an iterative process of building up a +language appropriate to the problem at hand, and then solving the problem in +that language. Defining new procedures is part of that, but Lisp also allows +the user to extend its syntax, with its famous @dfn{macros}. + +@cindex macros +@cindex transformation +Macros are syntactic extensions which cause the expression that they appear in +to be transformed in some way @emph{before} being evaluated. In expressions that +are intended for macro transformation, the identifier that names the relevant +macro must appear as the first element, like this: + +@lisp +(@var{macro-name} @var{macro-args} @dots{}) +@end lisp + +@cindex macro expansion +@cindex domain-specific language +@cindex embedded domain-specific language +@cindex DSL +@cindex EDSL +Macro expansion is a separate phase of evaluation, run before code is +interpreted or compiled. A macro is a program that runs on programs, translating +an embedded language into core Scheme@footnote{These days such embedded +languages are often referred to as @dfn{embedded domain-specific +languages}, or EDSLs.}. + +@menu +* Defining Macros:: Binding macros, globally and locally. +* Syntax Rules:: Pattern-driven macros. +* Syntax Case:: Procedural, hygienic macros. +* Syntax Transformer Helpers:: Helpers for use in procedural macros. +* Defmacros:: Lisp-style macros. +* Identifier Macros:: Identifier macros. +* Syntax Parameters:: Syntax Parameters. +* Eval When:: Affecting the expand-time environment. +* Macro Expansion:: Procedurally expanding macros. +* Hygiene and the Top-Level:: A hack you might want to know about. +* Internal Macros:: Macros as first-class values. +@end menu + +@node Defining Macros +@subsection Defining Macros + +A macro is a binding between a keyword and a syntax transformer. Since it's +difficult to discuss @code{define-syntax} without discussing the format of +transformers, consider the following example macro definition: + +@example +(define-syntax when + (syntax-rules () + ((when condition exp ...) + (if condition + (begin exp ...))))) + +(when #t + (display "hey ho\n") + (display "let's go\n")) +@print{} hey ho +@print{} let's go +@end example + +In this example, the @code{when} binding is bound with @code{define-syntax}. +Syntax transformers are discussed in more depth in @ref{Syntax Rules} and +@ref{Syntax Case}. + +@deffn {Syntax} define-syntax keyword transformer +Bind @var{keyword} to the syntax transformer obtained by evaluating +@var{transformer}. + +After a macro has been defined, further instances of @var{keyword} in Scheme +source code will invoke the syntax transformer defined by @var{transformer}. +@end deffn + +One can also establish local syntactic bindings with @code{let-syntax}. + +@deffn {Syntax} let-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +Bind each @var{keyword} to its corresponding @var{transformer} while +expanding @var{exp1} @var{exp2} @enddots{}. + +A @code{let-syntax} binding only exists at expansion-time. + +@example +(let-syntax ((unless + (syntax-rules () + ((unless condition exp ...) + (if (not condition) + (begin exp ...)))))) + (unless #t + (primitive-exit 1)) + "rock rock rock") +@result{} "rock rock rock" +@end example +@end deffn + +A @code{define-syntax} form is valid anywhere a definition may appear: at the +top-level, or locally. Just as a local @code{define} expands out to an instance +of @code{letrec}, a local @code{define-syntax} expands out to +@code{letrec-syntax}. + +@deffn {Syntax} letrec-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +Bind each @var{keyword} to its corresponding @var{transformer} while +expanding @var{exp1} @var{exp2} @enddots{}. + +In the spirit of @code{letrec} versus @code{let}, an expansion produced by +@var{transformer} may reference a @var{keyword} bound by the +same @var{letrec-syntax}. + +@example +(letrec-syntax ((my-or + (syntax-rules () + ((my-or) + #t) + ((my-or exp) + exp) + ((my-or exp rest ...) + (let ((t exp)) + (if t + t + (my-or rest ...))))))) + (my-or #f "rockaway beach")) +@result{} "rockaway beach" +@end example +@end deffn + +@node Syntax Rules +@subsection Syntax-rules Macros + +@code{syntax-rules} macros are simple, pattern-driven syntax transformers, with +a beauty worthy of Scheme. + +@deffn {Syntax} syntax-rules literals (pattern template) @dots{} +Create a syntax transformer that will rewrite an expression using the rules +embodied in the @var{pattern} and @var{template} clauses. +@end deffn + +A @code{syntax-rules} macro consists of three parts: the literals (if any), the +patterns, and as many templates as there are patterns. + +When the syntax expander sees the invocation of a @code{syntax-rules} macro, it +matches the expression against the patterns, in order, and rewrites the +expression using the template from the first matching pattern. If no pattern +matches, a syntax error is signalled. + +@subsubsection Patterns + +We have already seen some examples of patterns in the previous section: +@code{(unless condition exp ...)}, @code{(my-or exp)}, and so on. A pattern is +structured like the expression that it is to match. It can have nested structure +as well, like @code{(let ((var val) ...) exp exp* ...)}. Broadly speaking, +patterns are made of lists, improper lists, vectors, identifiers, and datums. +Users can match a sequence of patterns using the ellipsis (@code{...}). + +Identifiers in a pattern are called @dfn{literals} if they are present in the +@code{syntax-rules} literals list, and @dfn{pattern variables} otherwise. When +building up the macro output, the expander replaces instances of a pattern +variable in the template with the matched subexpression. + +@example +(define-syntax kwote + (syntax-rules () + ((kwote exp) + (quote exp)))) +(kwote (foo . bar)) +@result{} (foo . bar) +@end example + +An improper list of patterns matches as rest arguments do: + +@example +(define-syntax let1 + (syntax-rules () + ((_ (var val) . exps) + (let ((var val)) . exps)))) +@end example + +However this definition of @code{let1} probably isn't what you want, as the tail +pattern @var{exps} will match non-lists, like @code{(let1 (foo 'bar) . baz)}. So +often instead of using improper lists as patterns, ellipsized patterns are +better. Instances of a pattern variable in the template must be followed by an +ellipsis. + +@example +(define-syntax let1 + (syntax-rules () + ((_ (var val) exp ...) + (let ((var val)) exp ...)))) +@end example + +This @code{let1} probably still doesn't do what we want, because the body +matches sequences of zero expressions, like @code{(let1 (foo 'bar))}. In this +case we need to assert we have at least one body expression. A common idiom for +this is to name the ellipsized pattern variable with an asterisk: + +@example +(define-syntax let1 + (syntax-rules () + ((_ (var val) exp exp* ...) + (let ((var val)) exp exp* ...)))) +@end example + +A vector of patterns matches a vector whose contents match the patterns, +including ellipsizing and tail patterns. + +@example +(define-syntax letv + (syntax-rules () + ((_ #((var val) ...) exp exp* ...) + (let ((var val) ...) exp exp* ...)))) +(letv #((foo 'bar)) foo) +@result{} bar +@end example + +Literals are used to match specific datums in an expression, like the use of +@code{=>} and @code{else} in @code{cond} expressions. + +@example +(define-syntax cond1 + (syntax-rules (=> else) + ((cond1 test => fun) + (let ((exp test)) + (if exp (fun exp) #f))) + ((cond1 test exp exp* ...) + (if test (begin exp exp* ...))) + ((cond1 else exp exp* ...) + (begin exp exp* ...)))) + +(define (square x) (* x x)) +(cond1 10 => square) +@result{} 100 +(let ((=> #t)) + (cond1 10 => square)) +@result{} #<procedure square (x)> +@end example + +A literal matches an input expression if the input expression is an identifier +with the same name as the literal, and both are unbound@footnote{Language +lawyers probably see the need here for use of @code{literal-identifier=?} rather +than @code{free-identifier=?}, and would probably be correct. Patches +accepted.}. + +If a pattern is not a list, vector, or an identifier, it matches as a literal, +with @code{equal?}. + +@example +(define-syntax define-matcher-macro + (syntax-rules () + ((_ name lit) + (define-syntax name + (syntax-rules () + ((_ lit) #t) + ((_ else) #f)))))) + +(define-matcher-macro is-literal-foo? "foo") + +(is-literal-foo? "foo") +@result{} #t +(is-literal-foo? "bar") +@result{} #f +(let ((foo "foo")) + (is-literal-foo? foo)) +@result{} #f +@end example + +The last example indicates that matching happens at expansion-time, not +at run-time. + +Syntax-rules macros are always used as @code{(@var{macro} . @var{args})}, and +the @var{macro} will always be a symbol. Correspondingly, a @code{syntax-rules} +pattern must be a list (proper or improper), and the first pattern in that list +must be an identifier. Incidentally it can be any identifier -- it doesn't have +to actually be the name of the macro. Thus the following three are equivalent: + +@example +(define-syntax when + (syntax-rules () + ((when c e ...) + (if c (begin e ...))))) + +(define-syntax when + (syntax-rules () + ((_ c e ...) + (if c (begin e ...))))) + +(define-syntax when + (syntax-rules () + ((something-else-entirely c e ...) + (if c (begin e ...))))) +@end example + +For clarity, use one of the first two variants. Also note that since the pattern +variable will always match the macro itself (e.g., @code{cond1}), it is actually +left unbound in the template. + +@subsubsection Hygiene + +@code{syntax-rules} macros have a magical property: they preserve referential +transparency. When you read a macro definition, any free bindings in that macro +are resolved relative to the macro definition; and when you read a macro +instantiation, all free bindings in that expression are resolved relative to the +expression. + +This property is sometimes known as @dfn{hygiene}, and it does aid in code +cleanliness. In your macro definitions, you can feel free to introduce temporary +variables, without worrying about inadvertently introducing bindings into the +macro expansion. + +Consider the definition of @code{my-or} from the previous section: + +@example +(define-syntax my-or + (syntax-rules () + ((my-or) + #t) + ((my-or exp) + exp) + ((my-or exp rest ...) + (let ((t exp)) + (if t + t + (my-or rest ...)))))) +@end example + +A naive expansion of @code{(let ((t #t)) (my-or #f t))} would yield: + +@example +(let ((t #t)) + (let ((t #f)) + (if t t t))) +@result{} #f +@end example + +@noindent +Which clearly is not what we want. Somehow the @code{t} in the definition is +distinct from the @code{t} at the site of use; and it is indeed this distinction +that is maintained by the syntax expander, when expanding hygienic macros. + +This discussion is mostly relevant in the context of traditional Lisp macros +(@pxref{Defmacros}), which do not preserve referential transparency. Hygiene +adds to the expressive power of Scheme. + +@subsubsection Shorthands + +One often ends up writing simple one-clause @code{syntax-rules} macros. +There is a convenient shorthand for this idiom, in the form of +@code{define-syntax-rule}. + +@deffn {Syntax} define-syntax-rule (keyword . pattern) [docstring] template +Define @var{keyword} as a new @code{syntax-rules} macro with one clause. +@end deffn + +Cast into this form, our @code{when} example is significantly shorter: + +@example +(define-syntax-rule (when c e ...) + (if c (begin e ...))) +@end example + +@subsubsection Reporting Syntax Errors in Macros + +@deffn {Syntax} syntax-error message [arg ...] +Report an error at macro-expansion time. @var{message} must be a string +literal, and the optional @var{arg} operands can be arbitrary expressions +providing additional information. +@end deffn + +@code{syntax-error} is intended to be used within @code{syntax-rules} +templates. For example: + +@example +(define-syntax simple-let + (syntax-rules () + ((_ (head ... ((x . y) val) . tail) + body1 body2 ...) + (syntax-error + "expected an identifier but got" + (x . y))) + ((_ ((name val) ...) body1 body2 ...) + ((lambda (name ...) body1 body2 ...) + val ...)))) +@end example + +@subsubsection Specifying a Custom Ellipsis Identifier + +When writing macros that generate macro definitions, it is convenient to +use a different ellipsis identifier at each level. Guile allows the +desired ellipsis identifier to be specified as the first operand to +@code{syntax-rules}, as specified by SRFI-46 and R7RS. For example: + +@example +(define-syntax define-quotation-macros + (syntax-rules () + ((_ (macro-name head-symbol) ...) + (begin (define-syntax macro-name + (syntax-rules ::: () + ((_ x :::) + (quote (head-symbol x :::))))) + ...)))) +(define-quotation-macros (quote-a a) (quote-b b) (quote-c c)) +(quote-a 1 2 3) @result{} (a 1 2 3) +@end example + +@subsubsection Further Information + +For a formal definition of @code{syntax-rules} and its pattern language, see +@xref{Macros, , Macros, r5rs, Revised(5) Report on the Algorithmic Language +Scheme}. + +@code{syntax-rules} macros are simple and clean, but do they have limitations. +They do not lend themselves to expressive error messages: patterns either match +or they don't. Their ability to generate code is limited to template-driven +expansion; often one needs to define a number of helper macros to get real work +done. Sometimes one wants to introduce a binding into the lexical context of the +generated code; this is impossible with @code{syntax-rules}. Relatedly, they +cannot programmatically generate identifiers. + +The solution to all of these problems is to use @code{syntax-case} if you need +its features. But if for some reason you're stuck with @code{syntax-rules}, you +might enjoy Joe Marshall's +@uref{http://sites.google.com/site/evalapply/eccentric.txt,@code{syntax-rules} +Primer for the Merely Eccentric}. + +@node Syntax Case +@subsection Support for the @code{syntax-case} System + +@code{syntax-case} macros are procedural syntax transformers, with a power +worthy of Scheme. + +@deffn {Syntax} syntax-case syntax literals (pattern [guard] exp) @dots{} +Match the syntax object @var{syntax} against the given patterns, in order. If a +@var{pattern} matches, return the result of evaluating the associated @var{exp}. +@end deffn + +Compare the following definitions of @code{when}: + +@example +(define-syntax when + (syntax-rules () + ((_ test e e* ...) + (if test (begin e e* ...))))) + +(define-syntax when + (lambda (x) + (syntax-case x () + ((_ test e e* ...) + #'(if test (begin e e* ...)))))) +@end example + +Clearly, the @code{syntax-case} definition is similar to its @code{syntax-rules} +counterpart, and equally clearly there are some differences. The +@code{syntax-case} definition is wrapped in a @code{lambda}, a function of one +argument; that argument is passed to the @code{syntax-case} invocation; and the +``return value'' of the macro has a @code{#'} prefix. + +All of these differences stem from the fact that @code{syntax-case} does not +define a syntax transformer itself -- instead, @code{syntax-case} expressions +provide a way to destructure a @dfn{syntax object}, and to rebuild syntax +objects as output. + +So the @code{lambda} wrapper is simply a leaky implementation detail, that +syntax transformers are just functions that transform syntax to syntax. This +should not be surprising, given that we have already described macros as +``programs that write programs''. @code{syntax-case} is simply a way to take +apart and put together program text, and to be a valid syntax transformer it +needs to be wrapped in a procedure. + +Unlike traditional Lisp macros (@pxref{Defmacros}), @code{syntax-case} macros +transform syntax objects, not raw Scheme forms. Recall the naive expansion of +@code{my-or} given in the previous section: + +@example +(let ((t #t)) + (my-or #f t)) +;; naive expansion: +(let ((t #t)) + (let ((t #f)) + (if t t t))) +@end example + +Raw Scheme forms simply don't have enough information to distinguish the first +two @code{t} instances in @code{(if t t t)} from the third @code{t}. So instead +of representing identifiers as symbols, the syntax expander represents +identifiers as annotated syntax objects, attaching such information to those +syntax objects as is needed to maintain referential transparency. + +@deffn {Syntax} syntax form +Create a syntax object wrapping @var{form} within the current lexical context. +@end deffn + +Syntax objects are typically created internally to the process of expansion, but +it is possible to create them outside of syntax expansion: + +@example +(syntax (foo bar baz)) +@result{} #<some representation of that syntax> +@end example + +@noindent +However it is more common, and useful, to create syntax objects when building +output from a @code{syntax-case} expression. + +@example +(define-syntax add1 + (lambda (x) + (syntax-case x () + ((_ exp) + (syntax (+ exp 1)))))) +@end example + +It is not strictly necessary for a @code{syntax-case} expression to return a +syntax object, because @code{syntax-case} expressions can be used in helper +functions, or otherwise used outside of syntax expansion itself. However a +syntax transformer procedure must return a syntax object, so most uses of +@code{syntax-case} do end up returning syntax objects. + +Here in this case, the form that built the return value was @code{(syntax (+ exp +1))}. The interesting thing about this is that within a @code{syntax} +expression, any appearance of a pattern variable is substituted into the +resulting syntax object, carrying with it all relevant metadata from the source +expression, such as lexical identity and source location. + +Indeed, a pattern variable may only be referenced from inside a @code{syntax} +form. The syntax expander would raise an error when defining @code{add1} if it +found @var{exp} referenced outside a @code{syntax} form. + +Since @code{syntax} appears frequently in macro-heavy code, it has a special +reader macro: @code{#'}. @code{#'foo} is transformed by the reader into +@code{(syntax foo)}, just as @code{'foo} is transformed into @code{(quote foo)}. + +The pattern language used by @code{syntax-case} is conveniently the same +language used by @code{syntax-rules}. Given this, Guile actually defines +@code{syntax-rules} in terms of @code{syntax-case}: + +@example +(define-syntax syntax-rules + (lambda (x) + (syntax-case x () + ((_ (k ...) ((keyword . pattern) template) ...) + #'(lambda (x) + (syntax-case x (k ...) + ((dummy . pattern) #'template) + ...)))))) +@end example + +And that's that. + +@subsubsection Why @code{syntax-case}? + +The examples we have shown thus far could just as well have been expressed with +@code{syntax-rules}, and have just shown that @code{syntax-case} is more +verbose, which is true. But there is a difference: @code{syntax-case} creates +@emph{procedural} macros, giving the full power of Scheme to the macro expander. +This has many practical applications. + +A common desire is to be able to match a form only if it is an identifier. This +is impossible with @code{syntax-rules}, given the datum matching forms. But with +@code{syntax-case} it is easy: + +@deffn {Scheme Procedure} identifier? syntax-object +Returns @code{#t} if @var{syntax-object} is an identifier, or @code{#f} +otherwise. +@end deffn + +@example +;; relying on previous add1 definition +(define-syntax add1! + (lambda (x) + (syntax-case x () + ((_ var) (identifier? #'var) + #'(set! var (add1 var)))))) + +(define foo 0) +(add1! foo) +foo @result{} 1 +(add1! "not-an-identifier") @result{} error +@end example + +With @code{syntax-rules}, the error for @code{(add1! "not-an-identifier")} would +be something like ``invalid @code{set!}''. With @code{syntax-case}, it will say +something like ``invalid @code{add1!}'', because we attach the @dfn{guard +clause} to the pattern: @code{(identifier? #'var)}. This becomes more important +with more complicated macros. It is necessary to use @code{identifier?}, because +to the expander, an identifier is more than a bare symbol. + +Note that even in the guard clause, we reference the @var{var} pattern variable +within a @code{syntax} form, via @code{#'var}. + +Another common desire is to introduce bindings into the lexical context of the +output expression. One example would be in the so-called ``anaphoric macros'', +like @code{aif}. Anaphoric macros bind some expression to a well-known +identifier, often @code{it}, within their bodies. For example, in @code{(aif +(foo) (bar it))}, @code{it} would be bound to the result of @code{(foo)}. + +To begin with, we should mention a solution that doesn't work: + +@example +;; doesn't work +(define-syntax aif + (lambda (x) + (syntax-case x () + ((_ test then else) + #'(let ((it test)) + (if it then else)))))) +@end example + +The reason that this doesn't work is that, by default, the expander will +preserve referential transparency; the @var{then} and @var{else} expressions +won't have access to the binding of @code{it}. + +But they can, if we explicitly introduce a binding via @code{datum->syntax}. + +@deffn {Scheme Procedure} datum->syntax template-id datum +Create a syntax object that wraps @var{datum}, within the lexical context +corresponding to the identifier @var{template-id}. +@end deffn + +For completeness, we should mention that it is possible to strip the metadata +from a syntax object, returning a raw Scheme datum: + +@deffn {Scheme Procedure} syntax->datum syntax-object +Strip the metadata from @var{syntax-object}, returning its contents as a raw +Scheme datum. +@end deffn + +In this case we want to introduce @code{it} in the context of the whole +expression, so we can create a syntax object as @code{(datum->syntax x 'it)}, +where @code{x} is the whole expression, as passed to the transformer procedure. + +Here's another solution that doesn't work: + +@example +;; doesn't work either +(define-syntax aif + (lambda (x) + (syntax-case x () + ((_ test then else) + (let ((it (datum->syntax x 'it))) + #'(let ((it test)) + (if it then else))))))) +@end example + +The reason that this one doesn't work is that there are really two +environments at work here -- the environment of pattern variables, as +bound by @code{syntax-case}, and the environment of lexical variables, +as bound by normal Scheme. The outer let form establishes a binding in +the environment of lexical variables, but the inner let form is inside a +syntax form, where only pattern variables will be substituted. Here we +need to introduce a piece of the lexical environment into the pattern +variable environment, and we can do so using @code{syntax-case} itself: + +@example +;; works, but is obtuse +(define-syntax aif + (lambda (x) + (syntax-case x () + ((_ test then else) + ;; invoking syntax-case on the generated + ;; syntax object to expose it to `syntax' + (syntax-case (datum->syntax x 'it) () + (it + #'(let ((it test)) + (if it then else)))))))) + +(aif (getuid) (display it) (display "none")) (newline) +@print{} 500 +@end example + +However there are easier ways to write this. @code{with-syntax} is often +convenient: + +@deffn {Syntax} with-syntax ((pat val) @dots{}) exp @dots{} +Bind patterns @var{pat} from their corresponding values @var{val}, within the +lexical context of @var{exp} @enddots{}. + +@example +;; better +(define-syntax aif + (lambda (x) + (syntax-case x () + ((_ test then else) + (with-syntax ((it (datum->syntax x 'it))) + #'(let ((it test)) + (if it then else))))))) +@end example +@end deffn + +As you might imagine, @code{with-syntax} is defined in terms of +@code{syntax-case}. But even that might be off-putting to you if you are an old +Lisp macro hacker, used to building macro output with @code{quasiquote}. The +issue is that @code{with-syntax} creates a separation between the point of +definition of a value and its point of substitution. + +@pindex quasisyntax +@pindex unsyntax +@pindex unsyntax-splicing +So for cases in which a @code{quasiquote} style makes more sense, +@code{syntax-case} also defines @code{quasisyntax}, and the related +@code{unsyntax} and @code{unsyntax-splicing}, abbreviated by the reader as +@code{#`}, @code{#,}, and @code{#,@@}, respectively. + +For example, to define a macro that inserts a compile-time timestamp into a +source file, one may write: + +@example +(define-syntax display-compile-timestamp + (lambda (x) + (syntax-case x () + ((_) + #`(begin + (display "The compile timestamp was: ") + (display #,(current-time)) + (newline)))))) +@end example + +Readers interested in further information on @code{syntax-case} macros should +see R. Kent Dybvig's excellent @cite{The Scheme Programming Language}, either +edition 3 or 4, in the chapter on syntax. Dybvig was the primary author of the +@code{syntax-case} system. The book itself is available online at +@uref{http://scheme.com/tspl4/}. + +@subsubsection Custom Ellipsis Identifiers for syntax-case Macros + +When writing procedural macros that generate macro definitions, it is +convenient to use a different ellipsis identifier at each level. Guile +supports this for procedural macros using the @code{with-ellipsis} +special form: + +@deffn {Syntax} with-ellipsis ellipsis body @dots{} +@var{ellipsis} must be an identifier. Evaluate @var{body} in a special +lexical environment such that all macro patterns and templates within +@var{body} will use @var{ellipsis} as the ellipsis identifier instead of +the usual three dots (@code{...}). +@end deffn + +For example: + +@example +(define-syntax define-quotation-macros + (lambda (x) + (syntax-case x () + ((_ (macro-name head-symbol) ...) + #'(begin (define-syntax macro-name + (lambda (x) + (with-ellipsis ::: + (syntax-case x () + ((_ x :::) + #'(quote (head-symbol x :::))))))) + ...))))) +(define-quotation-macros (quote-a a) (quote-b b) (quote-c c)) +(quote-a 1 2 3) @result{} (a 1 2 3) +@end example + +Note that @code{with-ellipsis} does not affect the ellipsis identifier +of the generated code, unless @code{with-ellipsis} is included around +the generated code. + +@node Syntax Transformer Helpers +@subsection Syntax Transformer Helpers + +As noted in the previous section, Guile's syntax expander operates on +syntax objects. Procedural macros consume and produce syntax objects. +This section describes some of the auxiliary helpers that procedural +macros can use to compare, generate, and query objects of this data +type. + +@deffn {Scheme Procedure} bound-identifier=? a b +Return @code{#t} if the syntax objects @var{a} and @var{b} refer to the +same lexically-bound identifier, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} free-identifier=? a b +Return @code{#t} if the syntax objects @var{a} and @var{b} refer to the +same free identifier, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} generate-temporaries ls +Return a list of temporary identifiers as long as @var{ls} is long. +@end deffn + +@deffn {Scheme Procedure} syntax-source x +Return the source properties that correspond to the syntax object +@var{x}. @xref{Source Properties}, for more information. +@end deffn + +Guile also offers some more experimental interfaces in a separate +module. As was the case with the Large Hadron Collider, it is unclear +to our senior macrologists whether adding these interfaces will result +in awesomeness or in the destruction of Guile via the creation of a +singularity. We will preserve their functionality through the 2.0 +series, but we reserve the right to modify them in a future stable +series, to a more than usual degree. + +@example +(use-modules (system syntax)) +@end example + +@deffn {Scheme Procedure} syntax-module id +Return the name of the module whose source contains the identifier +@var{id}. +@end deffn + +@deffn {Scheme Procedure} syntax-local-binding id [#:resolve-syntax-parameters?=#t] +Resolve the identifer @var{id}, a syntax object, within the current +lexical environment, and return two values, the binding type and a +binding value. The binding type is a symbol, which may be one of the +following: + +@table @code +@item lexical +A lexically-bound variable. The value is a unique token (in the sense +of @code{eq?}) identifying this binding. +@item macro +A syntax transformer, either local or global. The value is the +transformer procedure. +@item syntax-parameter +A syntax parameter (@pxref{Syntax Parameters}). By default, +@code{syntax-local-binding} will resolve syntax parameters, so that this +value will not be returned. Pass @code{#:resolve-syntax-parameters? #f} +to indicate that you are interested in syntax parameters. The value is +the default transformer procedure, as in @code{macro}. +@item pattern-variable +A pattern variable, bound via @code{syntax-case}. The value is an +opaque object, internal to the expander. +@item ellipsis +An internal binding, bound via @code{with-ellipsis}. The value is the +(anti-marked) local ellipsis identifier. +@item displaced-lexical +A lexical variable that has gone out of scope. This can happen if a +badly-written procedural macro saves a syntax object, then attempts to +introduce it in a context in which it is unbound. The value is +@code{#f}. +@item global +A global binding. The value is a pair, whose head is the symbol, and +whose tail is the name of the module in which to resolve the symbol. +@item other +Some other binding, like @code{lambda} or other core bindings. The +value is @code{#f}. +@end table + +This is a very low-level procedure, with limited uses. One case in +which it is useful is to build abstractions that associate auxiliary +information with macros: + +@example +(define aux-property (make-object-property)) +(define-syntax-rule (with-aux aux value) + (let ((trans value)) + (set! (aux-property trans) aux) + trans)) +(define-syntax retrieve-aux + (lambda (x) + (syntax-case x () + ((x id) + (call-with-values (lambda () (syntax-local-binding #'id)) + (lambda (type val) + (with-syntax ((aux (datum->syntax #'here + (and (eq? type 'macro) + (aux-property val))))) + #''aux))))))) +(define-syntax foo + (with-aux 'bar + (syntax-rules () ((_) 'foo)))) +(foo) +@result{} foo +(retrieve-aux foo) +@result{} bar +@end example + +@code{syntax-local-binding} must be called within the dynamic extent of +a syntax transformer; to call it otherwise will signal an error. +@end deffn + +@deffn {Scheme Procedure} syntax-locally-bound-identifiers id +Return a list of identifiers that were visible lexically when the +identifier @var{id} was created, in order from outermost to innermost. + +This procedure is intended to be used in specialized procedural macros, +to provide a macro with the set of bound identifiers that the macro can +reference. + +As a technical implementation detail, the identifiers returned by +@code{syntax-locally-bound-identifiers} will be anti-marked, like the +syntax object that is given as input to a macro. This is to signal to +the macro expander that these bindings were present in the original +source, and do not need to be hygienically renamed, as would be the case +with other introduced identifiers. See the discussion of hygiene in +section 12.1 of the R6RS, for more information on marks. + +@example +(define (local-lexicals id) + (filter (lambda (x) + (eq? (syntax-local-binding x) 'lexical)) + (syntax-locally-bound-identifiers id))) +(define-syntax lexicals + (lambda (x) + (syntax-case x () + ((lexicals) #'(lexicals lexicals)) + ((lexicals scope) + (with-syntax (((id ...) (local-lexicals #'scope))) + #'(list (cons 'id id) ...)))))) + +(let* ((x 10) (x 20)) (lexicals)) +@result{} ((x . 10) (x . 20)) +@end example +@end deffn + + +@node Defmacros +@subsection Lisp-style Macro Definitions + +The traditional way to define macros in Lisp is very similar to procedure +definitions. The key differences are that the macro definition body should +return a list that describes the transformed expression, and that the definition +is marked as a macro definition (rather than a procedure definition) by the use +of a different definition keyword: in Lisp, @code{defmacro} rather than +@code{defun}, and in Scheme, @code{define-macro} rather than @code{define}. + +@fnindex defmacro +@fnindex define-macro +Guile supports this style of macro definition using both @code{defmacro} +and @code{define-macro}. The only difference between them is how the +macro name and arguments are grouped together in the definition: + +@lisp +(defmacro @var{name} (@var{args} @dots{}) @var{body} @dots{}) +@end lisp + +@noindent +is the same as + +@lisp +(define-macro (@var{name} @var{args} @dots{}) @var{body} @dots{}) +@end lisp + +@noindent +The difference is analogous to the corresponding difference between +Lisp's @code{defun} and Scheme's @code{define}. + +Having read the previous section on @code{syntax-case}, it's probably clear that +Guile actually implements defmacros in terms of @code{syntax-case}, applying the +transformer on the expression between invocations of @code{syntax->datum} and +@code{datum->syntax}. This realization leads us to the problem with defmacros, +that they do not preserve referential transparency. One can be careful to not +introduce bindings into expanded code, via liberal use of @code{gensym}, but +there is no getting around the lack of referential transparency for free +bindings in the macro itself. + +Even a macro as simple as our @code{when} from before is difficult to get right: + +@example +(define-macro (when cond exp . rest) + `(if ,cond + (begin ,exp . ,rest))) + +(when #f (display "Launching missiles!\n")) +@result{} #f + +(let ((if list)) + (when #f (display "Launching missiles!\n"))) +@print{} Launching missiles! +@result{} (#f #<unspecified>) +@end example + +Guile's perspective is that defmacros have had a good run, but that modern +macros should be written with @code{syntax-rules} or @code{syntax-case}. There +are still many uses of defmacros within Guile itself, but we will be phasing +them out over time. Of course we won't take away @code{defmacro} or +@code{define-macro} themselves, as there is lots of code out there that uses +them. + + +@node Identifier Macros +@subsection Identifier Macros + +When the syntax expander sees a form in which the first element is a macro, the +whole form gets passed to the macro's syntax transformer. One may visualize this +as: + +@example +(define-syntax foo foo-transformer) +(foo @var{arg}...) +;; expands via +(foo-transformer #'(foo @var{arg}...)) +@end example + +If, on the other hand, a macro is referenced in some other part of a form, the +syntax transformer is invoked with only the macro reference, not the whole form. + +@example +(define-syntax foo foo-transformer) +foo +;; expands via +(foo-transformer #'foo) +@end example + +This allows bare identifier references to be replaced programmatically via a +macro. @code{syntax-rules} provides some syntax to effect this transformation +more easily. + +@deffn {Syntax} identifier-syntax exp +Returns a macro transformer that will replace occurrences of the macro with +@var{exp}. +@end deffn + +For example, if you are importing external code written in terms of @code{fx+}, +the fixnum addition operator, but Guile doesn't have @code{fx+}, you may use the +following to replace @code{fx+} with @code{+}: + +@example +(define-syntax fx+ (identifier-syntax +)) +@end example + +There is also special support for recognizing identifiers on the +left-hand side of a @code{set!} expression, as in the following: + +@example +(define-syntax foo foo-transformer) +(set! foo @var{val}) +;; expands via +(foo-transformer #'(set! foo @var{val})) +;; if foo-transformer is a "variable transformer" +@end example + +As the example notes, the transformer procedure must be explicitly +marked as being a ``variable transformer'', as most macros aren't +written to discriminate on the form in the operator position. + +@deffn {Scheme Procedure} make-variable-transformer transformer +Mark the @var{transformer} procedure as being a ``variable +transformer''. In practice this means that, when bound to a syntactic +keyword, it may detect references to that keyword on the left-hand-side +of a @code{set!}. + +@example +(define bar 10) +(define-syntax bar-alias + (make-variable-transformer + (lambda (x) + (syntax-case x (set!) + ((set! var val) #'(set! bar val)) + ((var arg ...) #'(bar arg ...)) + (var (identifier? #'var) #'bar))))) + +bar-alias @result{} 10 +(set! bar-alias 20) +bar @result{} 20 +(set! bar 30) +bar-alias @result{} 30 +@end example +@end deffn + +There is an extension to identifier-syntax which allows it to handle the +@code{set!} case as well: + +@deffn {Syntax} identifier-syntax (var exp1) ((set! var val) exp2) +Create a variable transformer. The first clause is used for references +to the variable in operator or operand position, and the second for +appearances of the variable on the left-hand-side of an assignment. + +For example, the previous @code{bar-alias} example could be expressed +more succinctly like this: + +@example +(define-syntax bar-alias + (identifier-syntax + (var bar) + ((set! var val) (set! bar val)))) +@end example + +@noindent +As before, the templates in @code{identifier-syntax} forms do not need +wrapping in @code{#'} syntax forms. +@end deffn + + +@node Syntax Parameters +@subsection Syntax Parameters + +Syntax parameters@footnote{Described in the paper @cite{Keeping it Clean +with Syntax Parameters} by Barzilay, Culpepper and Flatt.} are a +mechanism for rebinding a macro definition within the dynamic extent of +a macro expansion. This provides a convenient solution to one of the +most common types of unhygienic macro: those that introduce a unhygienic +binding each time the macro is used. Examples include a @code{lambda} +form with a @code{return} keyword, or class macros that introduce a +special @code{self} binding. + +With syntax parameters, instead of introducing the binding +unhygienically each time, we instead create one binding for the keyword, +which we can then adjust later when we want the keyword to have a +different meaning. As no new bindings are introduced, hygiene is +preserved. This is similar to the dynamic binding mechanisms we have at +run-time (@pxref{SRFI-39, parameters}), except that the dynamic binding +only occurs during macro expansion. The code after macro expansion +remains lexically scoped. + +@deffn {Syntax} define-syntax-parameter keyword transformer +Binds @var{keyword} to the value obtained by evaluating +@var{transformer}. The @var{transformer} provides the default expansion +for the syntax parameter, and in the absence of +@code{syntax-parameterize}, is functionally equivalent to +@code{define-syntax}. Usually, you will just want to have the +@var{transformer} throw a syntax error indicating that the @var{keyword} +is supposed to be used in conjunction with another macro, for example: +@example +(define-syntax-parameter return + (lambda (stx) + (syntax-violation 'return "return used outside of a lambda^" stx))) +@end example +@end deffn + +@deffn {Syntax} syntax-parameterize ((keyword transformer) @dots{}) exp @dots{} +Adjusts @var{keyword} @dots{} to use the values obtained by evaluating +their @var{transformer} @dots{}, in the expansion of the @var{exp} +@dots{} forms. Each @var{keyword} must be bound to a syntax-parameter. +@code{syntax-parameterize} differs from @code{let-syntax}, in that the +binding is not shadowed, but adjusted, and so uses of the keyword in the +expansion of @var{exp} @dots{} use the new transformers. This is +somewhat similar to how @code{parameterize} adjusts the values of +regular parameters, rather than creating new bindings. + +@example +(define-syntax lambda^ + (syntax-rules () + [(lambda^ argument-list body body* ...) + (lambda argument-list + (call-with-current-continuation + (lambda (escape) + ;; In the body we adjust the 'return' keyword so that calls + ;; to 'return' are replaced with calls to the escape + ;; continuation. + (syntax-parameterize ([return (syntax-rules () + [(return vals (... ...)) + (escape vals (... ...))])]) + body body* ...))))])) + +;; Now we can write functions that return early. Here, 'product' will +;; return immediately if it sees any 0 element. +(define product + (lambda^ (list) + (fold (lambda (n o) + (if (zero? n) + (return 0) + (* n o))) + 1 + list))) +@end example +@end deffn + + +@node Eval When +@subsection Eval-when + +As @code{syntax-case} macros have the whole power of Scheme available to them, +they present a problem regarding time: when a macro runs, what parts of the +program are available for the macro to use? + +The default answer to this question is that when you import a module (via +@code{define-module} or @code{use-modules}), that module will be loaded up at +expansion-time, as well as at run-time. Additionally, top-level syntactic +definitions within one compilation unit made by @code{define-syntax} are also +evaluated at expansion time, in the order that they appear in the compilation +unit (file). + +But if a syntactic definition needs to call out to a normal procedure at +expansion-time, it might well need need special declarations to indicate that +the procedure should be made available at expansion-time. + +For example, the following code will work at a REPL, but not in a file: + +@example +;; incorrect +(use-modules (srfi srfi-19)) +(define (date) (date->string (current-date))) +(define-syntax %date (identifier-syntax (date))) +(define *compilation-date* %date) +@end example + +It works at a REPL because the expressions are evaluated one-by-one, in order, +but if placed in a file, the expressions are expanded one-by-one, but not +evaluated until the compiled file is loaded. + +The fix is to use @code{eval-when}. + +@example +;; correct: using eval-when +(use-modules (srfi srfi-19)) +(eval-when (expand load eval) + (define (date) (date->string (current-date)))) +(define-syntax %date (identifier-syntax (date))) +(define *compilation-date* %date) +@end example + +@deffn {Syntax} eval-when conditions exp... +Evaluate @var{exp...} under the given @var{conditions}. Valid +conditions include: + +@table @code +@item expand +Evaluate during macro expansion, whether compiling or not. + +@item load +Evaluate during the evaluation phase of compiled code, e.g. when loading +a compiled module or running compiled code at the REPL. + +@item eval +Evaluate during the evaluation phase of non-compiled code. + +@item compile +Evaluate during macro expansion, but only when compiling. +@end table + +In other words, when using the primitive evaluator, @code{eval-when} +expressions with @code{expand} are run during macro expansion, and those +with @code{eval} are run during the evaluation phase. + +When using the compiler, @code{eval-when} expressions with either +@code{expand} or @code{compile} are run during macro expansion, and +those with @code{load} are run during the evaluation phase. + +When in doubt, use the three conditions @code{(expand load eval)}, as in +the example above. Other uses of @code{eval-when} may void your +warranty or poison your cat. +@end deffn + +@node Macro Expansion +@subsection Macro Expansion + +Usually, macros are expanded on behalf of the user as needed. Macro +expansion is an integral part of @code{eval} and @code{compile}. Users +can also expand macros at the REPL prompt via the @code{expand} REPL +command; @xref{Compile Commands}. + +Macros can also be expanded programmatically, via @code{macroexpand}, +but the details get a bit hairy for two reasons. + +The first complication is that the result of macro-expansion isn't +Scheme: it's Tree-IL, Guile's high-level intermediate language. +@xref{Tree-IL}. As ``hygienic macros'' can produce identifiers that are +distinct but have the same name, the output format needs to be able to +represent distinctions between variable identities and names. Again, +@xref{Tree-IL}, for all the details. The easiest thing is to just run +@code{tree-il->scheme} on the result of macro-expansion: + +@lisp +(macroexpand '(+ 1 2)) +@result{} +#<tree-il (call (toplevel +) (const 1) (const 2))> + +(use-modules (language tree-il)) +(tree-il->scheme (macroexpand '(+ 1 2))) +@result{} +(+ 1 2) +@end lisp + +The second complication involves @code{eval-when}. As an example, what +would it mean to macro-expand the definition of a macro? + +@lisp +(macroexpand '(define-syntax qux (identifier-syntax 'bar))) +@result{} +? +@end lisp + +The answer is that it depends who is macro-expanding, and why. Do you +define the macro in the current environment? Residualize a macro +definition? Both? Neither? The default is to expand in ``eval'' mode, +which means an @code{eval-when} clauses will only proceed when +@code{eval} (or @code{expand}) is in its condition set. Top-level +macros will be @code{eval}'d in the top-level environment. + +In this way @code{(macroexpand @var{foo})} is equivalent to +@code{(macroexpand @var{foo} 'e '(eval))}. The second argument is the +mode (@code{'e} for ``eval'') and the third is the +eval-syntax-expanders-when parameter (only @code{eval} in this default +setting). + +But if you are compiling the macro definition, probably you want to +reify the macro definition itself. In that case you pass @code{'c} as +the second argument to @code{macroexpand}. But probably you want the +macro definition to be present at compile time as well, so you pass +@code{'(compile load eval)} as the @var{esew} parameter. In fact +@code{(compile @var{foo} #:to 'tree-il)} is entirely equivalent to +@code{(macroexpand @var{foo} 'c '(compile load eval))}; @xref{The Scheme +Compiler}. + +It's a terrible interface; we know. The macroexpander is somewhat +tricksy regarding modes, so unless you are building a macro-expanding +tool, we suggest to avoid invoking it directly. + + +@node Hygiene and the Top-Level +@subsection Hygiene and the Top-Level + +Consider the following macro. + +@lisp +(define-syntax-rule (defconst name val) + (begin + (define t val) + (define-syntax-rule (name) t))) +@end lisp + +If we use it to make a couple of bindings: + +@lisp +(defconst foo 42) +(defconst bar 37) +@end lisp + +The expansion would look something like this: + +@lisp +(begin + (define t 42) + (define-syntax-rule (foo) t)) +(begin + (define t 37) + (define-syntax-rule (bar) t)) +@end lisp + +As the two @code{t} bindings were introduced by the macro, they should +be introduced hygienically -- and indeed they are, inside a lexical +contour (a @code{let} or some other lexical scope). The @code{t} +reference in @code{foo} is distinct to the reference in @code{bar}. + +At the top-level things are more complicated. Before Guile 2.2, a use +of @code{defconst} at the top-level would not introduce a fresh binding +for @code{t}. This was consistent with a weaselly interpretation of the +Scheme standard, in which all possible bindings may be assumed to exist, +at the top-level, and in which we merely take advantage of toplevel +@code{define} of an existing binding being equivalent to @code{set!}. +But it's not a good reason. + +The solution is to create fresh names for all bindings introduced by +macros -- not just bindings in lexical contours, but also bindings +introduced at the top-level. + +However, the obvious strategy of just giving random names to introduced +toplevel identifiers poses a problem for separate compilation. Consider +without loss of generality a @code{defconst} of @code{foo} in module +@code{a} that introduces the fresh top-level name @code{t-1}. If we +then compile a module @code{b} that uses @code{foo}, there is now a +reference to @code{t-1} in module @code{b}. If module @code{a} is then +expanded again, for whatever reason, for example in a simple +recompilation, the introduced @code{t} gets a fresh name; say, +@code{t-2}. Now module @code{b} has broken because module @code{a} no +longer has a binding for @code{t-1}. + +If introduced top-level identifiers ``escape'' a module, in whatever +way, they then form part of the binary interface (ABI) of a module. It +is unacceptable from an engineering point of view to allow the ABI to +change randomly. (It also poses practical problems in meeting the +recompilation conditions of the Lesser GPL license, for such modules.) +For this reason many people prefer to never use identifier-introducing +macros at the top-level, instead making those macros receive the names +for their introduced identifiers as part of their arguments, or to +construct them programmatically and use @code{datum->syntax}. But this +approach requires omniscience as to the implementation of all macros one +might use, and also limits the expressive power of Scheme macros. + +There is no perfect solution to this issue. Guile does a terrible thing +here. When it goes to introduce a top-level identifier, Guile gives the +identifier a pseudo-fresh name: a name that depends on the hash of the +source expression in which the name occurs. The result in this case is +that the introduced definitions expand as: + +@lisp +(begin + (define t-1dc5e42de7c1050c 42) + (define-syntax-rule (foo) t-1dc5e42de7c1050c)) +(begin + (define t-10cb8ce9fdddd6e9 37) + (define-syntax-rule (bar) t-10cb8ce9fdddd6e9)) +@end lisp + +However, note that as the hash depends solely on the expression +introducing the definition, we also have: + +@lisp +(defconst baz 42) +@result{} (begin + (define t-1dc5e42de7c1050c 42) + (define-syntax-rule (baz) t-1dc5e42de7c1050c)) +@end lisp + +Note that the introduced binding has the same name! This is because the +source expression, @code{(define t 42)}, was the same. Probably you +will never see an error in this area, but it is important to understand +the components of the interface of a module, and that interface may +include macro-introduced identifiers. + + +@node Internal Macros +@subsection Internal Macros + +@deffn {Scheme Procedure} make-syntax-transformer name type binding +Construct a syntax transformer object. This is part of Guile's low-level support +for syntax-case. +@end deffn + +@deffn {Scheme Procedure} macro? obj +@deffnx {C Function} scm_macro_p (obj) +Return @code{#t} if @var{obj} is a syntax transformer, or @code{#f} +otherwise. + +Note that it's a bit difficult to actually get a macro as a first-class object; +simply naming it (like @code{case}) will produce a syntax error. But it is +possible to get these objects using @code{module-ref}: + +@example +(macro? (module-ref (current-module) 'case)) +@result{} #t +@end example +@end deffn + +@deffn {Scheme Procedure} macro-type m +@deffnx {C Function} scm_macro_type (m) +Return the @var{type} that was given when @var{m} was constructed, via +@code{make-syntax-transformer}. +@end deffn + +@deffn {Scheme Procedure} macro-name m +@deffnx {C Function} scm_macro_name (m) +Return the name of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} macro-binding m +@deffnx {C Function} scm_macro_binding (m) +Return the binding of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} macro-transformer m +@deffnx {C Function} scm_macro_transformer (m) +Return the transformer of the macro @var{m}. This will return a procedure, for +which one may ask the docstring. That's the whole reason this section is +documented. Actually a part of the result of @code{macro-binding}. +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-memory.texi b/doc/ref/api-memory.texi new file mode 100644 index 000000000..ce0187b14 --- /dev/null +++ b/doc/ref/api-memory.texi @@ -0,0 +1,436 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2009, 2010, 2012-2016 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Memory Management +@section Memory Management and Garbage Collection + +Guile uses a @emph{garbage collector} to manage most of its objects. +While the garbage collector is designed to be mostly invisible, you +sometimes need to interact with it explicitly. + +See @ref{Garbage Collection} for a general discussion of how garbage +collection relates to using Guile from C. + +@menu +* Garbage Collection Functions:: +* Memory Blocks:: +* Weak References:: +* Guardians:: +@end menu + + +@node Garbage Collection Functions +@subsection Function related to Garbage Collection + +@deffn {Scheme Procedure} gc +@deffnx {C Function} scm_gc () +Finds all of the ``live'' @code{SCM} objects and reclaims for further +use those that are no longer accessible. You normally don't need to +call this function explicitly. Its functionality is invoked +automatically as needed. +@end deffn + +@deftypefn {C Function} SCM scm_gc_protect_object (SCM @var{obj}) +Protects @var{obj} from being freed by the garbage collector, when it +otherwise might be. When you are done with the object, call +@code{scm_gc_unprotect_object} on the object. Calls to +@code{scm_gc_protect_object}/@code{scm_gc_unprotect_object} can be nested, and +the object remains protected until it has been unprotected as many times +as it was protected. It is an error to unprotect an object more times +than it has been protected. Returns the SCM object it was passed. + +Note that storing @var{obj} in a C global variable has the same +effect@footnote{In Guile up to version 1.8, C global variables were not +visited by the garbage collector in the mark phase; hence, +@code{scm_gc_protect_object} was the only way in C to prevent a Scheme +object from being freed.}. +@end deftypefn + +@deftypefn {C Function} SCM scm_gc_unprotect_object (SCM @var{obj}) + +Unprotects an object from the garbage collector which was protected by +@code{scm_gc_unprotect_object}. Returns the SCM object it was passed. +@end deftypefn + +@deftypefn {C Function} SCM scm_permanent_object (SCM @var{obj}) + +Similar to @code{scm_gc_protect_object} in that it causes the +collector to always mark the object, except that it should not be +nested (only call @code{scm_permanent_object} on an object once), and +it has no corresponding unpermanent function. Once an object is +declared permanent, it will never be freed. Returns the SCM object it +was passed. +@end deftypefn + +@c NOTE: The varargs scm_remember_upto_here is deliberately not +@c documented, because we don't think it can be implemented as a nice +@c inline compiler directive or asm block. New _3, _4 or whatever +@c forms could certainly be added though, if needed. + +@deftypefn {C Macro} void scm_remember_upto_here_1 (SCM obj) +@deftypefnx {C Macro} void scm_remember_upto_here_2 (SCM obj1, SCM obj2) +Create a reference to the given object or objects, so they're certain +to be present on the stack or in a register and hence will not be +freed by the garbage collector before this point. + +Note that these functions can only be applied to ordinary C local +variables (ie.@: ``automatics''). Objects held in global or static +variables or some malloced block or the like cannot be protected with +this mechanism. +@end deftypefn + +@deffn {Scheme Procedure} gc-stats +@deffnx {C Function} scm_gc_stats () +Return an association list of statistics about Guile's current +use of storage. +@end deffn + +@deffn {Scheme Procedure} gc-live-object-stats +@deffnx {C Function} scm_gc_live_object_stats () +Return an alist of statistics of the current live objects. +@end deffn + +@deftypefun void scm_gc_mark (SCM @var{x}) +Mark the object @var{x}, and recurse on any objects @var{x} refers to. +If @var{x}'s mark bit is already set, return immediately. This function +must only be called during the mark-phase of garbage collection, +typically from a smob @emph{mark} function. +@end deftypefun + + +@node Memory Blocks +@subsection Memory Blocks + +@cindex automatically-managed memory +@cindex GC-managed memory +@cindex conservative garbage collection + +In C programs, dynamic management of memory blocks is normally done +with the functions malloc, realloc, and free. Guile has additional +functions for dynamic memory allocation that are integrated into the +garbage collector and the error reporting system. + +Memory blocks that are associated with Scheme objects (for example a +foreign object) should be allocated with @code{scm_gc_malloc} or +@code{scm_gc_malloc_pointerless}. These two functions will either +return a valid pointer or signal an error. Memory blocks allocated this +way may be released explicitly; however, this is not strictly needed, +and we recommend @emph{not} calling @code{scm_gc_free}. All memory +allocated with @code{scm_gc_malloc} or @code{scm_gc_malloc_pointerless} +is automatically reclaimed when the garbage collector no longer sees any +live reference to it@footnote{In Guile up to version 1.8, memory +allocated with @code{scm_gc_malloc} @emph{had} to be freed with +@code{scm_gc_free}.}. + +When garbage collection occurs, Guile will visit the words in memory +allocated with @code{scm_gc_malloc}, looking for live pointers. This +means that if @code{scm_gc_malloc}-allocated memory contains a pointer +to some other part of the memory, the garbage collector notices it and +prevents it from being reclaimed@footnote{In Guile up to 1.8, memory +allocated with @code{scm_gc_malloc} was @emph{not} visited by the +collector in the mark phase. Consequently, the GC had to be told +explicitly about pointers to live objects contained in the memory block, +e.g., @i{via} SMOB mark functions (@pxref{Smobs, +@code{scm_set_smob_mark}})}. Conversely, memory allocated with +@code{scm_gc_malloc_pointerless} is assumed to be ``pointer-less'' and +is not scanned for pointers. + +For memory that is not associated with a Scheme object, you can use +@code{scm_malloc} instead of @code{malloc}. Like +@code{scm_gc_malloc}, it will either return a valid pointer or signal +an error. However, it will not assume that the new memory block can +be freed by a garbage collection. The memory must be explicitly freed +with @code{free}. + +There is also @code{scm_gc_realloc} and @code{scm_realloc}, to be used +in place of @code{realloc} when appropriate, and @code{scm_gc_calloc} +and @code{scm_calloc}, to be used in place of @code{calloc} when +appropriate. + +The function @code{scm_dynwind_free} can be useful when memory should be +freed with libc's @code{free} when leaving a dynwind context, +@xref{Dynamic Wind}. + +@deftypefn {C Function} {void *} scm_malloc (size_t @var{size}) +@deftypefnx {C Function} {void *} scm_calloc (size_t @var{size}) +Allocate @var{size} bytes of memory and return a pointer to it. When +@var{size} is 0, return @code{NULL}. When not enough memory is +available, signal an error. This function runs the GC to free up some +memory when it deems it appropriate. + +The memory is allocated by the libc @code{malloc} function and can be +freed with @code{free}. There is no @code{scm_free} function to go +with @code{scm_malloc} to make it easier to pass memory back and forth +between different modules. + +The function @code{scm_calloc} is similar to @code{scm_malloc}, but +initializes the block of memory to zero as well. + +These functions will (indirectly) call +@code{scm_gc_register_allocation}. +@end deftypefn + +@deftypefn {C Function} {void *} scm_realloc (void *@var{mem}, size_t @var{new_size}) +Change the size of the memory block at @var{mem} to @var{new_size} and +return its new location. When @var{new_size} is 0, this is the same +as calling @code{free} on @var{mem} and @code{NULL} is returned. When +@var{mem} is @code{NULL}, this function behaves like @code{scm_malloc} +and allocates a new block of size @var{new_size}. + +When not enough memory is available, signal an error. This function +runs the GC to free up some memory when it deems it appropriate. + +This function will call @code{scm_gc_register_allocation}. +@end deftypefn + + + + +@deftypefn {C Function} {void *} scm_gc_malloc (size_t @var{size}, const char *@var{what}) +@deftypefnx {C Function} {void *} scm_gc_malloc_pointerless (size_t @var{size}, const char *@var{what}) +@deftypefnx {C Function} {void *} scm_gc_realloc (void *@var{mem}, size_t @var{old_size}, size_t @var{new_size}, const char *@var{what}); +@deftypefnx {C Function} {void *} scm_gc_calloc (size_t @var{size}, const char *@var{what}) +Allocate @var{size} bytes of automatically-managed memory. The memory +is automatically freed when no longer referenced from any live memory +block. + +When garbage collection occurs, Guile will visit the words in memory +allocated with @code{scm_gc_malloc} or @code{scm_gc_calloc}, looking for +pointers to other memory allocations that are managed by the GC. In +contrast, memory allocated by @code{scm_gc_malloc_pointerless} is not +scanned for pointers. + +The @code{scm_gc_realloc} call preserves the ``pointerlessness'' of the +memory area pointed to by @var{mem}. Note that you need to pass the old +size of a reallocated memory block as well. See below for a motivation. +@end deftypefn + + +@deftypefn {C Function} void scm_gc_free (void *@var{mem}, size_t @var{size}, const char *@var{what}) +Explicitly free the memory block pointed to by @var{mem}, which was +previously allocated by one of the above @code{scm_gc} functions. This +function is almost always unnecessary, except for codebases that still +need to compile on Guile 1.8. + +Note that you need to explicitly pass the @var{size} parameter. This +is done since it should normally be easy to provide this parameter +(for memory that is associated with GC controlled objects) and help keep +the memory management overhead very low. However, in Guile 2.x, +@var{size} is always ignored. +@end deftypefn + + +@deftypefn {C Function} void scm_gc_register_allocation (size_t @var{size}) +Informs the garbage collector that @var{size} bytes have been allocated, +which the collector would otherwise not have known about. + +In general, Scheme will decide to collect garbage only after some amount +of memory has been allocated. Calling this function will make the +Scheme garbage collector know about more allocation, and thus run more +often (as appropriate). + +It is especially important to call this function when large unmanaged +allocations, like images, may be freed by small Scheme allocations, like +foreign objects. +@end deftypefn + + +@deftypefn {C Function} void scm_dynwind_free (void *mem) +Equivalent to @code{scm_dynwind_unwind_handler (free, @var{mem}, +SCM_F_WIND_EXPLICITLY)}. That is, the memory block at @var{mem} will be +freed (using @code{free} from the C library) when the current dynwind is +left. +@end deftypefn + +@deffn {Scheme Procedure} malloc-stats +Return an alist ((@var{what} . @var{n}) ...) describing number +of malloced objects. +@var{what} is the second argument to @code{scm_gc_malloc}, +@var{n} is the number of objects of that type currently +allocated. + +This function is only available if the @code{GUILE_DEBUG_MALLOC} +preprocessor macro was defined when Guile was compiled. +@end deffn + + +@node Weak References +@subsection Weak References + +[FIXME: This chapter is based on Mikael Djurfeldt's answer to a +question by Michael Livshin. Any mistakes are not theirs, of course. ] + +Weak references let you attach bookkeeping information to data so that +the additional information automatically disappears when the original +data is no longer in use and gets garbage collected. In a weak key hash, +the hash entry for that key disappears as soon as the key is no longer +referenced from anywhere else. For weak value hashes, the same happens +as soon as the value is no longer in use. Entries in a doubly weak hash +disappear when either the key or the value are not used anywhere else +anymore. + +Object properties offer the same kind of functionality as weak key +hashes in many situations. (@pxref{Object Properties}) + +Here's an example (a little bit strained perhaps, but one of the +examples is actually used in Guile): + +Assume that you're implementing a debugging system where you want to +associate information about filename and position of source code +expressions with the expressions themselves. + +Hashtables can be used for that, but if you use ordinary hash tables +it will be impossible for the scheme interpreter to "forget" old +source when, for example, a file is reloaded. + +To implement the mapping from source code expressions to positional +information it is necessary to use weak-key tables since we don't want +the expressions to be remembered just because they are in our table. + +To implement a mapping from source file line numbers to source code +expressions you would use a weak-value table. + +To implement a mapping from source code expressions to the procedures +they constitute a doubly-weak table has to be used. + +@menu +* Weak hash tables:: +* Weak vectors:: +@end menu + + +@node Weak hash tables +@subsubsection Weak hash tables + +@deffn {Scheme Procedure} make-weak-key-hash-table [size] +@deffnx {Scheme Procedure} make-weak-value-hash-table [size] +@deffnx {Scheme Procedure} make-doubly-weak-hash-table [size] +@deffnx {C Function} scm_make_weak_key_hash_table (size) +@deffnx {C Function} scm_make_weak_value_hash_table (size) +@deffnx {C Function} scm_make_doubly_weak_hash_table (size) +Return a weak hash table with @var{size} buckets. As with any +hash table, choosing a good size for the table requires some +caution. + +You can modify weak hash tables in exactly the same way you would modify +regular hash tables, with the exception of the routines that act on +handles. Weak tables have a different implementation behind the scenes +that doesn't have handles. @pxref{Hash Tables}, for more on +@code{hashq-ref} et al. +@end deffn + +Note that in a weak-key hash table, the reference to the value is +strong. This means that if the value references the key, even +indirectly, the key will never be collected, which can lead to a memory +leak. The reverse is true for weak value tables. + +@deffn {Scheme Procedure} weak-key-hash-table? obj +@deffnx {Scheme Procedure} weak-value-hash-table? obj +@deffnx {Scheme Procedure} doubly-weak-hash-table? obj +@deffnx {C Function} scm_weak_key_hash_table_p (obj) +@deffnx {C Function} scm_weak_value_hash_table_p (obj) +@deffnx {C Function} scm_doubly_weak_hash_table_p (obj) +Return @code{#t} if @var{obj} is the specified weak hash +table. Note that a doubly weak hash table is neither a weak key +nor a weak value hash table. +@end deffn + +@node Weak vectors +@subsubsection Weak vectors + +@deffn {Scheme Procedure} make-weak-vector size [fill] +@deffnx {C Function} scm_make_weak_vector (size, fill) +Return a weak vector with @var{size} elements. If the optional +argument @var{fill} is given, all entries in the vector will be +set to @var{fill}. The default value for @var{fill} is the +empty list. +@end deffn + +@deffn {Scheme Procedure} weak-vector elem @dots{} +@deffnx {Scheme Procedure} list->weak-vector l +@deffnx {C Function} scm_weak_vector (l) +Construct a weak vector from a list: @code{weak-vector} uses +the list of its arguments while @code{list->weak-vector} uses +its only argument @var{l} (a list) to construct a weak vector +the same way @code{list->vector} would. +@end deffn + +@deffn {Scheme Procedure} weak-vector? obj +@deffnx {C Function} scm_weak_vector_p (obj) +Return @code{#t} if @var{obj} is a weak vector. +@end deffn + +@deffn {Scheme Procedure} weak-vector-ref wvect k +@deffnx {C Function} scm_weak_vector_ref (wvect, k) +Return the @var{k}th element of the weak vector @var{wvect}, or +@code{#f} if that element has been collected. +@end deffn + +@deffn {Scheme Procedure} weak-vector-set! wvect k elt +@deffnx {C Function} scm_weak_vector_set_x (wvect, k, elt) +Set the @var{k}th element of the weak vector @var{wvect} to @var{elt}. +@end deffn + + +@node Guardians +@subsection Guardians + +Guardians provide a way to be notified about objects that would +otherwise be collected as garbage. Guarding them prevents the objects +from being collected and cleanup actions can be performed on them, for +example. + +See R. Kent Dybvig, Carl Bruggeman, and David Eby (1993) "Guardians in +a Generation-Based Garbage Collector". ACM SIGPLAN Conference on +Programming Language Design and Implementation, June 1993. + +@deffn {Scheme Procedure} make-guardian +@deffnx {C Function} scm_make_guardian () +Create a new guardian. A guardian protects a set of objects from +garbage collection, allowing a program to apply cleanup or other +actions. + +@code{make-guardian} returns a procedure representing the guardian. +Calling the guardian procedure with an argument adds the argument to +the guardian's set of protected objects. Calling the guardian +procedure without an argument returns one of the protected objects +which are ready for garbage collection, or @code{#f} if no such object +is available. Objects which are returned in this way are removed from +the guardian. + +You can put a single object into a guardian more than once and you can +put a single object into more than one guardian. The object will then +be returned multiple times by the guardian procedures. + +An object is eligible to be returned from a guardian when it is no +longer referenced from outside any guardian. + +There is no guarantee about the order in which objects are returned +from a guardian. If you want to impose an order on finalization +actions, for example, you can do that by keeping objects alive in some +global data structure until they are no longer needed for finalizing +other objects. + +Being an element in a weak vector, a key in a hash table with weak +keys, or a value in a hash table with weak values does not prevent an +object from being returned by a guardian. But as long as an object +can be returned from a guardian it will not be removed from such a +weak vector or hash table. In other words, a weak link does not +prevent an object from being considered collectable, but being inside +a guardian prevents a weak link from being broken. + +A key in a weak key hash table can be thought of as having a strong +reference to its associated value as long as the key is accessible. +Consequently, when the key is only accessible from within a guardian, +the reference from the key to the value is also considered to be +coming from within a guardian. Thus, if there is no other reference +to the value, it is eligible to be returned from a guardian. +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi new file mode 100644 index 000000000..8f18b1e62 --- /dev/null +++ b/doc/ref/api-modules.texi @@ -0,0 +1,1155 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2007-2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Modules +@section Modules +@cindex modules + +When programs become large, naming conflicts can occur when a function +or global variable defined in one file has the same name as a function +or global variable in another file. Even just a @emph{similarity} +between function names can cause hard-to-find bugs, since a programmer +might type the wrong function name. + +The approach used to tackle this problem is called @emph{information +encapsulation}, which consists of packaging functional units into a +given name space that is clearly separated from other name spaces. +@cindex encapsulation +@cindex information encapsulation +@cindex name space + +The language features that allow this are usually called @emph{the +module system} because programs are broken up into modules that are +compiled separately (or loaded separately in an interpreter). + +Older languages, like C, have limited support for name space +manipulation and protection. In C a variable or function is public by +default, and can be made local to a module with the @code{static} +keyword. But you cannot reference public variables and functions from +another module with different names. + +More advanced module systems have become a common feature in recently +designed languages: ML, Python, Perl, and Modula 3 all allow the +@emph{renaming} of objects from a foreign module, so they will not +clutter the global name space. +@cindex name space - private + +In addition, Guile offers variables as first-class objects. They can +be used for interacting with the module system. + +@menu +* General Information about Modules:: Guile module basics. +* Using Guile Modules:: How to use existing modules. +* Creating Guile Modules:: How to package your code into modules. +* Modules and the File System:: Installing modules in the file system. +* R6RS Version References:: Using version numbers with modules. +* R6RS Libraries:: The library and import forms. +* Variables:: First-class variables. +* Module System Reflection:: First-class modules. +* Accessing Modules from C:: How to work with modules with C code. +* provide and require:: The SLIB feature mechanism. +* Environments:: R5RS top-level environments. +@end menu + +@node General Information about Modules +@subsection General Information about Modules + +A Guile module can be thought of as a collection of named procedures, +variables and macros. More precisely, it is a set of @dfn{bindings} +of symbols (names) to Scheme objects. + +Within a module, all bindings are visible. Certain bindings +can be declared @dfn{public}, in which case they are added to the +module's so-called @dfn{export list}; this set of public bindings is +called the module's @dfn{public interface} (@pxref{Creating Guile +Modules}). + +A client module @dfn{uses} a providing module's bindings by either +accessing the providing module's public interface, or by building a +custom interface (and then accessing that). In a custom interface, the +client module can @dfn{select} which bindings to access and can also +algorithmically @dfn{rename} bindings. In contrast, when using the +providing module's public interface, the entire export list is available +without renaming (@pxref{Using Guile Modules}). + +All Guile modules have a unique @dfn{module name}, for example +@code{(ice-9 popen)} or @code{(srfi srfi-11)}. Module names are lists +of one or more symbols. + +When Guile goes to use an interface from a module, for example +@code{(ice-9 popen)}, Guile first looks to see if it has loaded +@code{(ice-9 popen)} for any reason. If the module has not been loaded +yet, Guile searches a @dfn{load path} for a file that might define it, +and loads that file. + +The following subsections go into more detail on using, creating, +installing, and otherwise manipulating modules and the module system. + +@node Using Guile Modules +@subsection Using Guile Modules + +To use a Guile module is to access either its public interface or a +custom interface (@pxref{General Information about Modules}). Both +types of access are handled by the syntactic form @code{use-modules}, +which accepts one or more interface specifications and, upon evaluation, +arranges for those interfaces to be available to the current module. +This process may include locating and loading code for a given module if +that code has not yet been loaded, following @code{%load-path} +(@pxref{Modules and the File System}). + +An @dfn{interface specification} has one of two forms. The first +variation is simply to name the module, in which case its public +interface is the one accessed. For example: + +@lisp +(use-modules (ice-9 popen)) +@end lisp + +Here, the interface specification is @code{(ice-9 popen)}, and the +result is that the current module now has access to @code{open-pipe}, +@code{close-pipe}, @code{open-input-pipe}, and so on (@pxref{Pipes}). + +Note in the previous example that if the current module had already +defined @code{open-pipe}, that definition would be overwritten by the +definition in @code{(ice-9 popen)}. For this reason (and others), there +is a second variation of interface specification that not only names a +module to be accessed, but also selects bindings from it and renames +them to suit the current module's needs. For example: + +@cindex binding renamer +@lisp +(use-modules ((ice-9 popen) + #:select ((open-pipe . pipe-open) close-pipe) + #:renamer (symbol-prefix-proc 'unixy:))) +@end lisp + +@noindent +or more simply: + +@cindex prefix +@lisp +(use-modules ((ice-9 popen) + #:select ((open-pipe . pipe-open) close-pipe) + #:prefix unixy:)) +@end lisp + +Here, the interface specification is more complex than before, and the +result is that a custom interface with only two bindings is created and +subsequently accessed by the current module. The mapping of old to new +names is as follows: + +@c Use `smallexample' since `table' is ugly. --ttn +@smallexample +(ice-9 popen) sees: current module sees: +open-pipe unixy:pipe-open +close-pipe unixy:close-pipe +@end smallexample + +This example also shows how to use the convenience procedure +@code{symbol-prefix-proc}. + +You can also directly refer to bindings in a module by using the +@code{@@} syntax. For example, instead of using the +@code{use-modules} statement from above and writing +@code{unixy:pipe-open} to refer to the @code{pipe-open} from the +@code{(ice-9 popen)}, you could also write @code{(@@ (ice-9 popen) +open-pipe)}. Thus an alternative to the complete @code{use-modules} +statement would be + +@lisp +(define unixy:pipe-open (@@ (ice-9 popen) open-pipe)) +(define unixy:close-pipe (@@ (ice-9 popen) close-pipe)) +@end lisp + +There is also @code{@@@@}, which can be used like @code{@@}, but does +not check whether the variable that is being accessed is actually +exported. Thus, @code{@@@@} can be thought of as the impolite version +of @code{@@} and should only be used as a last resort or for +debugging, for example. + +Note that just as with a @code{use-modules} statement, any module that +has not yet been loaded will be loaded when referenced by a @code{@@} or +@code{@@@@} form. + +You can also use the @code{@@} and @code{@@@@} syntaxes as the target +of a @code{set!} when the binding refers to a variable. + +@deffn {Scheme Procedure} symbol-prefix-proc prefix-sym +Return a procedure that prefixes its arg (a symbol) with +@var{prefix-sym}. +@end deffn + +@deffn syntax use-modules spec @dots{} +Resolve each interface specification @var{spec} into an interface and +arrange for these to be accessible by the current module. The return +value is unspecified. + +@var{spec} can be a list of symbols, in which case it names a module +whose public interface is found and used. + +@var{spec} can also be of the form: + +@cindex binding renamer +@lisp + (MODULE-NAME [#:select SELECTION] + [#:prefix PREFIX] + [#:renamer RENAMER]) +@end lisp + +in which case a custom interface is newly created and used. +@var{module-name} is a list of symbols, as above; @var{selection} is a +list of selection-specs; @var{prefix} is a symbol that is prepended to +imported names; and @var{renamer} is a procedure that takes a symbol and +returns its new name. A selection-spec is either a symbol or a pair of +symbols @code{(ORIG . SEEN)}, where @var{orig} is the name in the used +module and @var{seen} is the name in the using module. Note that +@var{seen} is also modified by @var{prefix} and @var{renamer}. + +The @code{#:select}, @code{#:prefix}, and @code{#:renamer} clauses are +optional. If all are omitted, the returned interface has no bindings. +If the @code{#:select} clause is omitted, @var{prefix} and @var{renamer} +operate on the used module's public interface. + +In addition to the above, @var{spec} can also include a @code{#:version} +clause, of the form: + +@lisp + #:version VERSION-SPEC +@end lisp + +where @var{version-spec} is an R6RS-compatible version reference. An +error will be signaled in the case in which a module with the same name +has already been loaded, if that module specifies a version and that +version is not compatible with @var{version-spec}. @xref{R6RS Version +References}, for more on version references. + +If the module name is not resolvable, @code{use-modules} will signal an +error. +@end deffn + +@deffn syntax @@ module-name binding-name +Refer to the binding named @var{binding-name} in module +@var{module-name}. The binding must have been exported by the module. +@end deffn + +@deffn syntax @@@@ module-name binding-name +Refer to the binding named @var{binding-name} in module +@var{module-name}. The binding must not have been exported by the +module. This syntax is only intended for debugging purposes or as a +last resort. +@end deffn + +@node Creating Guile Modules +@subsection Creating Guile Modules + +When you want to create your own modules, you have to take the following +steps: + +@itemize @bullet +@item +Create a Scheme source file and add all variables and procedures you wish +to export, or which are required by the exported procedures. + +@item +Add a @code{define-module} form at the beginning. + +@item +Export all bindings which should be in the public interface, either +by using @code{define-public} or @code{export} (both documented below). +@end itemize + +@deffn syntax define-module module-name option @dots{} +@var{module-name} is a list of one or more symbols. + +@lisp +(define-module (ice-9 popen)) +@end lisp + +@code{define-module} makes this module available to Guile programs under +the given @var{module-name}. + +@var{option} @dots{} are keyword/value pairs which specify more about the +defined module. The recognized options and their meaning are shown in +the following table. + +@table @code +@item #:use-module @var{interface-specification} +Equivalent to a @code{(use-modules @var{interface-specification})} +(@pxref{Using Guile Modules}). + +@item #:autoload @var{module} @var{symbol-list} +@cindex autoload +Load @var{module} when any of @var{symbol-list} are accessed. For +example, + +@example +(define-module (my mod) + #:autoload (srfi srfi-1) (partition delete-duplicates)) +... +(if something + (set! foo (delete-duplicates ...))) +@end example + +When a module is autoloaded, all its bindings become available. +@var{symbol-list} is just those that will first trigger the load. + +An autoload is a good way to put off loading a big module until it's +really needed, for instance for faster startup or if it will only be +needed in certain circumstances. + +@code{@@} can do a similar thing (@pxref{Using Guile Modules}), but in +that case an @code{@@} form must be written every time a binding from +the module is used. + +@item #:export @var{list} +@cindex export +Export all identifiers in @var{list} which must be a list of symbols +or pairs of symbols. This is equivalent to @code{(export @var{list})} +in the module body. + +@item #:re-export @var{list} +@cindex re-export +Re-export all identifiers in @var{list} which must be a list of +symbols or pairs of symbols. The symbols in @var{list} must be +imported by the current module from other modules. This is equivalent +to @code{re-export} below. + +@item #:replace @var{list} +@cindex replace +@cindex replacing binding +@cindex overriding binding +@cindex duplicate binding +Export all identifiers in @var{list} (a list of symbols or pairs of +symbols) and mark them as @dfn{replacing bindings}. In the module +user's name space, this will have the effect of replacing any binding +with the same name that is not also ``replacing''. Normally a +replacement results in an ``override'' warning message, +@code{#:replace} avoids that. + +In general, a module that exports a binding for which the @code{(guile)} +module already has a definition should use @code{#:replace} instead of +@code{#:export}. @code{#:replace}, in a sense, lets Guile know that the +module @emph{purposefully} replaces a core binding. It is important to +note, however, that this binding replacement is confined to the name +space of the module user. In other words, the value of the core binding +in question remains unchanged for other modules. + +Note that although it is often a good idea for the replaced binding to +remain compatible with a binding in @code{(guile)}, to avoid surprising +the user, sometimes the bindings will be incompatible. For example, +SRFI-19 exports its own version of @code{current-time} (@pxref{SRFI-19 +Time}) which is not compatible with the core @code{current-time} +function (@pxref{Time}). Guile assumes that a user importing a module +knows what she is doing, and uses @code{#:replace} for this binding +rather than @code{#:export}. + +A @code{#:replace} clause is equivalent to @code{(export! @var{list})} +in the module body. + +The @code{#:duplicates} (see below) provides fine-grain control about +duplicate binding handling on the module-user side. + +@item #:version @var{list} +@cindex module version +Specify a version for the module in the form of @var{list}, a list of +zero or more exact, nonnegative integers. The corresponding +@code{#:version} option in the @code{use-modules} form allows callers +to restrict the value of this option in various ways. + +@item #:duplicates @var{list} +@cindex duplicate binding handlers +@cindex duplicate binding +@cindex overriding binding +Tell Guile to handle duplicate bindings for the bindings imported by +the current module according to the policy defined by @var{list}, a +list of symbols. @var{list} must contain symbols representing a +duplicate binding handling policy chosen among the following: + +@table @code +@item check +Raises an error when a binding is imported from more than one place. +@item warn +Issue a warning when a binding is imported from more than one place +and leave the responsibility of actually handling the duplication to +the next duplicate binding handler. +@item replace +When a new binding is imported that has the same name as a previously +imported binding, then do the following: + +@enumerate +@item +@cindex replacing binding +If the old binding was said to be @dfn{replacing} (via the +@code{#:replace} option above) and the new binding is not replacing, +the keep the old binding. +@item +If the old binding was not said to be replacing and the new binding is +replacing, then replace the old binding with the new one. +@item +If neither the old nor the new binding is replacing, then keep the old +one. +@end enumerate + +@item warn-override-core +Issue a warning when a core binding is being overwritten and actually +override the core binding with the new one. +@item first +In case of duplicate bindings, the firstly imported binding is always +the one which is kept. +@item last +In case of duplicate bindings, the lastly imported binding is always +the one which is kept. +@item noop +In case of duplicate bindings, leave the responsibility to the next +duplicate handler. +@end table + +If @var{list} contains more than one symbol, then the duplicate +binding handlers which appear first will be used first when resolving +a duplicate binding situation. As mentioned above, some resolution +policies may explicitly leave the responsibility of handling the +duplication to the next handler in @var{list}. + +If GOOPS has been loaded before the @code{#:duplicates} clause is +processed, there are additional strategies available for dealing with +generic functions. @xref{Merging Generics}, for more information. + +@findex default-duplicate-binding-handler +The default duplicate binding resolution policy is given by the +@code{default-duplicate-binding-handler} procedure, and is + +@lisp +(replace warn-override-core warn last) +@end lisp + +@item #:pure +@cindex pure module +Create a @dfn{pure} module, that is a module which does not contain any +of the standard procedure bindings except for the syntax forms. This is +useful if you want to create @dfn{safe} modules, that is modules which +do not know anything about dangerous procedures. +@end table + +@end deffn + +@deffn syntax export variable @dots{} +Add all @var{variable}s (which must be symbols or pairs of symbols) to +the list of exported bindings of the current module. If @var{variable} +is a pair, its @code{car} gives the name of the variable as seen by the +current module and its @code{cdr} specifies a name for the binding in +the current module's public interface. +@end deffn + +@deffn syntax define-public @dots{} +Equivalent to @code{(begin (define foo ...) (export foo))}. +@end deffn + +@deffn syntax re-export variable @dots{} +Add all @var{variable}s (which must be symbols or pairs of symbols) to +the list of re-exported bindings of the current module. Pairs of +symbols are handled as in @code{export}. Re-exported bindings must be +imported by the current module from some other module. +@end deffn + +@deffn syntax export! variable @dots{} +Like @code{export}, but marking the exported variables as replacing. +Using a module with replacing bindings will cause any existing bindings +to be replaced without issuing any warnings. See the discussion of +@code{#:replace} above. +@end deffn + +@node Modules and the File System +@subsection Modules and the File System + +Typical programs only use a small subset of modules installed on a Guile +system. In order to keep startup time down, Guile only loads modules +when a program uses them, on demand. + +When a program evaluates @code{(use-modules (ice-9 popen))}, and the +module is not loaded, Guile searches for a conventionally-named file +from in the @dfn{load path}. + +In this case, loading @code{(ice-9 popen)} will eventually cause Guile +to run @code{(primitive-load-path "ice-9/popen")}. +@code{primitive-load-path} will search for a file @file{ice-9/popen} in +the @code{%load-path} (@pxref{Load Paths}). For each directory in +@code{%load-path}, Guile will try to find the file name, concatenated +with the extensions from @code{%load-extensions}. By default, this will +cause Guile to @code{stat} @file{ice-9/popen.scm}, and then +@file{ice-9/popen}. @xref{Load Paths}, for more on +@code{primitive-load-path}. + +If a corresponding compiled @file{.go} file is found in the +@code{%load-compiled-path} or in the fallback path, and is as fresh as +the source file, it will be loaded instead of the source file. If no +compiled file is found, Guile may try to compile the source file and +cache away the resulting @file{.go} file. @xref{Compilation}, for more +on compilation. + +Once Guile finds a suitable source or compiled file is found, the file +will be loaded. If, after loading the file, the module under +consideration is still not defined, Guile will signal an error. + +For more information on where and how to install Scheme modules, +@xref{Installing Site Packages}. + + +@node R6RS Version References +@subsection R6RS Version References + +Guile's module system includes support for locating modules based on +a declared version specifier of the same form as the one described in +R6RS (@pxref{Library form, R6RS Library Form,, r6rs, The Revised^6 +Report on the Algorithmic Language Scheme}). By using the +@code{#:version} keyword in a @code{define-module} form, a module may +specify a version as a list of zero or more exact, nonnegative integers. + +This version can then be used to locate the module during the module +search process. Client modules and callers of the @code{use-modules} +function may specify constraints on the versions of target modules by +providing a @dfn{version reference}, which has one of the following +forms: + +@lisp + (@var{sub-version-reference} ...) + (and @var{version-reference} ...) + (or @var{version-reference} ...) + (not @var{version-reference}) +@end lisp + +in which @var{sub-version-reference} is in turn one of: + +@lisp + (@var{sub-version}) + (>= @var{sub-version}) + (<= @var{sub-version}) + (and @var{sub-version-reference} ...) + (or @var{sub-version-reference} ...) + (not @var{sub-version-reference}) +@end lisp + +in which @var{sub-version} is an exact, nonnegative integer as above. A +version reference matches a declared module version if each element of +the version reference matches a corresponding element of the module +version, according to the following rules: + +@itemize @bullet +@item +The @code{and} sub-form matches a version or version element if every +element in the tail of the sub-form matches the specified version or +version element. + +@item +The @code{or} sub-form matches a version or version element if any +element in the tail of the sub-form matches the specified version or +version element. + +@item +The @code{not} sub-form matches a version or version element if the tail +of the sub-form does not match the version or version element. + +@item +The @code{>=} sub-form matches a version element if the element is +greater than or equal to the @var{sub-version} in the tail of the +sub-form. + +@item +The @code{<=} sub-form matches a version element if the version is less +than or equal to the @var{sub-version} in the tail of the sub-form. + +@item +A @var{sub-version} matches a version element if one is @var{eqv?} to +the other. +@end itemize + +For example, a module declared as: + +@lisp + (define-module (mylib mymodule) #:version (1 2 0)) +@end lisp + +would be successfully loaded by any of the following @code{use-modules} +expressions: + +@lisp + (use-modules ((mylib mymodule) #:version (1 2 (>= 0)))) + (use-modules ((mylib mymodule) #:version (or (1 2 0) (1 2 1)))) + (use-modules ((mylib mymodule) #:version ((and (>= 1) (not 2)) 2 0))) +@end lisp + + +@node R6RS Libraries +@subsection R6RS Libraries + +In addition to the API described in the previous sections, you also +have the option to create modules using the portable @code{library} form +described in R6RS (@pxref{Library form, R6RS Library Form,, r6rs, The +Revised^6 Report on the Algorithmic Language Scheme}), and to import +libraries created in this format by other programmers. Guile's R6RS +library implementation takes advantage of the flexibility built into the +module system by expanding the R6RS library form into a corresponding +Guile @code{define-module} form that specifies equivalent import and +export requirements and includes the same body expressions. The library +expression: + +@lisp + (library (mylib (1 2)) + (export mybinding) + (import (otherlib (3)))) +@end lisp + +is equivalent to the module definition: + +@lisp + (define-module (mylib) + #:version (1 2) + #:use-module ((otherlib) #:version (3)) + #:export (mybinding)) +@end lisp + +Central to the mechanics of R6RS libraries is the concept of import +and export @dfn{levels}, which control the visibility of bindings at +various phases of a library's lifecycle --- macros necessary to +expand forms in the library's body need to be available at expand +time; variables used in the body of a procedure exported by the +library must be available at runtime. R6RS specifies the optional +@code{for} sub-form of an @emph{import set} specification (see below) +as a mechanism by which a library author can indicate that a +particular library import should take place at a particular phase +with respect to the lifecycle of the importing library. + +Guile's library implementation uses a technique called +@dfn{implicit phasing} (first described by Abdulaziz Ghuloum and R. +Kent Dybvig), which allows the expander and compiler to automatically +determine the necessary visibility of a binding imported from another +library. As such, the @code{for} sub-form described below is ignored by +Guile (but may be required by Schemes in which phasing is explicit). + +@deffn {Scheme Syntax} library name (export export-spec ...) (import import-spec ...) body ... +Defines a new library with the specified name, exports, and imports, +and evaluates the specified body expressions in this library's +environment. + +The library @var{name} is a non-empty list of identifiers, optionally +ending with a version specification of the form described above +(@pxref{Creating Guile Modules}). + +Each @var{export-spec} is the name of a variable defined or imported +by the library, or must take the form +@code{(rename (internal-name external-name) ...)}, where the +identifier @var{internal-name} names a variable defined or imported +by the library and @var{external-name} is the name by which the +variable is seen by importing libraries. + +Each @var{import-spec} must be either an @dfn{import set} (see below) +or must be of the form @code{(for import-set import-level ...)}, +where each @var{import-level} is one of: + +@lisp + run + expand + (meta @var{level}) +@end lisp + +where @var{level} is an integer. Note that since Guile does not +require explicit phase specification, any @var{import-set}s found +inside of @code{for} sub-forms will be ``unwrapped'' during +expansion and processed as if they had been specified directly. + +Import sets in turn take one of the following forms: + +@lisp + @var{library-reference} + (library @var{library-reference}) + (only @var{import-set} @var{identifier} ...) + (except @var{import-set} @var{identifier} ...) + (prefix @var{import-set} @var{identifier}) + (rename @var{import-set} (@var{internal-identifier} @var{external-identifier}) ...) +@end lisp + +where @var{library-reference} is a non-empty list of identifiers +ending with an optional version reference (@pxref{R6RS Version +References}), and the other sub-forms have the following semantics, +defined recursively on nested @var{import-set}s: + +@itemize @bullet + +@item +The @code{library} sub-form is used to specify libraries for import +whose names begin with the identifier ``library.'' + +@item +The @code{only} sub-form imports only the specified @var{identifier}s +from the given @var{import-set}. + +@item +The @code{except} sub-form imports all of the bindings exported by +@var{import-set} except for those that appear in the specified list +of @var{identifier}s. + +@item +The @code{prefix} sub-form imports all of the bindings exported +by @var{import-set}, first prefixing them with the specified +@var{identifier}. + +@item +The @code{rename} sub-form imports all of the identifiers exported +by @var{import-set}. The binding for each @var{internal-identifier} +among these identifiers is made visible to the importing library as +the corresponding @var{external-identifier}; all other bindings are +imported using the names provided by @var{import-set}. + +@end itemize + +Note that because Guile translates R6RS libraries into module +definitions, an import specification may be used to declare a +dependency on a native Guile module --- although doing so may make +your libraries less portable to other Schemes. + +@end deffn + +@deffn {Scheme Syntax} import import-spec ... +Import into the current environment the libraries specified by the +given import specifications, where each @var{import-spec} takes the +same form as in the @code{library} form described above. +@end deffn + + +@node Variables +@subsection Variables +@tpindex Variables + +Each module has its own hash table, sometimes known as an @dfn{obarray}, +that maps the names defined in that module to their corresponding +variable objects. + +A variable is a box-like object that can hold any Scheme value. It is +said to be @dfn{undefined} if its box holds a special Scheme value that +denotes undefined-ness (which is different from all other Scheme values, +including for example @code{#f}); otherwise the variable is +@dfn{defined}. + +On its own, a variable object is anonymous. A variable is said to be +@dfn{bound} when it is associated with a name in some way, usually a +symbol in a module obarray. When this happens, the name is said to be +bound to the variable, in that module. + +(That's the theory, anyway. In practice, defined-ness and bound-ness +sometimes get confused, because Lisp and Scheme implementations have +often conflated --- or deliberately drawn no distinction between --- a +name that is unbound and a name that is bound to a variable whose value +is undefined. We will try to be clear about the difference and explain +any confusion where it is unavoidable.) + +Variables do not have a read syntax. Most commonly they are created and +bound implicitly by @code{define} expressions: a top-level @code{define} +expression of the form + +@lisp +(define @var{name} @var{value}) +@end lisp + +@noindent +creates a variable with initial value @var{value} and binds it to the +name @var{name} in the current module. But they can also be created +dynamically by calling one of the constructor procedures +@code{make-variable} and @code{make-undefined-variable}. + +@deffn {Scheme Procedure} make-undefined-variable +@deffnx {C Function} scm_make_undefined_variable () +Return a variable that is initially unbound. +@end deffn + +@deffn {Scheme Procedure} make-variable init +@deffnx {C Function} scm_make_variable (init) +Return a variable initialized to value @var{init}. +@end deffn + +@deffn {Scheme Procedure} variable-bound? var +@deffnx {C Function} scm_variable_bound_p (var) +Return @code{#t} if @var{var} is bound to a value, or @code{#f} +otherwise. Throws an error if @var{var} is not a variable object. +@end deffn + +@deffn {Scheme Procedure} variable-ref var +@deffnx {C Function} scm_variable_ref (var) +Dereference @var{var} and return its value. +@var{var} must be a variable object; see @code{make-variable} +and @code{make-undefined-variable}. +@end deffn + +@deffn {Scheme Procedure} variable-set! var val +@deffnx {C Function} scm_variable_set_x (var, val) +Set the value of the variable @var{var} to @var{val}. +@var{var} must be a variable object, @var{val} can be any +value. Return an unspecified value. +@end deffn + +@deffn {Scheme Procedure} variable-unset! var +@deffnx {C Function} scm_variable_unset_x (var) +Unset the value of the variable @var{var}, leaving @var{var} unbound. +@end deffn + +@deffn {Scheme Procedure} variable? obj +@deffnx {C Function} scm_variable_p (obj) +Return @code{#t} if @var{obj} is a variable object, else return +@code{#f}. +@end deffn + + +@node Module System Reflection +@subsection Module System Reflection + +The previous sections have described a declarative view of the module +system. You can also work with it programmatically by accessing and +modifying various parts of the Scheme objects that Guile uses to +implement the module system. + +At any time, there is a @dfn{current module}. This module is the one +where a top-level @code{define} and similar syntax will add new +bindings. You can find other module objects with @code{resolve-module}, +for example. + +These module objects can be used as the second argument to @code{eval}. + +@deffn {Scheme Procedure} current-module +@deffnx {C Function} scm_current_module () +Return the current module object. +@end deffn + +@deffn {Scheme Procedure} set-current-module module +@deffnx {C Function} scm_set_current_module (module) +Set the current module to @var{module} and return +the previous current module. +@end deffn + +@deffn {Scheme Procedure} save-module-excursion thunk +Call @var{thunk} within a @code{dynamic-wind} such that the module that +is current at invocation time is restored when @var{thunk}'s dynamic +extent is left (@pxref{Dynamic Wind}). + +More precisely, if @var{thunk} escapes non-locally, the current module +(at the time of escape) is saved, and the original current module (at +the time @var{thunk}'s dynamic extent was last entered) is restored. If +@var{thunk}'s dynamic extent is re-entered, then the current module is +saved, and the previously saved inner module is set current again. +@end deffn + +@deffn {Scheme Procedure} resolve-module name [autoload=#t] [version=#f] @ + [#:ensure=#t] +@deffnx {C Function} scm_resolve_module (name) +Find the module named @var{name} and return it. When it has not already +been defined and @var{autoload} is true, try to auto-load it. When it +can't be found that way either, create an empty module if @var{ensure} +is true, otherwise return @code{#f}. If @var{version} is true, ensure +that the resulting module is compatible with the given version reference +(@pxref{R6RS Version References}). The name is a list of symbols. +@end deffn + +@deffn {Scheme Procedure} resolve-interface name [#:select=#f] @ + [#:hide='()] [#:prefix=#f] @ + [#:renamer=#f] [#:version=#f] +Find the module named @var{name} as with @code{resolve-module} and +return its interface. The interface of a module is also a module +object, but it contains only the exported bindings. +@end deffn + +@deffn {Scheme Procedure} module-uses module +Return a list of the interfaces used by @var{module}. +@end deffn + +@deffn {Scheme Procedure} module-use! module interface +Add @var{interface} to the front of the use-list of @var{module}. Both +arguments should be module objects, and @var{interface} should very +likely be a module returned by @code{resolve-interface}. +@end deffn + +@deffn {Scheme Procedure} reload-module module +Revisit the source file that corresponds to @var{module}. Raises an +error if no source file is associated with the given module. +@end deffn + +As mentioned in the previous section, modules contain a mapping between +identifiers (as symbols) and storage locations (as variables). Guile +defines a number of procedures to allow access to this mapping. If you +are programming in C, @ref{Accessing Modules from C}. + +@deffn {Scheme Procedure} module-variable module name +Return the variable bound to @var{name} (a symbol) in @var{module}, or +@code{#f} if @var{name} is unbound. +@end deffn + +@deffn {Scheme Procedure} module-add! module name var +Define a new binding between @var{name} (a symbol) and @var{var} (a +variable) in @var{module}. +@end deffn + +@deffn {Scheme Procedure} module-ref module name +Look up the value bound to @var{name} in @var{module}. Like +@code{module-variable}, but also does a @code{variable-ref} on the +resulting variable, raising an error if @var{name} is unbound. +@end deffn + +@deffn {Scheme Procedure} module-define! module name value +Locally bind @var{name} to @var{value} in @var{module}. If @var{name} +was already locally bound in @var{module}, i.e., defined locally and not +by an imported module, the value stored in the existing variable will be +updated. Otherwise, a new variable will be added to the module, via +@code{module-add!}. +@end deffn + +@deffn {Scheme Procedure} module-set! module name value +Update the binding of @var{name} in @var{module} to @var{value}, raising +an error if @var{name} is not already bound in @var{module}. +@end deffn + +There are many other reflective procedures available in the default +environment. If you find yourself using one of them, please contact the +Guile developers so that we can commit to stability for that interface. + + +@node Accessing Modules from C +@subsection Accessing Modules from C + +The last sections have described how modules are used in Scheme code, +which is the recommended way of creating and accessing modules. You +can also work with modules from C, but it is more cumbersome. + +The following procedures are available. + +@deftypefn {C Function} SCM scm_c_call_with_current_module (SCM @var{module}, SCM (*@var{func})(void *), void *@var{data}) +Call @var{func} and make @var{module} the current module during the +call. The argument @var{data} is passed to @var{func}. The return +value of @code{scm_c_call_with_current_module} is the return value of +@var{func}. +@end deftypefn + +@deftypefn {C Function} SCM scm_public_variable (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_public_variable ({const char *}@var{module_name}, {const char *}@var{name}) +Find a the variable bound to the symbol @var{name} in the public +interface of the module named @var{module_name}. + +@var{module_name} should be a list of symbols, when represented as a +Scheme object, or a space-separated string, in the @code{const char *} +case. See @code{scm_c_define_module} below, for more examples. + +Signals an error if no module was found with the given name. If +@var{name} is not bound in the module, just returns @code{#f}. +@end deftypefn + +@deftypefn {C Function} SCM scm_private_variable (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_private_variable ({const char *}@var{module_name}, {const char *}@var{name}) +Like @code{scm_public_variable}, but looks in the internals of the +module named @var{module_name} instead of the public interface. +Logically, these procedures should only be called on modules you write. +@end deftypefn + +@deftypefn {C Function} SCM scm_public_lookup (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_public_lookup ({const char *}@var{module_name}, {const char *}@var{name}) +@deftypefnx {C Function} SCM scm_private_lookup (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_private_lookup ({const char *}@var{module_name}, {const char *}@var{name}) +Like @code{scm_public_variable} or @code{scm_private_variable}, but if +the @var{name} is not bound in the module, signals an error. Returns a +variable, always. + +@example +static SCM eval_string_var; + +/* NOTE: It is important that the call to 'my_init' + happens-before all calls to 'my_eval_string'. */ +void my_init (void) +@{ + eval_string_var = scm_c_public_lookup ("ice-9 eval-string", + "eval-string"); +@} + +SCM my_eval_string (SCM str) +@{ + return scm_call_1 (scm_variable_ref (eval_string_var), str); +@} +@end example +@end deftypefn + +@deftypefn {C Function} SCM scm_public_ref (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_public_ref ({const char *}@var{module_name}, {const char *}@var{name}) +@deftypefnx {C Function} SCM scm_private_ref (SCM @var{module_name}, SCM @var{name}) +@deftypefnx {C Function} SCM scm_c_private_ref ({const char *}@var{module_name}, {const char *}@var{name}) +Like @code{scm_public_lookup} or @code{scm_private_lookup}, but +additionally dereferences the variable. If the variable object is +unbound, signals an error. Returns the value bound to @var{name} in +@var{module_name}. +@end deftypefn + +In addition, there are a number of other lookup-related procedures. We +suggest that you use the @code{scm_public_} and @code{scm_private_} +family of procedures instead, if possible. + +@deftypefn {C Function} SCM scm_c_lookup ({const char *}@var{name}) +Return the variable bound to the symbol indicated by @var{name} in the +current module. If there is no such binding or the symbol is not +bound to a variable, signal an error. +@end deftypefn + +@deftypefn {C Function} SCM scm_lookup (SCM @var{name}) +Like @code{scm_c_lookup}, but the symbol is specified directly. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_module_lookup (SCM @var{module}, {const char *}@var{name}) +@deftypefnx {C Function} SCM scm_module_lookup (SCM @var{module}, SCM @var{name}) +Like @code{scm_c_lookup} and @code{scm_lookup}, but the specified +module is used instead of the current one. +@end deftypefn + +@deftypefn {C Function} SCM scm_module_variable (SCM @var{module}, SCM @var{name}) +Like @code{scm_module_lookup}, but if the binding does not exist, just +returns @code{#f} instead of raising an error. +@end deftypefn + +To define a value, use @code{scm_define}: + +@deftypefn {C Function} SCM scm_c_define ({const char *}@var{name}, SCM @var{val}) +Bind the symbol indicated by @var{name} to a variable in the current +module and set that variable to @var{val}. When @var{name} is already +bound to a variable, use that. Else create a new variable. +@end deftypefn + +@deftypefn {C Function} SCM scm_define (SCM @var{name}, SCM @var{val}) +Like @code{scm_c_define}, but the symbol is specified directly. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_module_define (SCM @var{module}, {const char *}@var{name}, SCM @var{val}) +@deftypefnx {C Function} SCM scm_module_define (SCM @var{module}, SCM @var{name}, SCM @var{val}) +Like @code{scm_c_define} and @code{scm_define}, but the specified +module is used instead of the current one. +@end deftypefn + +In some rare cases, you may need to access the variable that +@code{scm_module_define} would have accessed, without changing the +binding of the existing variable, if one is present. In that case, use +@code{scm_module_ensure_local_variable}: + +@deftypefn {C Function} SCM scm_module_ensure_local_variable (SCM @var{module}, SCM @var{sym}) +Like @code{scm_module_define}, but if the @var{sym} is already locally +bound in that module, the variable's existing binding is not reset. +Returns a variable. +@end deftypefn + +@deftypefn {C Function} SCM scm_module_reverse_lookup (SCM @var{module}, SCM @var{variable}) +Find the symbol that is bound to @var{variable} in @var{module}. When no such binding is found, return @code{#f}. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_define_module ({const char *}@var{name}, void (*@var{init})(void *), void *@var{data}) +Define a new module named @var{name} and make it current while +@var{init} is called, passing it @var{data}. Return the module. + +The parameter @var{name} is a string with the symbols that make up +the module name, separated by spaces. For example, @samp{"foo bar"} names +the module @samp{(foo bar)}. + +When there already exists a module named @var{name}, it is used +unchanged, otherwise, an empty module is created. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_resolve_module ({const char *}@var{name}) +Find the module name @var{name} and return it. When it has not +already been defined, try to auto-load it. When it can't be found +that way either, create an empty module. The name is interpreted as +for @code{scm_c_define_module}. +@end deftypefn + +@deftypefn {C Function} SCM scm_c_use_module ({const char *}@var{name}) +Add the module named @var{name} to the uses list of the current +module, as with @code{(use-modules @var{name})}. The name is +interpreted as for @code{scm_c_define_module}. +@end deftypefn + +@deftypefn {C Function} void scm_c_export ({const char *}@var{name}, ...) +Add the bindings designated by @var{name}, ... to the public interface +of the current module. The list of names is terminated by +@code{NULL}. +@end deftypefn + + +@node provide and require +@subsection provide and require + +Aubrey Jaffer, mostly to support his portable Scheme library SLIB, +implemented a provide/require mechanism for many Scheme implementations. +Library files in SLIB @emph{provide} a feature, and when user programs +@emph{require} that feature, the library file is loaded in. + +For example, the file @file{random.scm} in the SLIB package contains the +line + +@lisp +(provide 'random) +@end lisp + +so to use its procedures, a user would type + +@lisp +(require 'random) +@end lisp + +and they would magically become available, @emph{but still have the same +names!} So this method is nice, but not as good as a full-featured +module system. + +When SLIB is used with Guile, provide and require can be used to access +its facilities. + +@node Environments +@subsection Environments +@cindex environment + +Scheme, as defined in R5RS, does @emph{not} have a full module system. +However it does define the concept of a top-level @dfn{environment}. +Such an environment maps identifiers (symbols) to Scheme objects such +as procedures and lists: @ref{About Closure}. In other words, it +implements a set of @dfn{bindings}. + +Environments in R5RS can be passed as the second argument to +@code{eval} (@pxref{Fly Evaluation}). Three procedures are defined to +return environments: @code{scheme-report-environment}, +@code{null-environment} and @code{interaction-environment} (@pxref{Fly +Evaluation}). + +In addition, in Guile any module can be used as an R5RS environment, +i.e., passed as the second argument to @code{eval}. + +Note: the following two procedures are available only when the +@code{(ice-9 r5rs)} module is loaded: + +@lisp +(use-modules (ice-9 r5rs)) +@end lisp + +@deffn {Scheme Procedure} scheme-report-environment version +@deffnx {Scheme Procedure} null-environment version +@var{version} must be the exact integer `5', corresponding to revision +5 of the Scheme report (the Revised^5 Report on Scheme). +@code{scheme-report-environment} returns a specifier for an +environment that is empty except for all bindings defined in the +report that are either required or both optional and supported by the +implementation. @code{null-environment} returns a specifier for an +environment that is empty except for the (syntactic) bindings for all +syntactic keywords defined in the report that are either required or +both optional and supported by the implementation. + +Currently Guile does not support values of @var{version} for other +revisions of the report. + +The effect of assigning (through the use of @code{eval}) a variable +bound in a @code{scheme-report-environment} (for example @code{car}) +is unspecified. Currently the environments specified by +@code{scheme-report-environment} are not immutable in Guile. +@end deffn + + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-options.texi b/doc/ref/api-options.texi new file mode 100644 index 000000000..4a9125e42 --- /dev/null +++ b/doc/ref/api-options.texi @@ -0,0 +1,420 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +@c 2008, 2009, 2010, 2011, 2012, 2013 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Options and Config +@section Configuration, Features and Runtime Options + +Why is my Guile different from your Guile? There are three kinds of +possible variation: + +@itemize @bullet +@item +build differences --- different versions of the Guile source code, +installation directories, configuration flags that control pieces of +functionality being included or left out, etc. + +@item +differences in dynamically loaded code --- behaviour and features +provided by modules that can be dynamically loaded into a running Guile + +@item +different runtime options --- some of the options that are provided for +controlling Guile's behaviour may be set differently. +@end itemize + +Guile provides ``introspective'' variables and procedures to query all +of these possible variations at runtime. For runtime options, it also +provides procedures to change the settings of options and to obtain +documentation on what the options mean. + +@menu +* Build Config:: Build and installation configuration. +* Feature Tracking:: Available features in the Guile process. +* Runtime Options:: Controlling Guile's runtime behaviour. +@end menu + + +@node Build Config +@subsection Configuration, Build and Installation + +The following procedures and variables provide information about how +Guile was configured, built and installed on your system. + +@deffn {Scheme Procedure} version +@deffnx {Scheme Procedure} effective-version +@deffnx {Scheme Procedure} major-version +@deffnx {Scheme Procedure} minor-version +@deffnx {Scheme Procedure} micro-version +@deffnx {C Function} scm_version () +@deffnx {C Function} scm_effective_version () +@deffnx {C Function} scm_major_version () +@deffnx {C Function} scm_minor_version () +@deffnx {C Function} scm_micro_version () +Return a string describing Guile's full version number, effective +version number, major, minor or micro version number, respectively. +The @code{effective-version} function returns the version name that +should remain unchanged during a stable series. Currently that means +that it omits the micro version. The effective version should be used +for items like the versioned share directory name +i.e.@: @file{/usr/share/guile/3.0/} + +@lisp +(version) @result{} "3.0.0" +(effective-version) @result{} "3.0" +(major-version) @result{} "3" +(minor-version) @result{} "0" +(micro-version) @result{} "0" +@end lisp +@end deffn + +@deffn {Scheme Procedure} %package-data-dir +@deffnx {C Function} scm_sys_package_data_dir () +Return the name of the directory under which Guile Scheme files in +general are stored. On Unix-like systems, this is usually +@file{/usr/local/share/guile} or @file{/usr/share/guile}. +@end deffn + +@deffn {Scheme Procedure} %library-dir +@deffnx {C Function} scm_sys_library_dir () +Return the name of the directory where the Guile Scheme files that +belong to the core Guile installation (as opposed to files from a 3rd +party package) are installed. On Unix-like systems this is usually +@file{/usr/local/share/guile/@var{GUILE_EFFECTIVE_VERSION}} or +@file{/usr/share/guile/@var{GUILE_EFFECTIVE_VERSION}}; + +@noindent +for example @file{/usr/local/share/guile/3.0}. +@end deffn + +@deffn {Scheme Procedure} %site-dir +@deffnx {C Function} scm_sys_site_dir () +Return the name of the directory where Guile Scheme files specific to +your site should be installed. On Unix-like systems, this is usually +@file{/usr/local/share/guile/site} or @file{/usr/share/guile/site}. +@end deffn + +@deffn {Scheme Procedure} %site-ccache-dir +@deffnx {C Function} scm_sys_site_ccache_dir () +Return the directory where users should install compiled @code{.go} +files for use with this version of Guile. Might look something like +@file{/usr/lib/guile/@value{EFFECTIVE-VERSION}/site-ccache}. +@end deffn + +@defvar %guile-build-info +Alist of information collected during the building of a particular +Guile. Entries can be grouped into one of several categories: +directories, env vars, and versioning info. + +Briefly, here are the keys in @code{%guile-build-info}, by group: + +@cindex @code{srcdir} +@cindex @code{top_srcdir} +@cindex @code{prefix} +@cindex @code{exec_prefix} +@cindex @code{bindir} +@cindex @code{sbindir} +@cindex @code{libexecdir} +@cindex @code{datadir} +@cindex @code{sysconfdir} +@cindex @code{sharedstatedir} +@cindex @code{localstatedir} +@cindex @code{libdir} +@cindex @code{infodir} +@cindex @code{mandir} +@cindex @code{includedir} +@cindex @code{pkgdatadir} +@cindex @code{pkglibdir} +@cindex @code{pkgincludedir} +@table @asis +@item directories +srcdir, top_srcdir, prefix, exec_prefix, bindir, sbindir, libexecdir, +datadir, sysconfdir, sharedstatedir, localstatedir, libdir, infodir, +mandir, includedir, pkgdatadir, pkglibdir, pkgincludedir +@cindex @code{LIBS} +@item env vars +LIBS +@cindex @code{guileversion} +@cindex @code{libguileinterface} +@cindex @code{buildstamp} +@item versioning info +guileversion, libguileinterface, buildstamp +@end table + +Values are all strings. The value for @code{LIBS} is typically found +also as a part of @code{pkg-config --libs +guile-@value{EFFECTIVE-VERSION}} output. The value for +@code{guileversion} has form X.Y.Z, and should be the same as returned +by @code{(version)}. The value for @code{libguileinterface} is libtool +compatible and has form CURRENT:REVISION:AGE (@pxref{Versioning,, +Library interface versions, libtool, GNU Libtool}). The value for +@code{buildstamp} is the output of the command @samp{date -u +'%Y-%m-%d +%T'} (UTC). + +In the source, @code{%guile-build-info} is initialized from +libguile/libpath.h, which is completely generated, so deleting this file +before a build guarantees up-to-date values for that build. +@end defvar + +@cindex GNU triplet +@cindex canonical host type + +@defvar %host-type +The canonical host type (GNU triplet) of the host Guile was configured +for, e.g., @code{"x86_64-unknown-linux-gnu"} (@pxref{Canonicalizing,,, +autoconf, The GNU Autoconf Manual}). +@end defvar + +@node Feature Tracking +@subsection Feature Tracking + +Guile has a Scheme level variable @code{*features*} that keeps track to +some extent of the features that are available in a running Guile. +@code{*features*} is a list of symbols, for example @code{threads}, each +of which describes a feature of the running Guile process. + +@defvar *features* +A list of symbols describing available features of the Guile process. +@end defvar + +You shouldn't modify the @code{*features*} variable directly using +@code{set!}. Instead, see the procedures that are provided for this +purpose in the following subsection. + +@menu +* Feature Manipulation:: Checking for and advertising features. +* Common Feature Symbols:: Commonly available features. +@end menu + + +@node Feature Manipulation +@subsubsection Feature Manipulation + +To check whether a particular feature is available, use the +@code{provided?} procedure: + +@deffn {Scheme Procedure} provided? feature +@deffnx {Deprecated Scheme Procedure} feature? feature +Return @code{#t} if the specified @var{feature} is available, otherwise +@code{#f}. +@end deffn + +To advertise a feature from your own Scheme code, you can use the +@code{provide} procedure: + +@deffn {Scheme Procedure} provide feature +Add @var{feature} to the list of available features in this Guile +process. +@end deffn + +For C code, the equivalent function takes its feature name as a +@code{char *} argument for convenience: + +@deftypefn {C Function} void scm_add_feature (const char *str) +Add a symbol with name @var{str} to the list of available features in +this Guile process. +@end deftypefn + + +@node Common Feature Symbols +@subsubsection Common Feature Symbols + +In general, a particular feature may be available for one of two +reasons. Either because the Guile library was configured and compiled +with that feature enabled --- i.e.@: the feature is built into the library +on your system. Or because some C or Scheme code that was dynamically +loaded by Guile has added that feature to the list. + +In the first category, here are the features that the current version of +Guile may define (depending on how it is built), and what they mean. + +@table @code +@item array +Indicates support for arrays (@pxref{Arrays}). + +@item array-for-each +Indicates availability of @code{array-for-each} and other array mapping +procedures (@pxref{Arrays}). + +@item char-ready? +Indicates that the @code{char-ready?} function is available +(@pxref{Venerable Port Interfaces}). + +@item complex +Indicates support for complex numbers. + +@item current-time +Indicates availability of time-related functions: @code{times}, +@code{get-internal-run-time} and so on (@pxref{Time}). + +@item debug-extensions +Indicates that the debugging evaluator is available, together with the +options for controlling it. + +@item delay +Indicates support for promises (@pxref{Delayed Evaluation}). + +@item EIDs +Indicates that the @code{geteuid} and @code{getegid} really return +effective user and group IDs (@pxref{Processes}). + +@item inexact +Indicates support for inexact numbers. + +@item i/o-extensions +Indicates availability of the following extended I/O procedures: +@code{ftell}, @code{redirect-port}, @code{dup->fdes}, @code{dup2}, +@code{fileno}, @code{isatty?}, @code{fdopen}, +@code{primitive-move->fdes} and @code{fdes->ports} (@pxref{Ports and +File Descriptors}). + +@item net-db +Indicates availability of network database functions: +@code{scm_gethost}, @code{scm_getnet}, @code{scm_getproto}, +@code{scm_getserv}, @code{scm_sethost}, @code{scm_setnet}, @code{scm_setproto}, +@code{scm_setserv}, and their `byXXX' variants (@pxref{Network +Databases}). + +@item posix +Indicates support for POSIX functions: @code{pipe}, @code{getgroups}, +@code{kill}, @code{execl} and so on (@pxref{POSIX}). + +@item fork +Indicates support for the POSIX @code{fork} function (@pxref{Processes, +@code{primitive-fork}}). + +@item popen +Indicates support for @code{open-pipe} in the @code{(ice-9 popen)} +module (@pxref{Pipes}). + +@item random +Indicates availability of random number generation functions: +@code{random}, @code{copy-random-state}, @code{random-uniform} and so on +(@pxref{Random}). + +@item reckless +Indicates that Guile was built with important checks omitted --- you +should never see this! + +@item regex +Indicates support for POSIX regular expressions using +@code{make-regexp}, @code{regexp-exec} and friends (@pxref{Regexp +Functions}). + +@item socket +Indicates availability of socket-related functions: @code{socket}, +@code{bind}, @code{connect} and so on (@pxref{Network Sockets and +Communication}). + +@item sort +Indicates availability of sorting and merging functions +(@pxref{Sorting}). + +@item system +Indicates that the @code{system} function is available +(@pxref{Processes}). + +@item threads +Indicates support for multithreading (@pxref{Threads}). + +@item values +Indicates support for multiple return values using @code{values} and +@code{call-with-values} (@pxref{Multiple Values}). +@end table + +Available features in the second category depend, by definition, on what +additional code your Guile process has loaded in. The following table +lists features that you might encounter for this reason. + +@table @code +@item defmacro +Indicates that the @code{defmacro} macro is available (@pxref{Macros}). + +@item describe +Indicates that the @code{(oop goops describe)} module has been loaded, +which provides a procedure for describing the contents of GOOPS +instances. + +@item readline +Indicates that Guile has loaded in Readline support, for command line +editing (@pxref{Readline Support}). + +@item record +Indicates support for record definition using @code{make-record-type} +and friends (@pxref{Records}). +@end table + +Although these tables may seem exhaustive, it is probably unwise in +practice to rely on them, as the correspondences between feature symbols +and available procedures/behaviour are not strictly defined. If you are +writing code that needs to check for the existence of some procedure, it +is probably safer to do so directly using the @code{defined?} procedure +than to test for the corresponding feature using @code{provided?}. + + +@node Runtime Options +@subsection Runtime Options + +There are a number of runtime options available for paramaterizing +built-in procedures, like @code{read}, and built-in behavior, like what +happens on an uncaught error. + +For more information on reader options, @xref{Scheme Read}. + +For more information on print options, @xref{Scheme Write}. + +Finally, for more information on debugger options, @xref{Debug +Options}. + +@subsubsection Examples of option use + +Here is an example of a session in which some read and debug option +handling procedures are used. In this example, the user + +@enumerate +@item +Notices that the symbols @code{abc} and @code{aBc} are not the same +@item +Examines the @code{read-options}, and sees that @code{case-insensitive} +is set to ``no''. +@item +Enables @code{case-insensitive} +@item +Quits the recursive prompt +@item +Verifies that now @code{aBc} and @code{abc} are the same +@end enumerate + +@smalllisp +scheme@@(guile-user)> (define abc "hello") +scheme@@(guile-user)> abc +$1 = "hello" +scheme@@(guile-user)> aBc +<unknown-location>: warning: possibly unbound variable `aBc' +ERROR: In procedure module-lookup: +ERROR: Unbound variable: aBc +Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. +scheme@@(guile-user) [1]> (read-options 'help) +copy no Copy source code expressions. +positions yes Record positions of source code expressions. +case-insensitive no Convert symbols to lower case. +keywords #f Style of keyword recognition: #f, 'prefix or 'postfix. +r6rs-hex-escapes no Use R6RS variable-length character and string hex escapes. +square-brackets yes Treat `[' and `]' as parentheses, for R6RS compatibility. +hungry-eol-escapes no In strings, consume leading whitespace after an + escaped end-of-line. +curly-infix no Support SRFI-105 curly infix expressions. +scheme@@(guile-user) [1]> (read-enable 'case-insensitive) +$2 = (square-brackets keywords #f case-insensitive positions) +scheme@@(guile-user) [1]> ,q +scheme@@(guile-user)> aBc +$3 = "hello" +@end smalllisp + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-overview.texi b/doc/ref/api-overview.texi new file mode 100644 index 000000000..56ca7924e --- /dev/null +++ b/doc/ref/api-overview.texi @@ -0,0 +1,111 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node API Overview +@section Overview of the Guile API + +Guile's application programming interface (@dfn{API}) makes +functionality available that an application developer can use in either +C or Scheme programming. The interface consists of @dfn{elements} that +may be macros, functions or variables in C, and procedures, variables, +syntax or other types of object in Scheme. + +Many elements are available to both Scheme and C, in a form that is +appropriate. For example, the @code{assq} Scheme procedure is also +available as @code{scm_assq} to C code. These elements are documented +only once, addressing both the Scheme and C aspects of them. + +The Scheme name of an element is related to its C name in a regular +way. Also, a C function takes its parameters in a systematic way. + +Normally, the name of a C function can be derived given its Scheme name, +using some simple textual transformations: + +@itemize @bullet + +@item +Replace @code{-} (hyphen) with @code{_} (underscore). + +@item +Replace @code{?} (question mark) with @code{_p}. + +@item +Replace @code{!} (exclamation point) with @code{_x}. + +@item +Replace internal @code{->} with @code{_to_}. + +@item +Replace @code{<=} (less than or equal) with @code{_leq}. + +@item +Replace @code{>=} (greater than or equal) with @code{_geq}. + +@item +Replace @code{<} (less than) with @code{_less}. + +@item +Replace @code{>} (greater than) with @code{_gr}. + +@item +Prefix with @code{scm_}. + +@end itemize + +@c Here is an Emacs Lisp command that prompts for a Scheme function name and +@c inserts the corresponding C function name into the buffer. + +@c @example +@c (defun insert-scheme-to-C (name &optional use-gh) +@c "Transforms Scheme NAME, a string, to its C counterpart, and inserts it. +@c Prefix arg non-nil means use \"gh_\" prefix, otherwise use \"scm_\" prefix." +@c (interactive "sScheme name: \nP") +@c (let ((transforms '(("-" . "_") +@c ("?" . "_p") +@c ("!" . "_x") +@c ("->" . "_to_") +@c ("<=" . "_leq") +@c (">=" . "_geq") +@c ("<" . "_less") +@c (">" . "_gr") +@c ("@@" . "at")))) +@c (while transforms +@c (let ((trigger (concat "\\(.*\\)" +@c (regexp-quote (caar transforms)) +@c "\\(.*\\)")) +@c (sub (cdar transforms)) +@c (m nil)) +@c (while (setq m (string-match trigger name)) +@c (setq name (concat (match-string 1 name) +@c sub +@c (match-string 2 name))))) +@c (setq transforms (cdr transforms)))) +@c (insert (if use-gh "gh_" "scm_") name)) +@c @end example + +A C function always takes a fixed number of arguments of type +@code{SCM}, even when the corresponding Scheme function takes a +variable number. + +For some Scheme functions, some last arguments are optional; the +corresponding C function must always be invoked with all optional +arguments specified. To get the effect as if an argument has not been +specified, pass @code{SCM_UNDEFINED} as its value. You can not do +this for an argument in the middle; when one argument is +@code{SCM_UNDEFINED} all the ones following it must be +@code{SCM_UNDEFINED} as well. + +Some Scheme functions take an arbitrary number of @emph{rest} +arguments; the corresponding C function must be invoked with a list of +all these arguments. This list is always the last argument of the C +function. + +These two variants can also be combined. + +The type of the return value of a C function that corresponds to a +Scheme function is always @code{SCM}. In the descriptions below, +types are therefore often omitted but for the return value and for the +arguments. diff --git a/doc/ref/api-peg.texi b/doc/ref/api-peg.texi new file mode 100644 index 000000000..82e2758b4 --- /dev/null +++ b/doc/ref/api-peg.texi @@ -0,0 +1,1037 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2006, 2010, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node PEG Parsing +@section PEG Parsing + +Parsing Expression Grammars (PEGs) are a way of specifying formal +languages for text processing. They can be used either for matching +(like regular expressions) or for building recursive descent parsers +(like lex/yacc). Guile uses a superset of PEG syntax that allows more +control over what information is preserved during parsing. + +Wikipedia has a clear and concise introduction to PEGs if you want to +familiarize yourself with the syntax: +@url{http://en.wikipedia.org/wiki/Parsing_expression_grammar}. + +The @code{(ice-9 peg)} module works by compiling PEGs down to lambda +expressions. These can either be stored in variables at compile-time by +the define macros (@code{define-peg-pattern} and +@code{define-peg-string-patterns}) or calculated explicitly at runtime +with the compile functions (@code{compile-peg-pattern} and +@code{peg-string-compile}). + +They can then be used for either parsing (@code{match-pattern}) or searching +(@code{search-for-pattern}). For convenience, @code{search-for-pattern} +also takes pattern literals in case you want to inline a simple search +(people often use regular expressions this way). + +The rest of this documentation consists of a syntax reference, an API +reference, and a tutorial. + +@menu +* PEG Syntax Reference:: +* PEG API Reference:: +* PEG Tutorial:: +* PEG Internals:: +@end menu + +@node PEG Syntax Reference +@subsection PEG Syntax Reference + +@subsubheading Normal PEG Syntax: + +@deftp {PEG Pattern} sequence a b +Parses @var{a}. If this succeeds, continues to parse @var{b} from the +end of the text parsed as @var{a}. Succeeds if both @var{a} and +@var{b} succeed. + +@code{"a b"} + +@code{(and a b)} +@end deftp + +@deftp {PEG Pattern} {ordered choice} a b +Parses @var{a}. If this fails, backtracks and parses @var{b}. +Succeeds if either @var{a} or @var{b} succeeds. + +@code{"a/b"} + +@code{(or a b)} +@end deftp + +@deftp {PEG Pattern} {zero or more} a +Parses @var{a} as many times in a row as it can, starting each @var{a} +at the end of the text parsed by the previous @var{a}. Always +succeeds. + +@code{"a*"} + +@code{(* a)} +@end deftp + +@deftp {PEG Pattern} {one or more} a +Parses @var{a} as many times in a row as it can, starting each @var{a} +at the end of the text parsed by the previous @var{a}. Succeeds if at +least one @var{a} was parsed. + +@code{"a+"} + +@code{(+ a)} +@end deftp + +@deftp {PEG Pattern} optional a +Tries to parse @var{a}. Succeeds if @var{a} succeeds. + +@code{"a?"} + +@code{(? a)} +@end deftp + +@deftp {PEG Pattern} {followed by} a +Makes sure it is possible to parse @var{a}, but does not actually parse +it. Succeeds if @var{a} would succeed. + +@code{"&a"} + +@code{(followed-by a)} +@end deftp + +@deftp {PEG Pattern} {not followed by} a +Makes sure it is impossible to parse @var{a}, but does not actually +parse it. Succeeds if @var{a} would fail. + +@code{"!a"} + +@code{(not-followed-by a)} +@end deftp + +@deftp {PEG Pattern} {string literal} ``abc'' +Parses the string @var{"abc"}. Succeeds if that parsing succeeds. + +@code{"'abc'"} + +@code{"abc"} +@end deftp + +@deftp {PEG Pattern} {any character} +Parses any single character. Succeeds unless there is no more text to +be parsed. + +@code{"."} + +@code{peg-any} +@end deftp + +@deftp {PEG Pattern} {character class} a b +Alternative syntax for ``Ordered Choice @var{a} @var{b}'' if @var{a} and +@var{b} are characters. + +@code{"[ab]"} + +@code{(or "a" "b")} +@end deftp + +@deftp {PEG Pattern} {range of characters} a z +Parses any character falling between @var{a} and @var{z}. + +@code{"[a-z]"} + +@code{(range #\a #\z)} +@end deftp + +Example: + +@example +"(a !b / c &d*) 'e'+" +@end example + +Would be: + +@lisp +(and + (or + (and a (not-followed-by b)) + (and c (followed-by (* d)))) + (+ "e")) +@end lisp + +@subsubheading Extended Syntax + +There is some extra syntax for S-expressions. + +@deftp {PEG Pattern} ignore a +Ignore the text matching @var{a} +@end deftp + +@deftp {PEG Pattern} capture a +Capture the text matching @var{a}. +@end deftp + +@deftp {PEG Pattern} peg a +Embed the PEG pattern @var{a} using string syntax. +@end deftp + +Example: + +@example +"!a / 'b'" +@end example + +Is equivalent to + +@lisp +(or (peg "!a") "b") +@end lisp + +and + +@lisp +(or (not-followed-by a) "b") +@end lisp + +@node PEG API Reference +@subsection PEG API Reference + +@subsubheading Define Macros + +The most straightforward way to define a PEG is by using one of the +define macros (both of these macroexpand into @code{define} +expressions). These macros bind parsing functions to variables. These +parsing functions may be invoked by @code{match-pattern} or +@code{search-for-pattern}, which return a PEG match record. Raw data can be +retrieved from this record with the PEG match deconstructor functions. +More complicated (and perhaps enlightening) examples can be found in the +tutorial. + +@deffn {Scheme Macro} define-peg-string-patterns peg-string +Defines all the nonterminals in the PEG @var{peg-string}. More +precisely, @code{define-peg-string-patterns} takes a superset of PEGs. A normal PEG +has a @code{<-} between the nonterminal and the pattern. +@code{define-peg-string-patterns} uses this symbol to determine what information it +should propagate up the parse tree. The normal @code{<-} propagates the +matched text up the parse tree, @code{<--} propagates the matched text +up the parse tree tagged with the name of the nonterminal, and @code{<} +discards that matched text and propagates nothing up the parse tree. +Also, nonterminals may consist of any alphanumeric character or a ``-'' +character (in normal PEGs nonterminals can only be alphabetic). + +For example, if we: +@lisp +(define-peg-string-patterns + "as <- 'a'+ +bs <- 'b'+ +as-or-bs <- as/bs") +(define-peg-string-patterns + "as-tag <-- 'a'+ +bs-tag <-- 'b'+ +as-or-bs-tag <-- as-tag/bs-tag") +@end lisp +Then: +@lisp +(match-pattern as-or-bs "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> +(match-pattern as-or-bs-tag "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: (as-or-bs-tag (as-tag aa))> +@end lisp + +Note that in doing this, we have bound 6 variables at the toplevel +(@var{as}, @var{bs}, @var{as-or-bs}, @var{as-tag}, @var{bs-tag}, and +@var{as-or-bs-tag}). +@end deffn + +@deffn {Scheme Macro} define-peg-pattern name capture-type peg-sexp +Defines a single nonterminal @var{name}. @var{capture-type} determines +how much information is passed up the parse tree. @var{peg-sexp} is a +PEG in S-expression form. + +Possible values for capture-type: + +@table @code +@item all +passes the matched text up the parse tree tagged with the name of the +nonterminal. +@item body +passes the matched text up the parse tree. +@item none +passes nothing up the parse tree. +@end table + +For Example, if we: +@lisp +(define-peg-pattern as body (+ "a")) +(define-peg-pattern bs body (+ "b")) +(define-peg-pattern as-or-bs body (or as bs)) +(define-peg-pattern as-tag all (+ "a")) +(define-peg-pattern bs-tag all (+ "b")) +(define-peg-pattern as-or-bs-tag all (or as-tag bs-tag)) +@end lisp +Then: +@lisp +(match-pattern as-or-bs "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> +(match-pattern as-or-bs-tag "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: (as-or-bs-tag (as-tag aa))> +@end lisp + +Note that in doing this, we have bound 6 variables at the toplevel +(@var{as}, @var{bs}, @var{as-or-bs}, @var{as-tag}, @var{bs-tag}, and +@var{as-or-bs-tag}). +@end deffn + +@subsubheading Compile Functions +It is sometimes useful to be able to compile anonymous PEG patterns at +runtime. These functions let you do that using either syntax. + +@deffn {Scheme Procedure} peg-string-compile peg-string capture-type +Compiles the PEG pattern in @var{peg-string} propagating according to +@var{capture-type} (capture-type can be any of the values from +@code{define-peg-pattern}). +@end deffn + + +@deffn {Scheme Procedure} compile-peg-pattern peg-sexp capture-type +Compiles the PEG pattern in @var{peg-sexp} propagating according to +@var{capture-type} (capture-type can be any of the values from +@code{define-peg-pattern}). +@end deffn + +The functions return syntax objects, which can be useful if you want to +use them in macros. If all you want is to define a new nonterminal, you +can do the following: + +@lisp +(define exp '(+ "a")) +(define as (compile (compile-peg-pattern exp 'body))) +@end lisp + +You can use this nonterminal with all of the regular PEG functions: + +@lisp +(match-pattern as "aaaaa") @result{} +#<peg start: 0 end: 5 string: bbbbb tree: bbbbb> +@end lisp + +@subsubheading Parsing & Matching Functions + +For our purposes, ``parsing'' means parsing a string into a tree +starting from the first character, while ``matching'' means searching +through the string for a substring. In practice, the only difference +between the two functions is that @code{match-pattern} gives up if it can't +find a valid substring starting at index 0 and @code{search-for-pattern} keeps +looking. They are both equally capable of ``parsing'' and ``matching'' +given those constraints. + +@deffn {Scheme Procedure} match-pattern nonterm string +Parses @var{string} using the PEG stored in @var{nonterm}. If no match +was found, @code{match-pattern} returns false. If a match was found, a PEG +match record is returned. + +The @code{capture-type} argument to @code{define-peg-pattern} allows you to +choose what information to hold on to while parsing. The options are: + +@table @code +@item all +tag the matched text with the nonterminal +@item body +just the matched text +@item none +nothing +@end table + +@lisp +(define-peg-pattern as all (+ "a")) +(match-pattern as "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: (as aa)> + +(define-peg-pattern as body (+ "a")) +(match-pattern as "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> + +(define-peg-pattern as none (+ "a")) +(match-pattern as "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: ()> + +(define-peg-pattern bs body (+ "b")) +(match-pattern bs "aabbcc") @result{} +#f +@end lisp +@end deffn + +@deffn {Scheme Macro} search-for-pattern nonterm-or-peg string +Searches through @var{string} looking for a matching subexpression. +@var{nonterm-or-peg} can either be a nonterminal or a literal PEG +pattern. When a literal PEG pattern is provided, @code{search-for-pattern} works +very similarly to the regular expression searches many hackers are used +to. If no match was found, @code{search-for-pattern} returns false. If a match +was found, a PEG match record is returned. + +@lisp +(define-peg-pattern as body (+ "a")) +(search-for-pattern as "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> +(search-for-pattern (+ "a") "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> +(search-for-pattern "'a'+" "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: aa> + +(define-peg-pattern as all (+ "a")) +(search-for-pattern as "aabbcc") @result{} +#<peg start: 0 end: 2 string: aabbcc tree: (as aa)> + +(define-peg-pattern bs body (+ "b")) +(search-for-pattern bs "aabbcc") @result{} +#<peg start: 2 end: 4 string: aabbcc tree: bb> +(search-for-pattern (+ "b") "aabbcc") @result{} +#<peg start: 2 end: 4 string: aabbcc tree: bb> +(search-for-pattern "'b'+" "aabbcc") @result{} +#<peg start: 2 end: 4 string: aabbcc tree: bb> + +(define-peg-pattern zs body (+ "z")) +(search-for-pattern zs "aabbcc") @result{} +#f +(search-for-pattern (+ "z") "aabbcc") @result{} +#f +(search-for-pattern "'z'+" "aabbcc") @result{} +#f +@end lisp +@end deffn + +@subsubheading PEG Match Records +The @code{match-pattern} and @code{search-for-pattern} functions both return PEG +match records. Actual information can be extracted from these with the +following functions. + +@deffn {Scheme Procedure} peg:string match-record +Returns the original string that was parsed in the creation of +@code{match-record}. +@end deffn + +@deffn {Scheme Procedure} peg:start match-record +Returns the index of the first parsed character in the original string +(from @code{peg:string}). If this is the same as @code{peg:end}, +nothing was parsed. +@end deffn + +@deffn {Scheme Procedure} peg:end match-record +Returns one more than the index of the last parsed character in the +original string (from @code{peg:string}). If this is the same as +@code{peg:start}, nothing was parsed. +@end deffn + +@deffn {Scheme Procedure} peg:substring match-record +Returns the substring parsed by @code{match-record}. This is equivalent to +@code{(substring (peg:string match-record) (peg:start match-record) (peg:end +match-record))}. +@end deffn + +@deffn {Scheme Procedure} peg:tree match-record +Returns the tree parsed by @code{match-record}. +@end deffn + +@deffn {Scheme Procedure} peg-record? match-record +Returns true if @code{match-record} is a PEG match record, or false +otherwise. +@end deffn + +Example: +@lisp +(define-peg-pattern bs all (peg "'b'+")) + +(search-for-pattern bs "aabbcc") @result{} +#<peg start: 2 end: 4 string: aabbcc tree: (bs bb)> + +(let ((pm (search-for-pattern bs "aabbcc"))) + `((string ,(peg:string pm)) + (start ,(peg:start pm)) + (end ,(peg:end pm)) + (substring ,(peg:substring pm)) + (tree ,(peg:tree pm)) + (record? ,(peg-record? pm)))) @result{} +((string "aabbcc") + (start 2) + (end 4) + (substring "bb") + (tree (bs "bb")) + (record? #t)) +@end lisp + +@subsubheading Miscellaneous + +@deffn {Scheme Procedure} context-flatten tst lst +Takes a predicate @var{tst} and a list @var{lst}. Flattens @var{lst} +until all elements are either atoms or satisfy @var{tst}. If @var{lst} +itself satisfies @var{tst}, @code{(list lst)} is returned (this is a +flat list whose only element satisfies @var{tst}). + +@lisp +(context-flatten (lambda (x) (and (number? (car x)) (= (car x) 1))) '(2 2 (1 1 (2 2)) (2 2 (1 1)))) @result{} +(2 2 (1 1 (2 2)) 2 2 (1 1)) +(context-flatten (lambda (x) (and (number? (car x)) (= (car x) 1))) '(1 1 (1 1 (2 2)) (2 2 (1 1)))) @result{} +((1 1 (1 1 (2 2)) (2 2 (1 1)))) +@end lisp + +If you're wondering why this is here, take a look at the tutorial. +@end deffn + +@deffn {Scheme Procedure} keyword-flatten terms lst +A less general form of @code{context-flatten}. Takes a list of terminal +atoms @code{terms} and flattens @var{lst} until all elements are either +atoms, or lists which have an atom from @code{terms} as their first +element. +@lisp +(keyword-flatten '(a b) '(c a b (a c) (b c) (c (b a) (c a)))) @result{} +(c a b (a c) (b c) c (b a) c a) +@end lisp + +If you're wondering why this is here, take a look at the tutorial. +@end deffn + +@node PEG Tutorial +@subsection PEG Tutorial + +@subsubheading Parsing /etc/passwd +This example will show how to parse /etc/passwd using PEGs. + +First we define an example /etc/passwd file: + +@lisp +(define *etc-passwd* + "root:x:0:0:root:/root:/bin/bash +daemon:x:1:1:daemon:/usr/sbin:/bin/sh +bin:x:2:2:bin:/bin:/bin/sh +sys:x:3:3:sys:/dev:/bin/sh +nobody:x:65534:65534:nobody:/nonexistent:/bin/sh +messagebus:x:103:107::/var/run/dbus:/bin/false +") +@end lisp + +As a first pass at this, we might want to have all the entries in +/etc/passwd in a list. + +Doing this with string-based PEG syntax would look like this: +@lisp +(define-peg-string-patterns + "passwd <- entry* !. +entry <-- (! NL .)* NL* +NL < '\n'") +@end lisp + +A @code{passwd} file is 0 or more entries (@code{entry*}) until the end +of the file (@code{!.} (@code{.} is any character, so @code{!.} means +``not anything'')). We want to capture the data in the nonterminal +@code{passwd}, but not tag it with the name, so we use @code{<-}. + +An entry is a series of 0 or more characters that aren't newlines +(@code{(! NL .)*}) followed by 0 or more newlines (@code{NL*}). We want +to tag all the entries with @code{entry}, so we use @code{<--}. + +A newline is just a literal newline (@code{'\n'}). We don't want a +bunch of newlines cluttering up the output, so we use @code{<} to throw +away the captured data. + +Here is the same PEG defined using S-expressions: +@lisp +(define-peg-pattern passwd body (and (* entry) (not-followed-by peg-any))) +(define-peg-pattern entry all (and (* (and (not-followed-by NL) peg-any)) + (* NL))) +(define-peg-pattern NL none "\n") +@end lisp + +Obviously this is much more verbose. On the other hand, it's more +explicit, and thus easier to build automatically. However, there are +some tricks that make S-expressions easier to use in some cases. One is +the @code{ignore} keyword; the string syntax has no way to say ``throw +away this text'' except breaking it out into a separate nonterminal. +For instance, to throw away the newlines we had to define @code{NL}. In +the S-expression syntax, we could have simply written @code{(ignore +"\n")}. Also, for the cases where string syntax is really much cleaner, +the @code{peg} keyword can be used to embed string syntax in +S-expression syntax. For instance, we could have written: + +@lisp +(define-peg-pattern passwd body (peg "entry* !.")) +@end lisp + +However we define it, parsing @code{*etc-passwd*} with the @code{passwd} +nonterminal yields the same results: + +@lisp +(peg:tree (match-pattern passwd *etc-passwd*)) @result{} +((entry "root:x:0:0:root:/root:/bin/bash") + (entry "daemon:x:1:1:daemon:/usr/sbin:/bin/sh") + (entry "bin:x:2:2:bin:/bin:/bin/sh") + (entry "sys:x:3:3:sys:/dev:/bin/sh") + (entry "nobody:x:65534:65534:nobody:/nonexistent:/bin/sh") + (entry "messagebus:x:103:107::/var/run/dbus:/bin/false")) +@end lisp + +However, here is something to be wary of: + +@lisp +(peg:tree (match-pattern passwd "one entry")) @result{} +(entry "one entry") +@end lisp + +By default, the parse trees generated by PEGs are compressed as much as +possible without losing information. It may not look like this is what +you want at first, but uncompressed parse trees are an enormous headache +(there's no easy way to predict how deep particular lists will nest, +there are empty lists littered everywhere, etc. etc.). One side-effect +of this, however, is that sometimes the compressor is too aggressive. +No information is discarded when @code{((entry "one entry"))} is +compressed to @code{(entry "one entry")}, but in this particular case it +probably isn't what we want. + +There are two functions for easily dealing with this: +@code{keyword-flatten} and @code{context-flatten}. The +@code{keyword-flatten} function takes a list of keywords and a list to +flatten, then tries to coerce the list such that the first element of +all sublists is one of the keywords. The @code{context-flatten} +function is similar, but instead of a list of keywords it takes a +predicate that should indicate whether a given sublist is good enough +(refer to the API reference for more details). + +What we want here is @code{keyword-flatten}. +@lisp +(keyword-flatten '(entry) (peg:tree (match-pattern passwd *etc-passwd*))) @result{} +((entry "root:x:0:0:root:/root:/bin/bash") + (entry "daemon:x:1:1:daemon:/usr/sbin:/bin/sh") + (entry "bin:x:2:2:bin:/bin:/bin/sh") + (entry "sys:x:3:3:sys:/dev:/bin/sh") + (entry "nobody:x:65534:65534:nobody:/nonexistent:/bin/sh") + (entry "messagebus:x:103:107::/var/run/dbus:/bin/false")) +(keyword-flatten '(entry) (peg:tree (match-pattern passwd "one entry"))) @result{} +((entry "one entry")) +@end lisp + +Of course, this is a somewhat contrived example. In practice we would +probably just tag the @code{passwd} nonterminal to remove the ambiguity +(using either the @code{all} keyword for S-expressions or the @code{<--} +symbol for strings).. + +@lisp +(define-peg-pattern tag-passwd all (peg "entry* !.")) +(peg:tree (match-pattern tag-passwd *etc-passwd*)) @result{} +(tag-passwd + (entry "root:x:0:0:root:/root:/bin/bash") + (entry "daemon:x:1:1:daemon:/usr/sbin:/bin/sh") + (entry "bin:x:2:2:bin:/bin:/bin/sh") + (entry "sys:x:3:3:sys:/dev:/bin/sh") + (entry "nobody:x:65534:65534:nobody:/nonexistent:/bin/sh") + (entry "messagebus:x:103:107::/var/run/dbus:/bin/false")) +(peg:tree (match-pattern tag-passwd "one entry")) +(tag-passwd + (entry "one entry")) +@end lisp + +If you're ever uncertain about the potential results of parsing +something, remember the two absolute rules: +@enumerate +@item +No parsing information will ever be discarded. +@item +There will never be any lists with fewer than 2 elements. +@end enumerate + +For the purposes of (1), "parsing information" means things tagged with +the @code{any} keyword or the @code{<--} symbol. Plain strings will be +concatenated. + +Let's extend this example a bit more and actually pull some useful +information out of the passwd file: + +@lisp +(define-peg-string-patterns + "passwd <-- entry* !. +entry <-- login C pass C uid C gid C nameORcomment C homedir C shell NL* +login <-- text +pass <-- text +uid <-- [0-9]* +gid <-- [0-9]* +nameORcomment <-- text +homedir <-- path +shell <-- path +path <-- (SLASH pathELEMENT)* +pathELEMENT <-- (!NL !C !'/' .)* +text <- (!NL !C .)* +C < ':' +NL < '\n' +SLASH < '/'") +@end lisp + +This produces rather pretty parse trees: +@lisp +(passwd + (entry (login "root") + (pass "x") + (uid "0") + (gid "0") + (nameORcomment "root") + (homedir (path (pathELEMENT "root"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "bash")))) + (entry (login "daemon") + (pass "x") + (uid "1") + (gid "1") + (nameORcomment "daemon") + (homedir + (path (pathELEMENT "usr") (pathELEMENT "sbin"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "sh")))) + (entry (login "bin") + (pass "x") + (uid "2") + (gid "2") + (nameORcomment "bin") + (homedir (path (pathELEMENT "bin"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "sh")))) + (entry (login "sys") + (pass "x") + (uid "3") + (gid "3") + (nameORcomment "sys") + (homedir (path (pathELEMENT "dev"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "sh")))) + (entry (login "nobody") + (pass "x") + (uid "65534") + (gid "65534") + (nameORcomment "nobody") + (homedir (path (pathELEMENT "nonexistent"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "sh")))) + (entry (login "messagebus") + (pass "x") + (uid "103") + (gid "107") + nameORcomment + (homedir + (path (pathELEMENT "var") + (pathELEMENT "run") + (pathELEMENT "dbus"))) + (shell (path (pathELEMENT "bin") (pathELEMENT "false"))))) +@end lisp + +Notice that when there's no entry in a field (e.g. @code{nameORcomment} +for messagebus) the symbol is inserted. This is the ``don't throw away +any information'' rule---we succesfully matched a @code{nameORcomment} +of 0 characters (since we used @code{*} when defining it). This is +usually what you want, because it allows you to e.g. use @code{list-ref} +to pull out elements (since they all have known offsets). + +If you'd prefer not to have symbols for empty matches, you can replace +the @code{*} with a @code{+} and add a @code{?} after the +@code{nameORcomment} in @code{entry}. Then it will try to parse 1 or +more characters, fail (inserting nothing into the parse tree), but +continue because it didn't have to match the nameORcomment to continue. + + +@subsubheading Embedding Arithmetic Expressions + +We can parse simple mathematical expressions with the following PEG: + +@lisp +(define-peg-string-patterns + "expr <- sum +sum <-- (product ('+' / '-') sum) / product +product <-- (value ('*' / '/') product) / value +value <-- number / '(' expr ')' +number <-- [0-9]+") +@end lisp + +Then: +@lisp +(peg:tree (match-pattern expr "1+1/2*3+(1+1)/2")) @result{} +(sum (product (value (number "1"))) + "+" + (sum (product + (value (number "1")) + "/" + (product + (value (number "2")) + "*" + (product (value (number "3"))))) + "+" + (sum (product + (value "(" + (sum (product (value (number "1"))) + "+" + (sum (product (value (number "1"))))) + ")") + "/" + (product (value (number "2"))))))) +@end lisp + +There is very little wasted effort in this PEG. The @code{number} +nonterminal has to be tagged because otherwise the numbers might run +together with the arithmetic expressions during the string concatenation +stage of parse-tree compression (the parser will see ``1'' followed by +``/'' and decide to call it ``1/''). When in doubt, tag. + +It is very easy to turn these parse trees into lisp expressions: + +@lisp +(define (parse-sum sum left . rest) + (if (null? rest) + (apply parse-product left) + (list (string->symbol (car rest)) + (apply parse-product left) + (apply parse-sum (cadr rest))))) + +(define (parse-product product left . rest) + (if (null? rest) + (apply parse-value left) + (list (string->symbol (car rest)) + (apply parse-value left) + (apply parse-product (cadr rest))))) + +(define (parse-value value first . rest) + (if (null? rest) + (string->number (cadr first)) + (apply parse-sum (car rest)))) + +(define parse-expr parse-sum) +@end lisp + +(Notice all these functions look very similar; for a more complicated +PEG, it would be worth abstracting.) + +Then: +@lisp +(apply parse-expr (peg:tree (match-pattern expr "1+1/2*3+(1+1)/2"))) @result{} +(+ 1 (+ (/ 1 (* 2 3)) (/ (+ 1 1) 2))) +@end lisp + +But wait! The associativity is wrong! Where it says @code{(/ 1 (* 2 +3))}, it should say @code{(* (/ 1 2) 3)}. + +It's tempting to try replacing e.g. @code{"sum <-- (product ('+' / '-') +sum) / product"} with @code{"sum <-- (sum ('+' / '-') product) / +product"}, but this is a Bad Idea. PEGs don't support left recursion. +To see why, imagine what the parser will do here. When it tries to +parse @code{sum}, it first has to try and parse @code{sum}. But to do +that, it first has to try and parse @code{sum}. This will continue +until the stack gets blown off. + +So how does one parse left-associative binary operators with PEGs? +Honestly, this is one of their major shortcomings. There's no +general-purpose way of doing this, but here the repetition operators are +a good choice: + +@lisp +(use-modules (srfi srfi-1)) + +(define-peg-string-patterns + "expr <- sum +sum <-- (product ('+' / '-'))* product +product <-- (value ('*' / '/'))* value +value <-- number / '(' expr ')' +number <-- [0-9]+") + +;; take a deep breath... +(define (make-left-parser next-func) + (lambda (sum first . rest) ;; general form, comments below assume + ;; that we're dealing with a sum expression + (if (null? rest) ;; form (sum (product ...)) + (apply next-func first) + (if (string? (cadr first));; form (sum ((product ...) "+") (product ...)) + (list (string->symbol (cadr first)) + (apply next-func (car first)) + (apply next-func (car rest))) + ;; form (sum (((product ...) "+") ((product ...) "+")) (product ...)) + (car + (reduce ;; walk through the list and build a left-associative tree + (lambda (l r) + (list (list (cadr r) (car r) (apply next-func (car l))) + (string->symbol (cadr l)))) + 'ignore + (append ;; make a list of all the products + ;; the first one should be pre-parsed + (list (list (apply next-func (caar first)) + (string->symbol (cadar first)))) + (cdr first) + ;; the last one has to be added in + (list (append rest '("done")))))))))) + +(define (parse-value value first . rest) + (if (null? rest) + (string->number (cadr first)) + (apply parse-sum (car rest)))) +(define parse-product (make-left-parser parse-value)) +(define parse-sum (make-left-parser parse-product)) +(define parse-expr parse-sum) +@end lisp + +Then: +@lisp +(apply parse-expr (peg:tree (match-pattern expr "1+1/2*3+(1+1)/2"))) @result{} +(+ (+ 1 (* (/ 1 2) 3)) (/ (+ 1 1) 2)) +@end lisp + +As you can see, this is much uglier (it could be made prettier by using +@code{context-flatten}, but the way it's written above makes it clear +how we deal with the three ways the zero-or-more @code{*} expression can +parse). Fortunately, most of the time we can get away with only using +right-associativity. + +@subsubheading Simplified Functions + +For a more tantalizing example, consider the following grammar that +parses (highly) simplified C functions: + +@lisp +(define-peg-string-patterns + "cfunc <-- cSP ctype cSP cname cSP cargs cLB cSP cbody cRB +ctype <-- cidentifier +cname <-- cidentifier +cargs <-- cLP (! (cSP cRP) carg cSP (cCOMMA / cRP) cSP)* cSP +carg <-- cSP ctype cSP cname +cbody <-- cstatement * +cidentifier <- [a-zA-z][a-zA-Z0-9_]* +cstatement <-- (!';'.)*cSC cSP +cSC < ';' +cCOMMA < ',' +cLP < '(' +cRP < ')' +cLB < '@{' +cRB < '@}' +cSP < [ \t\n]*") +@end lisp + +Then: +@lisp +(match-pattern cfunc "int square(int a) @{ return a*a;@}") @result{} +(32 + (cfunc (ctype "int") + (cname "square") + (cargs (carg (ctype "int") (cname "a"))) + (cbody (cstatement "return a*a")))) +@end lisp + +And: +@lisp +(match-pattern cfunc "int mod(int a, int b) @{ int c = a/b;return a-b*c; @}") @result{} +(52 + (cfunc (ctype "int") + (cname "mod") + (cargs (carg (ctype "int") (cname "a")) + (carg (ctype "int") (cname "b"))) + (cbody (cstatement "int c = a/b") + (cstatement "return a- b*c")))) +@end lisp + +By wrapping all the @code{carg} nonterminals in a @code{cargs} +nonterminal, we were able to remove any ambiguity in the parsing +structure and avoid having to call @code{context-flatten} on the output +of @code{match-pattern}. We used the same trick with the @code{cstatement} +nonterminals, wrapping them in a @code{cbody} nonterminal. + +The whitespace nonterminal @code{cSP} used here is a (very) useful +instantiation of a common pattern for matching syntactically irrelevant +information. Since it's tagged with @code{<} and ends with @code{*} it +won't clutter up the parse trees (all the empty lists will be discarded +during the compression step) and it will never cause parsing to fail. + +@node PEG Internals +@subsection PEG Internals + +A PEG parser takes a string as input and attempts to parse it as a given +nonterminal. The key idea of the PEG implementation is that every +nonterminal is just a function that takes a string as an argument and +attempts to parse that string as its nonterminal. The functions always +start from the beginning, but a parse is considered successful if there +is material left over at the end. + +This makes it easy to model different PEG parsing operations. For +instance, consider the PEG grammar @code{"ab"}, which could also be +written @code{(and "a" "b")}. It matches the string ``ab''. Here's how +that might be implemented in the PEG style: + +@lisp +(define (match-and-a-b str) + (match-a str) + (match-b str)) +@end lisp + +As you can see, the use of functions provides an easy way to model +sequencing. In a similar way, one could model @code{(or a b)} with +something like the following: + +@lisp +(define (match-or-a-b str) + (or (match-a str) (match-b str))) +@end lisp + +Here the semantics of a PEG @code{or} expression map naturally onto +Scheme's @code{or} operator. This function will attempt to run +@code{(match-a str)}, and return its result if it succeeds. Otherwise it +will run @code{(match-b str)}. + +Of course, the code above wouldn't quite work. We need some way for the +parsing functions to communicate. The actual interface used is below. + +@subsubheading Parsing Function Interface + +A parsing function takes three arguments - a string, the length of that +string, and the position in that string it should start parsing at. In +effect, the parsing functions pass around substrings in pieces - the +first argument is a buffer of characters, and the second two give a +range within that buffer that the parsing function should look at. + +Parsing functions return either #f, if they failed to match their +nonterminal, or a list whose first element must be an integer +representing the final position in the string they matched and whose cdr +can be any other data the function wishes to return, or '() if it +doesn't have any more data. + +The one caveat is that if the extra data it returns is a list, any +adjacent strings in that list will be appended by @code{match-pattern}. For +instance, if a parsing function returns @code{(13 ("a" "b" "c"))}, +@code{match-pattern} will take @code{(13 ("abc"))} as its value. + +For example, here is a function to match ``ab'' using the actual +interface. + +@lisp +(define (match-a-b str len pos) + (and (<= (+ pos 2) len) + (string= str "ab" pos (+ pos 2)) + (list (+ pos 2) '()))) ; we return no extra information +@end lisp + +The above function can be used to match a string by running +@code{(match-pattern match-a-b "ab")}. + +@subsubheading Code Generators and Extensible Syntax + +PEG expressions, such as those in a @code{define-peg-pattern} form, are +interpreted internally in two steps. + +First, any string PEG is expanded into an s-expression PEG by the code +in the @code{(ice-9 peg string-peg)} module. + +Then, the s-expression PEG that results is compiled into a parsing +function by the @code{(ice-9 peg codegen)} module. In particular, the +function @code{compile-peg-pattern} is called on the s-expression. It then +decides what to do based on the form it is passed. + +The PEG syntax can be expanded by providing @code{compile-peg-pattern} more +options for what to do with its forms. The extended syntax will be +associated with a symbol, for instance @code{my-parsing-form}, and will +be called on all PEG expressions of the form +@lisp +(my-parsing-form ...) +@end lisp + +The parsing function should take two arguments. The first will be a +syntax object containing a list with all of the arguments to the form +(but not the form's name), and the second will be the +@code{capture-type} argument that is passed to @code{define-peg-pattern}. + +New functions can be registered by calling @code{(add-peg-compiler! +symbol function)}, where @code{symbol} is the symbol that will indicate +a form of this type and @code{function} is the code generating function +described above. The function @code{add-peg-compiler!} is exported from +the @code{(ice-9 peg codegen)} module. diff --git a/doc/ref/api-procedures.texi b/doc/ref/api-procedures.texi new file mode 100644 index 000000000..df24178f9 --- /dev/null +++ b/doc/ref/api-procedures.texi @@ -0,0 +1,919 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, +@c 2011, 2012, 2013 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Procedures +@section Procedures + +@menu +* Lambda:: Basic procedure creation using lambda. +* Primitive Procedures:: Procedures defined in C. +* Compiled Procedures:: Scheme procedures can be compiled. +* Optional Arguments:: Handling keyword, optional and rest arguments. +* Case-lambda:: One function, multiple arities. +* Higher-Order Functions:: Function that take or return functions. +* Procedure Properties:: Procedure properties and meta-information. +* Procedures with Setters:: Procedures with setters. +* Inlinable Procedures:: Procedures that can be inlined. +@end menu + + +@node Lambda +@subsection Lambda: Basic Procedure Creation +@cindex lambda + +A @code{lambda} expression evaluates to a procedure. The environment +which is in effect when a @code{lambda} expression is evaluated is +enclosed in the newly created procedure, this is referred to as a +@dfn{closure} (@pxref{About Closure}). + +When a procedure created by @code{lambda} is called with some actual +arguments, the environment enclosed in the procedure is extended by +binding the variables named in the formal argument list to new locations +and storing the actual arguments into these locations. Then the body of +the @code{lambda} expression is evaluated sequentially. The result of +the last expression in the procedure body is then the result of the +procedure invocation. + +The following examples will show how procedures can be created using +@code{lambda}, and what you can do with these procedures. + +@lisp +(lambda (x) (+ x x)) @result{} @r{a procedure} +((lambda (x) (+ x x)) 4) @result{} 8 +@end lisp + +The fact that the environment in effect when creating a procedure is +enclosed in the procedure is shown with this example: + +@lisp +(define add4 + (let ((x 4)) + (lambda (y) (+ x y)))) +(add4 6) @result{} 10 +@end lisp + + +@deffn syntax lambda formals body +@var{formals} should be a formal argument list as described in the +following table. + +@table @code +@item (@var{variable1} @dots{}) +The procedure takes a fixed number of arguments; when the procedure is +called, the arguments will be stored into the newly created location for +the formal variables. +@item @var{variable} +The procedure takes any number of arguments; when the procedure is +called, the sequence of actual arguments will converted into a list and +stored into the newly created location for the formal variable. +@item (@var{variable1} @dots{} @var{variablen} . @var{variablen+1}) +If a space-delimited period precedes the last variable, then the +procedure takes @var{n} or more variables where @var{n} is the number +of formal arguments before the period. There must be at least one +argument before the period. The first @var{n} actual arguments will be +stored into the newly allocated locations for the first @var{n} formal +arguments and the sequence of the remaining actual arguments is +converted into a list and the stored into the location for the last +formal argument. If there are exactly @var{n} actual arguments, the +empty list is stored into the location of the last formal argument. +@end table + +The list in @var{variable} or @var{variablen+1} is always newly +created and the procedure can modify it if desired. This is the case +even when the procedure is invoked via @code{apply}, the required part +of the list argument there will be copied (@pxref{Fly Evaluation,, +Procedures for On the Fly Evaluation}). + +@var{body} is a sequence of Scheme expressions which are evaluated in +order when the procedure is invoked. +@end deffn + +@node Primitive Procedures +@subsection Primitive Procedures +@cindex primitives +@cindex primitive procedures + +Procedures written in C can be registered for use from Scheme, +provided they take only arguments of type @code{SCM} and return +@code{SCM} values. @code{scm_c_define_gsubr} is likely to be the most +useful mechanism, combining the process of registration +(@code{scm_c_make_gsubr}) and definition (@code{scm_define}). + +@deftypefun SCM scm_c_make_gsubr (const char *name, int req, int opt, int rst, fcn) +Register a C procedure @var{fcn} as a ``subr'' --- a primitive +subroutine that can be called from Scheme. It will be associated with +the given @var{name} but no environment binding will be created. The +arguments @var{req}, @var{opt} and @var{rst} specify the number of +required, optional and ``rest'' arguments respectively. The total +number of these arguments should match the actual number of arguments +to @var{fcn}, but may not exceed 10. The number of rest arguments should be 0 or 1. +@code{scm_c_make_gsubr} returns a value of type @code{SCM} which is a +``handle'' for the procedure. +@end deftypefun + +@deftypefun SCM scm_c_define_gsubr (const char *name, int req, int opt, int rst, fcn) +Register a C procedure @var{fcn}, as for @code{scm_c_make_gsubr} +above, and additionally create a top-level Scheme binding for the +procedure in the ``current environment'' using @code{scm_define}. +@code{scm_c_define_gsubr} returns a handle for the procedure in the +same way as @code{scm_c_make_gsubr}, which is usually not further +required. +@end deftypefun + +@node Compiled Procedures +@subsection Compiled Procedures + +The evaluation strategy given in @ref{Lambda} describes how procedures +are @dfn{interpreted}. Interpretation operates directly on expanded +Scheme source code, recursively calling the evaluator to obtain the +value of nested expressions. + +Most procedures are compiled, however. This means that Guile has done +some pre-computation on the procedure, to determine what it will need to +do each time the procedure runs. Compiled procedures run faster than +interpreted procedures. + +Loading files is the normal way that compiled procedures come to +being. If Guile sees that a file is uncompiled, or that its compiled +file is out of date, it will attempt to compile the file when it is +loaded, and save the result to disk. Procedures can be compiled at +runtime as well. @xref{Read/Load/Eval/Compile}, for more information +on runtime compilation. + +Compiled procedures, also known as @dfn{programs}, respond all +procedures that operate on procedures. In addition, there are a few +more accessors for low-level details on programs. + +Most people won't need to use the routines described in this section, +but it's good to have them documented. You'll have to include the +appropriate module first, though: + +@example +(use-modules (system vm program)) +@end example + +@deffn {Scheme Procedure} program? obj +@deffnx {C Function} scm_program_p (obj) +Returns @code{#t} if @var{obj} is a compiled procedure, or @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} program-code program +@deffnx {C Function} scm_program_code (program) +Returns the address of the program's entry, as an integer. This address +is mostly useful to procedures in @code{(system vm debug)}. +@end deffn + +@deffn {Scheme Procedure} program-num-free-variable program +@deffnx {C Function} scm_program_num_free_variables (program) +Return the number of free variables captured by this program. +@end deffn + +@deffn {Scheme Procedure} program-free-variable-ref program n +@deffnx {C Function} scm_program_free_variable-ref (program, n) +@deffnx {Scheme Procedure} program-free-variable-set! program n val +@deffnx {C Function} scm_program_free_variable_set_x (program, n, val) +Accessors for a program's free variables. Some of the values captured +are actually in variable ``boxes''. @xref{Variables and the VM}, for +more information. + +Users must not modify the returned value unless they think they're +really clever. +@end deffn + +@c FIXME + +@deffn {Scheme Procedure} program-bindings program +@deffnx {Scheme Procedure} make-binding name boxed? index start end +@deffnx {Scheme Procedure} binding:name binding +@deffnx {Scheme Procedure} binding:boxed? binding +@deffnx {Scheme Procedure} binding:index binding +@deffnx {Scheme Procedure} binding:start binding +@deffnx {Scheme Procedure} binding:end binding +Bindings annotations for programs, along with their accessors. + +Bindings declare names and liveness extents for block-local variables. +The best way to see what these are is to play around with them at a +REPL. @xref{VM Concepts}, for more information. + +Note that bindings information is stored in a program as part of its +metadata thunk, so including it in the generated object code does not +impose a runtime performance penalty. +@end deffn + +@deffn {Scheme Procedure} program-sources program +@deffnx {Scheme Procedure} source:addr source +@deffnx {Scheme Procedure} source:line source +@deffnx {Scheme Procedure} source:column source +@deffnx {Scheme Procedure} source:file source +Source location annotations for programs, along with their accessors. + +Source location information propagates through the compiler and ends +up being serialized to the program's metadata. This information is +keyed by the offset of the instruction pointer within the object code +of the program. Specifically, it is keyed on the @code{ip} @emph{just +following} an instruction, so that backtraces can find the source +location of a call that is in progress. +@end deffn + +@deffn {Scheme Procedure} program-arities program +@deffnx {C Function} scm_program_arities (program) +@deffnx {Scheme Procedure} program-arity program ip +@deffnx {Scheme Procedure} arity:start arity +@deffnx {Scheme Procedure} arity:end arity +@deffnx {Scheme Procedure} arity:nreq arity +@deffnx {Scheme Procedure} arity:nopt arity +@deffnx {Scheme Procedure} arity:rest? arity +@deffnx {Scheme Procedure} arity:kw arity +@deffnx {Scheme Procedure} arity:allow-other-keys? arity +Accessors for a representation of the ``arity'' of a program. + +The normal case is that a procedure has one arity. For example, +@code{(lambda (x) x)}, takes one required argument, and that's it. One +could access that number of required arguments via @code{(arity:nreq +(program-arities (lambda (x) x)))}. Similarly, @code{arity:nopt} gets +the number of optional arguments, and @code{arity:rest?} returns a true +value if the procedure has a rest arg. + +@code{arity:kw} returns a list of @code{(@var{kw} . @var{idx})} pairs, +if the procedure has keyword arguments. The @var{idx} refers to the +@var{idx}th local variable; @xref{Variables and the VM}, for more +information. Finally @code{arity:allow-other-keys?} returns a true +value if other keys are allowed. @xref{Optional Arguments}, for more +information. + +So what about @code{arity:start} and @code{arity:end}, then? They +return the range of bytes in the program's bytecode for which a given +arity is valid. You see, a procedure can actually have more than one +arity. The question, ``what is a procedure's arity'' only really makes +sense at certain points in the program, delimited by these +@code{arity:start} and @code{arity:end} values. +@end deffn + +@deffn {Scheme Procedure} program-arguments-alist program [ip] +Return an association list describing the arguments that @var{program} accepts, or +@code{#f} if the information cannot be obtained. + +The alist keys that are currently defined are `required', `optional', +`keyword', `allow-other-keys?', and `rest'. For example: + +@example +(program-arguments-alist + (lambda* (a b #:optional c #:key (d 1) #:rest e) + #t)) @result{} +((required . (a b)) + (optional . (c)) + (keyword . ((#:d . 4))) + (allow-other-keys? . #f) + (rest . d)) +@end example +@end deffn + +@deffn {Scheme Procedure} program-lambda-list program [ip] +Return a representation of the arguments of @var{program} as a lambda +list, or @code{#f} if this information is not available. + +For example: + +@example +(program-lambda-list + (lambda* (a b #:optional c #:key (d 1) #:rest e) + #t)) @result{} +@end example +@end deffn + +@node Optional Arguments +@subsection Optional Arguments + +Scheme procedures, as defined in R5RS, can either handle a fixed number +of actual arguments, or a fixed number of actual arguments followed by +arbitrarily many additional arguments. Writing procedures of variable +arity can be useful, but unfortunately, the syntactic means for handling +argument lists of varying length is a bit inconvenient. It is possible +to give names to the fixed number of arguments, but the remaining +(optional) arguments can be only referenced as a list of values +(@pxref{Lambda}). + +For this reason, Guile provides an extension to @code{lambda}, +@code{lambda*}, which allows the user to define procedures with +optional and keyword arguments. In addition, Guile's virtual machine +has low-level support for optional and keyword argument dispatch. +Calls to procedures with optional and keyword arguments can be made +cheaply, without allocating a rest list. + +@menu +* lambda* and define*:: Creating advanced argument handling procedures. +* ice-9 optargs:: (ice-9 optargs) provides some utilities. +@end menu + + +@node lambda* and define* +@subsubsection lambda* and define*. + +@code{lambda*} is like @code{lambda}, except with some extensions to +allow optional and keyword arguments. + +@deffn {library syntax} lambda* ([var@dots{}] @* @ + [#:optional vardef@dots{}] @* @ + [#:key vardef@dots{} [#:allow-other-keys]] @* @ + [#:rest var | . var]) @* @ + body1 body2 @dots{} +@sp 1 +Create a procedure which takes optional and/or keyword arguments +specified with @code{#:optional} and @code{#:key}. For example, + +@lisp +(lambda* (a b #:optional c d . e) '()) +@end lisp + +is a procedure with fixed arguments @var{a} and @var{b}, optional +arguments @var{c} and @var{d}, and rest argument @var{e}. If the +optional arguments are omitted in a call, the variables for them are +bound to @code{#f}. + +@fnindex define* +Likewise, @code{define*} is syntactic sugar for defining procedures +using @code{lambda*}. + +@code{lambda*} can also make procedures with keyword arguments. For +example, a procedure defined like this: + +@lisp +(define* (sir-yes-sir #:key action how-high) + (list action how-high)) +@end lisp + +can be called as @code{(sir-yes-sir #:action 'jump)}, +@code{(sir-yes-sir #:how-high 13)}, @code{(sir-yes-sir #:action +'lay-down #:how-high 0)}, or just @code{(sir-yes-sir)}. Whichever +arguments are given as keywords are bound to values (and those not +given are @code{#f}). + +Optional and keyword arguments can also have default values to take +when not present in a call, by giving a two-element list of variable +name and expression. For example in + +@lisp +(define* (frob foo #:optional (bar 42) #:key (baz 73)) + (list foo bar baz)) +@end lisp + +@var{foo} is a fixed argument, @var{bar} is an optional argument with +default value 42, and baz is a keyword argument with default value 73. +Default value expressions are not evaluated unless they are needed, +and until the procedure is called. + +Normally it's an error if a call has keywords other than those +specified by @code{#:key}, but adding @code{#:allow-other-keys} to the +definition (after the keyword argument declarations) will ignore +unknown keywords. + +If a call has a keyword given twice, the last value is used. For +example, + +@lisp +(define* (flips #:key (heads 0) (tails 0)) + (display (list heads tails))) + +(flips #:heads 37 #:tails 42 #:heads 99) +@print{} (99 42) +@end lisp + +@code{#:rest} is a synonym for the dotted syntax rest argument. The +argument lists @code{(a . b)} and @code{(a #:rest b)} are equivalent +in all respects. This is provided for more similarity to DSSSL, +MIT-Scheme and Kawa among others, as well as for refugees from other +Lisp dialects. + +When @code{#:key} is used together with a rest argument, the keyword +parameters in a call all remain in the rest list. This is the same as +Common Lisp. For example, + +@lisp +((lambda* (#:key (x 0) #:allow-other-keys #:rest r) + (display r)) + #:x 123 #:y 456) +@print{} (#:x 123 #:y 456) +@end lisp + +@code{#:optional} and @code{#:key} establish their bindings +successively, from left to right. This means default expressions can +refer back to prior parameters, for example + +@lisp +(lambda* (start #:optional (end (+ 10 start))) + (do ((i start (1+ i))) + ((> i end)) + (display i))) +@end lisp + +The exception to this left-to-right scoping rule is the rest argument. +If there is a rest argument, it is bound after the optional arguments, +but before the keyword arguments. +@end deffn + + +@node ice-9 optargs +@subsubsection (ice-9 optargs) + +Before Guile 2.0, @code{lambda*} and @code{define*} were implemented +using macros that processed rest list arguments. This was not optimal, +as calling procedures with optional arguments had to allocate rest +lists at every procedure invocation. Guile 2.0 improved this +situation by bringing optional and keyword arguments into Guile's +core. + +However there are occasions in which you have a list and want to parse +it for optional or keyword arguments. Guile's @code{(ice-9 optargs)} +provides some macros to help with that task. + +The syntax @code{let-optional} and @code{let-optional*} are for +destructuring rest argument lists and giving names to the various list +elements. @code{let-optional} binds all variables simultaneously, while +@code{let-optional*} binds them sequentially, consistent with @code{let} +and @code{let*} (@pxref{Local Bindings}). + +@deffn {library syntax} let-optional rest-arg (binding @dots{}) body1 body2 @dots{} +@deffnx {library syntax} let-optional* rest-arg (binding @dots{}) body1 body2 @dots{} +These two macros give you an optional argument interface that is very +@dfn{Schemey} and introduces no fancy syntax. They are compatible with +the scsh macros of the same name, but are slightly extended. Each of +@var{binding} may be of one of the forms @var{var} or @code{(@var{var} +@var{default-value})}. @var{rest-arg} should be the rest-argument of the +procedures these are used from. The items in @var{rest-arg} are +sequentially bound to the variable names are given. When @var{rest-arg} +runs out, the remaining vars are bound either to the default values or +@code{#f} if no default value was specified. @var{rest-arg} remains +bound to whatever may have been left of @var{rest-arg}. + +After binding the variables, the expressions @var{body1} @var{body2} @dots{} +are evaluated in order. +@end deffn + +Similarly, @code{let-keywords} and @code{let-keywords*} extract values +from keyword style argument lists, binding local variables to those +values or to defaults. + +@deffn {library syntax} let-keywords args allow-other-keys? (binding @dots{}) body1 body2 @dots{} +@deffnx {library syntax} let-keywords* args allow-other-keys? (binding @dots{}) body1 body2 @dots{} +@var{args} is evaluated and should give a list of the form +@code{(#:keyword1 value1 #:keyword2 value2 @dots{})}. The +@var{binding}s are variables and default expressions, with the variables +to be set (by name) from the keyword values. The @var{body1} +@var{body2} @dots{} forms are then evaluated and the last is the +result. An example will make the syntax clearest, + +@example +(define args '(#:xyzzy "hello" #:foo "world")) + +(let-keywords args #t + ((foo "default for foo") + (bar (string-append "default" "for" "bar"))) + (display foo) + (display ", ") + (display bar)) +@print{} world, defaultforbar +@end example + +The binding for @code{foo} comes from the @code{#:foo} keyword in +@code{args}. But the binding for @code{bar} is the default in the +@code{let-keywords}, since there's no @code{#:bar} in the args. + +@var{allow-other-keys?} is evaluated and controls whether unknown +keywords are allowed in the @var{args} list. When true other keys are +ignored (such as @code{#:xyzzy} in the example), when @code{#f} an +error is thrown for anything unknown. +@end deffn + +@code{(ice-9 optargs)} also provides some more @code{define*} sugar, +which is not so useful with modern Guile coding, but still supported: +@code{define*-public} is the @code{lambda*} version of +@code{define-public}; @code{defmacro*} and @code{defmacro*-public} +exist for defining macros with the improved argument list handling +possibilities. The @code{-public} versions not only define the +procedures/macros, but also export them from the current module. + +@deffn {library syntax} define*-public formals body1 body2 @dots{} +Like a mix of @code{define*} and @code{define-public}. +@end deffn + +@deffn {library syntax} defmacro* name formals body1 body2 @dots{} +@deffnx {library syntax} defmacro*-public name formals body1 body2 @dots{} +These are just like @code{defmacro} and @code{defmacro-public} except that they +take @code{lambda*}-style extended parameter lists, where @code{#:optional}, +@code{#:key}, @code{#:allow-other-keys} and @code{#:rest} are allowed with the usual +semantics. Here is an example of a macro with an optional argument: + +@lisp +(defmacro* transmogrify (a #:optional b) + (a 1)) +@end lisp +@end deffn + +@node Case-lambda +@subsection Case-lambda +@cindex SRFI-16 +@cindex variable arity +@cindex arity, variable + +R5RS's rest arguments are indeed useful and very general, but they +often aren't the most appropriate or efficient means to get the job +done. For example, @code{lambda*} is a much better solution to the +optional argument problem than @code{lambda} with rest arguments. + +@fnindex case-lambda +Likewise, @code{case-lambda} works well for when you want one +procedure to do double duty (or triple, or ...), without the penalty +of consing a rest list. + +For example: + +@lisp +(define (make-accum n) + (case-lambda + (() n) + ((m) (set! n (+ n m)) n))) + +(define a (make-accum 20)) +(a) @result{} 20 +(a 10) @result{} 30 +(a) @result{} 30 +@end lisp + +The value returned by a @code{case-lambda} form is a procedure which +matches the number of actual arguments against the formals in the +various clauses, in order. The first matching clause is selected, the +corresponding values from the actual parameter list are bound to the +variable names in the clauses and the body of the clause is evaluated. +If no clause matches, an error is signalled. + +The syntax of the @code{case-lambda} form is defined in the following +EBNF grammar. @dfn{Formals} means a formal argument list just like +with @code{lambda} (@pxref{Lambda}). + +@example +@group +<case-lambda> + --> (case-lambda <case-lambda-clause>*) + --> (case-lambda <docstring> <case-lambda-clause>*) +<case-lambda-clause> + --> (<formals> <definition-or-command>*) +<formals> + --> (<identifier>*) + | (<identifier>* . <identifier>) + | <identifier> +@end group +@end example + +Rest lists can be useful with @code{case-lambda}: + +@lisp +(define plus + (case-lambda + "Return the sum of all arguments." + (() 0) + ((a) a) + ((a b) (+ a b)) + ((a b . rest) (apply plus (+ a b) rest)))) +(plus 1 2 3) @result{} 6 +@end lisp + +@fnindex case-lambda* +Also, for completeness. Guile defines @code{case-lambda*} as well, +which is like @code{case-lambda}, except with @code{lambda*} clauses. +A @code{case-lambda*} clause matches if the arguments fill the +required arguments, but are not too many for the optional and/or rest +arguments. + +Keyword arguments are possible with @code{case-lambda*} as well, but +they do not contribute to the ``matching'' behavior, and their +interactions with required, optional, and rest arguments can be +surprising. + +For the purposes of @code{case-lambda*} (and of @code{case-lambda}, as a +special case), a clause @dfn{matches} if it has enough required +arguments, and not too many positional arguments. The required +arguments are any arguments before the @code{#:optional}, @code{#:key}, +and @code{#:rest} arguments. @dfn{Positional} arguments are the +required arguments, together with the optional arguments. + +In the absence of @code{#:key} or @code{#:rest} arguments, it's easy to +see how there could be too many positional arguments: you pass 5 +arguments to a function that only takes 4 arguments, including optional +arguments. If there is a @code{#:rest} argument, there can never be too +many positional arguments: any application with enough required +arguments for a clause will match that clause, even if there are also +@code{#:key} arguments. + +Otherwise, for applications to a clause with @code{#:key} arguments (and +without a @code{#:rest} argument), a clause will match there only if +there are enough required arguments and if the next argument after +binding required and optional arguments, if any, is a keyword. For +efficiency reasons, Guile is currently unable to include keyword +arguments in the matching algorithm. Clauses match on positional +arguments only, not by comparing a given keyword to the available set of +keyword arguments that a function has. + +Some examples follow. + +@example +(define f + (case-lambda* + ((a #:optional b) 'clause-1) + ((a #:optional b #:key c) 'clause-2) + ((a #:key d) 'clause-3) + ((#:key e #:rest f) 'clause-4))) + +(f) @result{} clause-4 +(f 1) @result{} clause-1 +(f) @result{} clause-4 +(f #:e 10) clause-1 +(f 1 #:foo) clause-1 +(f 1 #:c 2) clause-2 +(f #:a #:b #:c #:d #:e) clause-4 + +;; clause-2 will match anything that clause-3 would match. +(f 1 #:d 2) @result{} error: bad keyword args in clause 2 +@end example + +Don't forget that the clauses are matched in order, and the first +matching clause will be taken. This can result in a keyword being bound +to a required argument, as in the case of @code{f #:e 10}. + + +@node Higher-Order Functions +@subsection Higher-Order Functions + +@cindex higher-order functions + +As a functional programming language, Scheme allows the definition of +@dfn{higher-order functions}, i.e., functions that take functions as +arguments and/or return functions. Utilities to derive procedures from +other procedures are provided and described below. + +@deffn {Scheme Procedure} const value +Return a procedure that accepts any number of arguments and returns +@var{value}. + +@lisp +(procedure? (const 3)) @result{} #t +((const 'hello)) @result{} hello +((const 'hello) 'world) @result{} hello +@end lisp +@end deffn + +@deffn {Scheme Procedure} negate proc +Return a procedure with the same arity as @var{proc} that returns the +@code{not} of @var{proc}'s result. + +@lisp +(procedure? (negate number?)) @result{} #t +((negate odd?) 2) @result{} #t +((negate real?) 'dream) @result{} #t +((negate string-prefix?) "GNU" "GNU Guile") + @result{} #f +(filter (negate number?) '(a 2 "b")) + @result{} (a "b") +@end lisp +@end deffn + +@deffn {Scheme Procedure} compose proc1 proc2 @dots{} +Compose @var{proc1} with the procedures @var{proc2} @dots{} such that +the last @var{proc} argument is applied first and @var{proc1} last, and +return the resulting procedure. The given procedures must have +compatible arity. + +@lisp +(procedure? (compose 1+ 1-)) @result{} #t +((compose sqrt 1+ 1+) 2) @result{} 2.0 +((compose 1+ sqrt) 3) @result{} 2.73205080756888 +(eq? (compose 1+) 1+) @result{} #t + +((compose zip unzip2) '((1 2) (a b))) + @result{} ((1 2) (a b)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} identity x +Return X. +@end deffn + +@deffn {Scheme Procedure} and=> value proc +When @var{value} is @code{#f}, return @code{#f}. Otherwise, return +@code{(@var{proc} @var{value})}. +@end deffn + +@node Procedure Properties +@subsection Procedure Properties and Meta-information + +In addition to the information that is strictly necessary to run, +procedures may have other associated information. For example, the +name of a procedure is information not for the procedure, but about +the procedure. This meta-information can be accessed via the procedure +properties interface. + +The first group of procedures in this meta-interface are predicates to +test whether a Scheme object is a procedure, or a special procedure, +respectively. @code{procedure?} is the most general predicates, it +returns @code{#t} for any kind of procedure. + +@rnindex procedure? +@deffn {Scheme Procedure} procedure? obj +@deffnx {C Function} scm_procedure_p (obj) +Return @code{#t} if @var{obj} is a procedure. +@end deffn + +@deffn {Scheme Procedure} thunk? obj +@deffnx {C Function} scm_thunk_p (obj) +Return @code{#t} if @var{obj} is a thunk---a procedure that does +not accept arguments. +@end deffn + +@cindex procedure properties +Procedure properties are general properties associated with +procedures. These can be the name of a procedure or other relevant +information, such as debug hints. + +@deffn {Scheme Procedure} procedure-name proc +@deffnx {C Function} scm_procedure_name (proc) +Return the name of the procedure @var{proc} +@end deffn + +@deffn {Scheme Procedure} procedure-source proc +@deffnx {C Function} scm_procedure_source (proc) +Return the source of the procedure @var{proc}. Returns @code{#f} if +the source code is not available. +@end deffn + +@deffn {Scheme Procedure} procedure-properties proc +@deffnx {C Function} scm_procedure_properties (proc) +Return the properties associated with @var{proc}, as an association +list. +@end deffn + +@deffn {Scheme Procedure} procedure-property proc key +@deffnx {C Function} scm_procedure_property (proc, key) +Return the property of @var{proc} with name @var{key}. +@end deffn + +@deffn {Scheme Procedure} set-procedure-properties! proc alist +@deffnx {C Function} scm_set_procedure_properties_x (proc, alist) +Set @var{proc}'s property list to @var{alist}. +@end deffn + +@deffn {Scheme Procedure} set-procedure-property! proc key value +@deffnx {C Function} scm_set_procedure_property_x (proc, key, value) +In @var{proc}'s property list, set the property named @var{key} to +@var{value}. +@end deffn + +@cindex procedure documentation +Documentation for a procedure can be accessed with the procedure +@code{procedure-documentation}. + +@deffn {Scheme Procedure} procedure-documentation proc +@deffnx {C Function} scm_procedure_documentation (proc) +Return the documentation string associated with @code{proc}. By +convention, if a procedure contains more than one expression and the +first expression is a string constant, that string is assumed to contain +documentation for that procedure. +@end deffn + + +@node Procedures with Setters +@subsection Procedures with Setters + +@c FIXME::martin: Review me! + +@c FIXME::martin: Document `operator struct'. + +@cindex procedure with setter +@cindex setter +A @dfn{procedure with setter} is a special kind of procedure which +normally behaves like any accessor procedure, that is a procedure which +accesses a data structure. The difference is that this kind of +procedure has a so-called @dfn{setter} attached, which is a procedure +for storing something into a data structure. + +Procedures with setters are treated specially when the procedure appears +in the special form @code{set!} (REFFIXME). How it works is best shown +by example. + +Suppose we have a procedure called @code{foo-ref}, which accepts two +arguments, a value of type @code{foo} and an integer. The procedure +returns the value stored at the given index in the @code{foo} object. +Let @code{f} be a variable containing such a @code{foo} data +structure.@footnote{Working definitions would be: +@lisp +(define foo-ref vector-ref) +(define foo-set! vector-set!) +(define f (make-vector 2 #f)) +@end lisp +} + +@lisp +(foo-ref f 0) @result{} bar +(foo-ref f 1) @result{} braz +@end lisp + +Also suppose that a corresponding setter procedure called +@code{foo-set!} does exist. + +@lisp +(foo-set! f 0 'bla) +(foo-ref f 0) @result{} bla +@end lisp + +Now we could create a new procedure called @code{foo}, which is a +procedure with setter, by calling @code{make-procedure-with-setter} with +the accessor and setter procedures @code{foo-ref} and @code{foo-set!}. +Let us call this new procedure @code{foo}. + +@lisp +(define foo (make-procedure-with-setter foo-ref foo-set!)) +@end lisp + +@code{foo} can from now on be used to either read from the data +structure stored in @code{f}, or to write into the structure. + +@lisp +(set! (foo f 0) 'dum) +(foo f 0) @result{} dum +@end lisp + +@deffn {Scheme Procedure} make-procedure-with-setter procedure setter +@deffnx {C Function} scm_make_procedure_with_setter (procedure, setter) +Create a new procedure which behaves like @var{procedure}, but +with the associated setter @var{setter}. +@end deffn + +@deffn {Scheme Procedure} procedure-with-setter? obj +@deffnx {C Function} scm_procedure_with_setter_p (obj) +Return @code{#t} if @var{obj} is a procedure with an +associated setter procedure. +@end deffn + +@deffn {Scheme Procedure} procedure proc +@deffnx {C Function} scm_procedure (proc) +Return the procedure of @var{proc}, which must be an +applicable struct. +@end deffn + +@deffn {Scheme Procedure} setter proc +Return the setter of @var{proc}, which must be either a procedure with +setter or an operator struct. +@end deffn + +@node Inlinable Procedures +@subsection Inlinable Procedures + +@cindex inlining +@cindex procedure inlining +You can define an @dfn{inlinable procedure} by using +@code{define-inlinable} instead of @code{define}. An inlinable +procedure behaves the same as a regular procedure, but direct calls will +result in the procedure body being inlined into the caller. + +@cindex partial evaluator +Bear in mind that starting from version 2.0.3, Guile has a partial +evaluator that can inline the body of inner procedures when deemed +appropriate: + +@example +scheme@@(guile-user)> ,optimize (define (foo x) + (define (bar) (+ x 3)) + (* (bar) 2)) +$1 = (define foo + (lambda (#@{x 94@}#) (* (+ #@{x 94@}# 3) 2))) +@end example + +@noindent +The partial evaluator does not inline top-level bindings, though, so +this is a situation where you may find it interesting to use +@code{define-inlinable}. + +Procedures defined with @code{define-inlinable} are @emph{always} +inlined, at all direct call sites. This eliminates function call +overhead at the expense of an increase in code size. Additionally, the +caller will not transparently use the new definition if the inline +procedure is redefined. It is not possible to trace an inlined +procedures or install a breakpoint in it (@pxref{Traps}). For these +reasons, you should not make a procedure inlinable unless it +demonstrably improves performance in a crucial way. + +In general, only small procedures should be considered for inlining, as +making large procedures inlinable will probably result in an increase in +code size. Additionally, the elimination of the call overhead rarely +matters for large procedures. + +@deffn {Scheme Syntax} define-inlinable (name parameter @dots{}) body1 body2 @dots{} +Define @var{name} as a procedure with parameters @var{parameter}s and +bodies @var{body1}, @var{body2}, @enddots{}. +@end deffn + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-regex.texi b/doc/ref/api-regex.texi new file mode 100644 index 000000000..b14c2b39c --- /dev/null +++ b/doc/ref/api-regex.texi @@ -0,0 +1,534 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2012 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Regular Expressions +@section Regular Expressions +@tpindex Regular expressions + +@cindex regular expressions +@cindex regex +@cindex emacs regexp + +A @dfn{regular expression} (or @dfn{regexp}) is a pattern that +describes a whole class of strings. A full description of regular +expressions and their syntax is beyond the scope of this manual. + +If your system does not include a POSIX regular expression library, +and you have not linked Guile with a third-party regexp library such +as Rx, these functions will not be available. You can tell whether +your Guile installation includes regular expression support by +checking whether @code{(provided? 'regex)} returns true. + +The following regexp and string matching features are provided by the +@code{(ice-9 regex)} module. Before using the described functions, +you should load this module by executing @code{(use-modules (ice-9 +regex))}. + +@menu +* Regexp Functions:: Functions that create and match regexps. +* Match Structures:: Finding what was matched by a regexp. +* Backslash Escapes:: Removing the special meaning of regexp + meta-characters. +@end menu + + +@node Regexp Functions +@subsection Regexp Functions + +By default, Guile supports POSIX extended regular expressions. That +means that the characters @samp{(}, @samp{)}, @samp{+} and @samp{?} are +special, and must be escaped if you wish to match the literal characters +and there is no support for ``non-greedy'' variants of @samp{*}, +@samp{+} or @samp{?}. + +This regular expression interface was modeled after that +implemented by SCSH, the Scheme Shell. It is intended to be +upwardly compatible with SCSH regular expressions. + +Zero bytes (@code{#\nul}) cannot be used in regex patterns or input +strings, since the underlying C functions treat that as the end of +string. If there's a zero byte an error is thrown. + +Internally, patterns and input strings are converted to the current +locale's encoding, and then passed to the C library's regular expression +routines (@pxref{Regular Expressions,,, libc, The GNU C Library +Reference Manual}). The returned match structures always point to +characters in the strings, not to individual bytes, even in the case of +multi-byte encodings. + +@deffn {Scheme Procedure} string-match pattern str [start] +Compile the string @var{pattern} into a regular expression and compare +it with @var{str}. The optional numeric argument @var{start} specifies +the position of @var{str} at which to begin matching. + +@code{string-match} returns a @dfn{match structure} which +describes what, if anything, was matched by the regular +expression. @xref{Match Structures}. If @var{str} does not match +@var{pattern} at all, @code{string-match} returns @code{#f}. +@end deffn + +Two examples of a match follow. In the first example, the pattern +matches the four digits in the match string. In the second, the pattern +matches nothing. + +@example +(string-match "[0-9][0-9][0-9][0-9]" "blah2002") +@result{} #("blah2002" (4 . 8)) + +(string-match "[A-Za-z]" "123456") +@result{} #f +@end example + +Each time @code{string-match} is called, it must compile its +@var{pattern} argument into a regular expression structure. This +operation is expensive, which makes @code{string-match} inefficient if +the same regular expression is used several times (for example, in a +loop). For better performance, you can compile a regular expression in +advance and then match strings against the compiled regexp. + +@deffn {Scheme Procedure} make-regexp pat flag@dots{} +@deffnx {C Function} scm_make_regexp (pat, flaglst) +Compile the regular expression described by @var{pat}, and +return the compiled regexp structure. If @var{pat} does not +describe a legal regular expression, @code{make-regexp} throws +a @code{regular-expression-syntax} error. + +The @var{flag} arguments change the behavior of the compiled +regular expression. The following values may be supplied: + +@defvar regexp/icase +Consider uppercase and lowercase letters to be the same when +matching. +@end defvar + +@defvar regexp/newline +If a newline appears in the target string, then permit the +@samp{^} and @samp{$} operators to match immediately after or +immediately before the newline, respectively. Also, the +@samp{.} and @samp{[^...]} operators will never match a newline +character. The intent of this flag is to treat the target +string as a buffer containing many lines of text, and the +regular expression as a pattern that may match a single one of +those lines. +@end defvar + +@defvar regexp/basic +Compile a basic (``obsolete'') regexp instead of the extended +(``modern'') regexps that are the default. Basic regexps do +not consider @samp{|}, @samp{+} or @samp{?} to be special +characters, and require the @samp{@{...@}} and @samp{(...)} +metacharacters to be backslash-escaped (@pxref{Backslash +Escapes}). There are several other differences between basic +and extended regular expressions, but these are the most +significant. +@end defvar + +@defvar regexp/extended +Compile an extended regular expression rather than a basic +regexp. This is the default behavior; this flag will not +usually be needed. If a call to @code{make-regexp} includes +both @code{regexp/basic} and @code{regexp/extended} flags, the +one which comes last will override the earlier one. +@end defvar +@end deffn + +@deffn {Scheme Procedure} regexp-exec rx str [start [flags]] +@deffnx {C Function} scm_regexp_exec (rx, str, start, flags) +Match the compiled regular expression @var{rx} against +@code{str}. If the optional integer @var{start} argument is +provided, begin matching from that position in the string. +Return a match structure describing the results of the match, +or @code{#f} if no match could be found. + +The @var{flags} argument changes the matching behavior. The following +flag values may be supplied, use @code{logior} (@pxref{Bitwise +Operations}) to combine them, + +@defvar regexp/notbol +Consider that the @var{start} offset into @var{str} is not the +beginning of a line and should not match operator @samp{^}. + +If @var{rx} was created with the @code{regexp/newline} option above, +@samp{^} will still match after a newline in @var{str}. +@end defvar + +@defvar regexp/noteol +Consider that the end of @var{str} is not the end of a line and should +not match operator @samp{$}. + +If @var{rx} was created with the @code{regexp/newline} option above, +@samp{$} will still match before a newline in @var{str}. +@end defvar +@end deffn + +@lisp +;; Regexp to match uppercase letters +(define r (make-regexp "[A-Z]*")) + +;; Regexp to match letters, ignoring case +(define ri (make-regexp "[A-Z]*" regexp/icase)) + +;; Search for bob using regexp r +(match:substring (regexp-exec r "bob")) +@result{} "" ; no match + +;; Search for bob using regexp ri +(match:substring (regexp-exec ri "Bob")) +@result{} "Bob" ; matched case insensitive +@end lisp + +@deffn {Scheme Procedure} regexp? obj +@deffnx {C Function} scm_regexp_p (obj) +Return @code{#t} if @var{obj} is a compiled regular expression, +or @code{#f} otherwise. +@end deffn + +@sp 1 +@deffn {Scheme Procedure} list-matches regexp str [flags] +Return a list of match structures which are the non-overlapping +matches of @var{regexp} in @var{str}. @var{regexp} can be either a +pattern string or a compiled regexp. The @var{flags} argument is as +per @code{regexp-exec} above. + +@example +(map match:substring (list-matches "[a-z]+" "abc 42 def 78")) +@result{} ("abc" "def") +@end example +@end deffn + +@deffn {Scheme Procedure} fold-matches regexp str init proc [flags] +Apply @var{proc} to the non-overlapping matches of @var{regexp} in +@var{str}, to build a result. @var{regexp} can be either a pattern +string or a compiled regexp. The @var{flags} argument is as per +@code{regexp-exec} above. + +@var{proc} is called as @code{(@var{proc} match prev)} where +@var{match} is a match structure and @var{prev} is the previous return +from @var{proc}. For the first call @var{prev} is the given +@var{init} parameter. @code{fold-matches} returns the final value +from @var{proc}. + +For example to count matches, + +@example +(fold-matches "[a-z][0-9]" "abc x1 def y2" 0 + (lambda (match count) + (1+ count))) +@result{} 2 +@end example +@end deffn + +@sp 1 +Regular expressions are commonly used to find patterns in one string +and replace them with the contents of another string. The following +functions are convenient ways to do this. + +@c begin (scm-doc-string "regex.scm" "regexp-substitute") +@deffn {Scheme Procedure} regexp-substitute port match item @dots{} +Write to @var{port} selected parts of the match structure @var{match}. +Or if @var{port} is @code{#f} then form a string from those parts and +return that. + +Each @var{item} specifies a part to be written, and may be one of the +following, + +@itemize @bullet +@item +A string. String arguments are written out verbatim. + +@item +An integer. The submatch with that number is written +(@code{match:substring}). Zero is the entire match. + +@item +The symbol @samp{pre}. The portion of the matched string preceding +the regexp match is written (@code{match:prefix}). + +@item +The symbol @samp{post}. The portion of the matched string following +the regexp match is written (@code{match:suffix}). +@end itemize + +For example, changing a match and retaining the text before and after, + +@example +(regexp-substitute #f (string-match "[0-9]+" "number 25 is good") + 'pre "37" 'post) +@result{} "number 37 is good" +@end example + +Or matching a @sc{yyyymmdd} format date such as @samp{20020828} and +re-ordering and hyphenating the fields. + +@lisp +(define date-regex + "([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])") +(define s "Date 20020429 12am.") +(regexp-substitute #f (string-match date-regex s) + 'pre 2 "-" 3 "-" 1 'post " (" 0 ")") +@result{} "Date 04-29-2002 12am. (20020429)" +@end lisp +@end deffn + + +@c begin (scm-doc-string "regex.scm" "regexp-substitute") +@deffn {Scheme Procedure} regexp-substitute/global port regexp target item@dots{} +@cindex search and replace +Write to @var{port} selected parts of matches of @var{regexp} in +@var{target}. If @var{port} is @code{#f} then form a string from +those parts and return that. @var{regexp} can be a string or a +compiled regex. + +This is similar to @code{regexp-substitute}, but allows global +substitutions on @var{target}. Each @var{item} behaves as per +@code{regexp-substitute}, with the following differences, + +@itemize @bullet +@item +A function. Called as @code{(@var{item} match)} with the match +structure for the @var{regexp} match, it should return a string to be +written to @var{port}. + +@item +The symbol @samp{post}. This doesn't output anything, but instead +causes @code{regexp-substitute/global} to recurse on the unmatched +portion of @var{target}. + +This @emph{must} be supplied to perform a global search and replace on +@var{target}; without it @code{regexp-substitute/global} returns after +a single match and output. +@end itemize + +For example, to collapse runs of tabs and spaces to a single hyphen +each, + +@example +(regexp-substitute/global #f "[ \t]+" "this is the text" + 'pre "-" 'post) +@result{} "this-is-the-text" +@end example + +Or using a function to reverse the letters in each word, + +@example +(regexp-substitute/global #f "[a-z]+" "to do and not-do" + 'pre (lambda (m) (string-reverse (match:substring m))) 'post) +@result{} "ot od dna ton-od" +@end example + +Without the @code{post} symbol, just one regexp match is made. For +example the following is the date example from +@code{regexp-substitute} above, without the need for the separate +@code{string-match} call. + +@lisp +(define date-regex + "([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])") +(define s "Date 20020429 12am.") +(regexp-substitute/global #f date-regex s + 'pre 2 "-" 3 "-" 1 'post " (" 0 ")") + +@result{} "Date 04-29-2002 12am. (20020429)" +@end lisp +@end deffn + + +@node Match Structures +@subsection Match Structures + +@cindex match structures + +A @dfn{match structure} is the object returned by @code{string-match} and +@code{regexp-exec}. It describes which portion of a string, if any, +matched the given regular expression. Match structures include: a +reference to the string that was checked for matches; the starting and +ending positions of the regexp match; and, if the regexp included any +parenthesized subexpressions, the starting and ending positions of each +submatch. + +In each of the regexp match functions described below, the @code{match} +argument must be a match structure returned by a previous call to +@code{string-match} or @code{regexp-exec}. Most of these functions +return some information about the original target string that was +matched against a regular expression; we will call that string +@var{target} for easy reference. + +@c begin (scm-doc-string "regex.scm" "regexp-match?") +@deffn {Scheme Procedure} regexp-match? obj +Return @code{#t} if @var{obj} is a match structure returned by a +previous call to @code{regexp-exec}, or @code{#f} otherwise. +@end deffn + +@c begin (scm-doc-string "regex.scm" "match:substring") +@deffn {Scheme Procedure} match:substring match [n] +Return the portion of @var{target} matched by subexpression number +@var{n}. Submatch 0 (the default) represents the entire regexp match. +If the regular expression as a whole matched, but the subexpression +number @var{n} did not match, return @code{#f}. +@end deffn + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:substring s) +@result{} "2002" + +;; match starting at offset 6 in the string +(match:substring + (string-match "[0-9][0-9][0-9][0-9]" "blah987654" 6)) +@result{} "7654" +@end lisp + +@c begin (scm-doc-string "regex.scm" "match:start") +@deffn {Scheme Procedure} match:start match [n] +Return the starting position of submatch number @var{n}. +@end deffn + +In the following example, the result is 4, since the match starts at +character index 4: + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:start s) +@result{} 4 +@end lisp + +@c begin (scm-doc-string "regex.scm" "match:end") +@deffn {Scheme Procedure} match:end match [n] +Return the ending position of submatch number @var{n}. +@end deffn + +In the following example, the result is 8, since the match runs between +characters 4 and 8 (i.e.@: the ``2002''). + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:end s) +@result{} 8 +@end lisp + +@c begin (scm-doc-string "regex.scm" "match:prefix") +@deffn {Scheme Procedure} match:prefix match +Return the unmatched portion of @var{target} preceding the regexp match. + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:prefix s) +@result{} "blah" +@end lisp +@end deffn + +@c begin (scm-doc-string "regex.scm" "match:suffix") +@deffn {Scheme Procedure} match:suffix match +Return the unmatched portion of @var{target} following the regexp match. +@end deffn + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:suffix s) +@result{} "foo" +@end lisp + +@c begin (scm-doc-string "regex.scm" "match:count") +@deffn {Scheme Procedure} match:count match +Return the number of parenthesized subexpressions from @var{match}. +Note that the entire regular expression match itself counts as a +subexpression, and failed submatches are included in the count. +@end deffn + +@c begin (scm-doc-string "regex.scm" "match:string") +@deffn {Scheme Procedure} match:string match +Return the original @var{target} string. +@end deffn + +@lisp +(define s (string-match "[0-9][0-9][0-9][0-9]" "blah2002foo")) +(match:string s) +@result{} "blah2002foo" +@end lisp + + +@node Backslash Escapes +@subsection Backslash Escapes + +Sometimes you will want a regexp to match characters like @samp{*} or +@samp{$} exactly. For example, to check whether a particular string +represents a menu entry from an Info node, it would be useful to match +it against a regexp like @samp{^* [^:]*::}. However, this won't work; +because the asterisk is a metacharacter, it won't match the @samp{*} at +the beginning of the string. In this case, we want to make the first +asterisk un-magic. + +You can do this by preceding the metacharacter with a backslash +character @samp{\}. (This is also called @dfn{quoting} the +metacharacter, and is known as a @dfn{backslash escape}.) When Guile +sees a backslash in a regular expression, it considers the following +glyph to be an ordinary character, no matter what special meaning it +would ordinarily have. Therefore, we can make the above example work by +changing the regexp to @samp{^\* [^:]*::}. The @samp{\*} sequence tells +the regular expression engine to match only a single asterisk in the +target string. + +Since the backslash is itself a metacharacter, you may force a regexp to +match a backslash in the target string by preceding the backslash with +itself. For example, to find variable references in a @TeX{} program, +you might want to find occurrences of the string @samp{\let\} followed +by any number of alphabetic characters. The regular expression +@samp{\\let\\[A-Za-z]*} would do this: the double backslashes in the +regexp each match a single backslash in the target string. + +@c begin (scm-doc-string "regex.scm" "regexp-quote") +@deffn {Scheme Procedure} regexp-quote str +Quote each special character found in @var{str} with a backslash, and +return the resulting string. +@end deffn + +@strong{Very important:} Using backslash escapes in Guile source code +(as in Emacs Lisp or C) can be tricky, because the backslash character +has special meaning for the Guile reader. For example, if Guile +encounters the character sequence @samp{\n} in the middle of a string +while processing Scheme code, it replaces those characters with a +newline character. Similarly, the character sequence @samp{\t} is +replaced by a horizontal tab. Several of these @dfn{escape sequences} +are processed by the Guile reader before your code is executed. +Unrecognized escape sequences are ignored: if the characters @samp{\*} +appear in a string, they will be translated to the single character +@samp{*}. + +This translation is obviously undesirable for regular expressions, since +we want to be able to include backslashes in a string in order to +escape regexp metacharacters. Therefore, to make sure that a backslash +is preserved in a string in your Guile program, you must use @emph{two} +consecutive backslashes: + +@lisp +(define Info-menu-entry-pattern (make-regexp "^\\* [^:]*")) +@end lisp + +The string in this example is preprocessed by the Guile reader before +any code is executed. The resulting argument to @code{make-regexp} is +the string @samp{^\* [^:]*}, which is what we really want. + +This also means that in order to write a regular expression that matches +a single backslash character, the regular expression string in the +source code must include @emph{four} backslashes. Each consecutive pair +of backslashes gets translated by the Guile reader to a single +backslash, and the resulting double-backslash is interpreted by the +regexp engine as matching a single backslash character. Hence: + +@lisp +(define tex-variable-pattern (make-regexp "\\\\let\\\\=[A-Za-z]*")) +@end lisp + +The reason for the unwieldiness of this syntax is historical. Both +regular expression pattern matchers and Unix string processing systems +have traditionally used backslashes with the special meanings +described above. The POSIX regular expression specification and ANSI C +standard both require these semantics. Attempting to abandon either +convention would cause other kinds of compatibility problems, possibly +more severe ones. Therefore, without extending the Scheme reader to +support strings with different quoting conventions (an ungainly and +confusing extension when implemented in other languages), we must adhere +to this cumbersome escape syntax. diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi new file mode 100644 index 000000000..7b39a03d6 --- /dev/null +++ b/doc/ref/api-scheduling.texi @@ -0,0 +1,994 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2012, 2013 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Scheduling +@section Threads, Mutexes, Asyncs and Dynamic Roots + +@menu +* Threads:: Multiple threads of execution. +* Thread Local Variables:: Some fluids are thread-local. +* Asyncs:: Asynchronous interrupts. +* Atomics:: Atomic references. +* Mutexes and Condition Variables:: Synchronization primitives. +* Blocking:: How to block properly in guile mode. +* Futures:: Fine-grain parallelism. +* Parallel Forms:: Parallel execution of forms. +@end menu + + +@node Threads +@subsection Threads +@cindex threads +@cindex Guile threads +@cindex POSIX threads + +Guile supports POSIX threads, unless it was configured with +@code{--without-threads} or the host lacks POSIX thread support. When +thread support is available, the @code{threads} feature is provided +(@pxref{Feature Manipulation, @code{provided?}}). + +The procedures below manipulate Guile threads, which are wrappers around +the system's POSIX threads. For application-level parallelism, using +higher-level constructs, such as futures, is recommended +(@pxref{Futures}). + +To use these facilities, load the @code{(ice-9 threads)} module. + +@example +(use-modules (ice-9 threads)) +@end example + +@deffn {Scheme Procedure} all-threads +@deffnx {C Function} scm_all_threads () +Return a list of all threads. +@end deffn + +@deffn {Scheme Procedure} current-thread +@deffnx {C Function} scm_current_thread () +Return the thread that called this function. +@end deffn + +@deffn {Scheme Procedure} call-with-new-thread thunk [handler] +Call @code{thunk} in a new thread and with a new dynamic state, +returning the new thread. The procedure @var{thunk} is called via +@code{with-continuation-barrier}. + +When @var{handler} is specified, then @var{thunk} is called from +within a @code{catch} with tag @code{#t} that has @var{handler} as its +handler. This catch is established inside the continuation barrier. + +Once @var{thunk} or @var{handler} returns, the return value is made +the @emph{exit value} of the thread and the thread is terminated. +@end deffn + +@deftypefn {C Function} SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data) +Call @var{body} in a new thread, passing it @var{body_data}, returning +the new thread. The function @var{body} is called via +@code{scm_c_with_continuation_barrier}. + +When @var{handler} is non-@code{NULL}, @var{body} is called via +@code{scm_internal_catch} with tag @code{SCM_BOOL_T} that has +@var{handler} and @var{handler_data} as the handler and its data. This +catch is established inside the continuation barrier. + +Once @var{body} or @var{handler} returns, the return value is made the +@emph{exit value} of the thread and the thread is terminated. +@end deftypefn + +@deffn {Scheme Procedure} thread? obj +@deffnx {C Function} scm_thread_p (obj) +Return @code{#t} ff @var{obj} is a thread; otherwise, return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} join-thread thread [timeout [timeoutval]] +@deffnx {C Function} scm_join_thread (thread) +@deffnx {C Function} scm_join_thread_timed (thread, timeout, timeoutval) +Wait for @var{thread} to terminate and return its exit value. Only +threads that were created with @code{call-with-new-thread} or +@code{scm_spawn_thread} can be joinable; attempting to join a foreign +thread will raise an error. + +When @var{timeout} is given, it specifies a point in time where the +waiting should be aborted. It can be either an integer as returned by +@code{current-time} or a pair as returned by @code{gettimeofday}. When +the waiting is aborted, @var{timeoutval} is returned (if it is +specified; @code{#f} is returned otherwise). +@end deffn + +@deffn {Scheme Procedure} thread-exited? thread +@deffnx {C Function} scm_thread_exited_p (thread) +Return @code{#t} if @var{thread} has exited, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} yield +@deffnx {C Function} scm_yield (thread) +If one or more threads are waiting to execute, calling yield forces an +immediate context switch to one of them. Otherwise, yield has no effect. +@end deffn + +@deffn {Scheme Procedure} cancel-thread thread . values +@deffnx {C Function} scm_cancel_thread (thread) +Asynchronously interrupt @var{thread} and ask it to terminate. +@code{dynamic-wind} post thunks will run, but throw handlers will not. +If @var{thread} has already terminated or been signaled to terminate, +this function is a no-op. Calling @code{join-thread} on the thread will +return the given @var{values}, if the cancel succeeded. + +Under the hood, thread cancellation uses @code{system-async-mark} and +@code{abort-to-prompt}. @xref{Asyncs} for more on asynchronous +interrupts. +@end deffn + +@deffn macro make-thread proc arg @dots{} +Apply @var{proc} to @var{arg} @dots{} in a new thread formed by +@code{call-with-new-thread} using a default error handler that display +the error to the current error port. The @var{arg} @dots{} +expressions are evaluated in the new thread. +@end deffn + +@deffn macro begin-thread expr1 expr2 @dots{} +Evaluate forms @var{expr1} @var{expr2} @dots{} in a new thread formed by +@code{call-with-new-thread} using a default error handler that display +the error to the current error port. +@end deffn + +One often wants to limit the number of threads running to be +proportional to the number of available processors. These interfaces +are therefore exported by (ice-9 threads) as well. + +@deffn {Scheme Procedure} total-processor-count +@deffnx {C Function} scm_total_processor_count () +Return the total number of processors of the machine, which +is guaranteed to be at least 1. A ``processor'' here is a +thread execution unit, which can be either: + +@itemize +@item an execution core in a (possibly multi-core) chip, in a + (possibly multi- chip) module, in a single computer, or +@item a thread execution unit inside a core in the case of + @dfn{hyper-threaded} CPUs. +@end itemize + +Which of the two definitions is used, is unspecified. +@end deffn + +@deffn {Scheme Procedure} current-processor-count +@deffnx {C Function} scm_current_processor_count () +Like @code{total-processor-count}, but return the number of +processors available to the current process. See +@code{setaffinity} and @code{getaffinity} for more +information. +@end deffn + + +@node Thread Local Variables +@subsection Thread-Local Variables + +Sometimes you want to establish a variable binding that is only valid +for a given thread: a ``thread-local variable''. + +You would think that fluids or parameters would be Guile's answer for +thread-local variables, since establishing a new fluid binding doesn't +affect bindings in other threads. @xref{Fluids and Dynamic States}, or +@xref{Parameters}. However, new threads inherit the fluid bindings that +were in place in their creator threads. In this way, a binding +established using a fluid (or a parameter) in a thread can escape to +other threads, which might not be what you want. Or, it might escape +via explicit reification via @code{current-dynamic-state}. + +Of course, this dynamic scoping might be exactly what you want; that's +why fluids and parameters work this way, and is what you want for for +many common parameters such as the current input and output ports, the +current locale conversion parameters, and the like. Perhaps this is the +case for most parameters, even. If your use case for thread-local +bindings comes from a desire to isolate a binding from its setting in +unrelated threads, then fluids and parameters apply nicely. + +On the other hand, if your use case is to prevent concurrent access to a +value from multiple threads, then using vanilla fluids or parameters is +not appropriate. For this purpose, Guile has @dfn{thread-local fluids}. +A fluid created with @code{make-thread-local-fluid} won't be captured by +@code{current-dynamic-state} and won't be propagated to new threads. + +@deffn {Scheme Procedure} make-thread-local-fluid [dflt] +@deffnx {C Function} scm_make_thread_local_fluid (dflt) +Return a newly created fluid, whose initial value is @var{dflt}, or +@code{#f} if @var{dflt} is not given. Unlike fluids made with +@code{make-fluid}, thread local fluids are not captured by +@code{make-dynamic-state}. Similarly, a newly spawned child thread does +not inherit thread-local fluid values from the parent thread. +@end deffn + +@deffn {Scheme Procedure} fluid-thread-local? fluid +@deffnx {C Function} scm_fluid_thread_local_p (fluid) +Return @code{#t} if the fluid @var{fluid} is is thread-local, or +@code{#f} otherwise. +@end deffn + +For example: + +@example +(define %thread-local (make-thread-local-fluid)) + +(with-fluids ((%thread-local (compute-data))) + ... (fluid-ref %thread-local) ...) +@end example + +You can also make a thread-local parameter out of a thread-local fluid +using the normal @code{fluid->parameter}: + +@example +(define param (fluid->parameter (make-thread-local-fluid))) + +(parameterize ((param (compute-data))) + ... (param) ...) +@end example + + +@node Asyncs +@subsection Asynchronous Interrupts + +@cindex asyncs +@cindex asynchronous interrupts +@cindex interrupts + +Every Guile thread can be interrupted. Threads running Guile code will +periodically check if there are pending interrupts and run them if +necessary. To interrupt a thread, call @code{system-async-mark} on that +thread. + +@deffn {Scheme Procedure} system-async-mark proc [thread] +@deffnx {C Function} scm_system_async_mark (proc) +@deffnx {C Function} scm_system_async_mark_for_thread (proc, thread) +Enqueue @var{proc} (a procedure with zero arguments) for future +execution in @var{thread}. When @var{proc} has already been enqueued +for @var{thread} but has not been executed yet, this call has no effect. +When @var{thread} is omitted, the thread that called +@code{system-async-mark} is used. +@end deffn + +Note that @code{scm_system_async_mark_for_thread} is not +``async-signal-safe'' and so cannot be called from a C signal handler. +(Indeed in general, @code{libguile} functions are not safe to call from +C signal handlers.) + +Though an interrupt procedure can have any side effect permitted to +Guile code, asynchronous interrupts are generally used either for +profiling or for prematurely cancelling a computation. The former case +is mostly transparent to the program being run, by design, but the +latter case can introduce bugs. Like finalizers (@pxref{Foreign Object +Memory Management}), asynchronous interrupts introduce concurrency in a +program. An asyncronous interrupt can run in the middle of some +mutex-protected operation, for example, and potentially corrupt the +program's state. + +If some bit of Guile code needs to temporarily inhibit interrupts, it +can use @code{call-with-blocked-asyncs}. This function works by +temporarily increasing the @emph{async blocking level} of the current +thread while a given procedure is running. The blocking level starts +out at zero, and whenever a safe point is reached, a blocking level +greater than zero will prevent the execution of queued asyncs. + +Analogously, the procedure @code{call-with-unblocked-asyncs} will +temporarily decrease the blocking level of the current thread. You +can use it when you want to disable asyncs by default and only allow +them temporarily. + +In addition to the C versions of @code{call-with-blocked-asyncs} and +@code{call-with-unblocked-asyncs}, C code can use +@code{scm_dynwind_block_asyncs} and @code{scm_dynwind_unblock_asyncs} +inside a @dfn{dynamic context} (@pxref{Dynamic Wind}) to block or +unblock asyncs temporarily. + +@deffn {Scheme Procedure} call-with-blocked-asyncs proc +@deffnx {C Function} scm_call_with_blocked_asyncs (proc) +Call @var{proc} and block the execution of asyncs by one level for the +current thread while it is running. Return the value returned by +@var{proc}. For the first two variants, call @var{proc} with no +arguments; for the third, call it with @var{data}. +@end deffn + +@deftypefn {C Function} {void *} scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data) +The same but with a C function @var{proc} instead of a Scheme thunk. +@end deftypefn + +@deffn {Scheme Procedure} call-with-unblocked-asyncs proc +@deffnx {C Function} scm_call_with_unblocked_asyncs (proc) +Call @var{proc} and unblock the execution of asyncs by one level for the +current thread while it is running. Return the value returned by +@var{proc}. For the first two variants, call @var{proc} with no +arguments; for the third, call it with @var{data}. +@end deffn + +@deftypefn {C Function} {void *} scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data) +The same but with a C function @var{proc} instead of a Scheme thunk. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_block_asyncs () +During the current dynwind context, increase the blocking of asyncs by +one level. This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_unblock_asyncs () +During the current dynwind context, decrease the blocking of asyncs by +one level. This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). +@end deftypefn + +Sometimes you want to interrupt a thread that might be waiting for +something to happen, for example on a file descriptor or a condition +variable. In that case you can inform Guile of how to interrupt that +wait using the following procedures: + +@deftypefn {C Function} int scm_c_prepare_to_wait_on_fd (int fd) +Inform Guile that the current thread is about to sleep, and that if an +asynchronous interrupt is signalled on this thread, Guile should wake up +the thread by writing a zero byte to @var{fd}. Returns zero if the +prepare succeeded, or nonzero if the thread already has a pending async +and that it should avoid waiting. +@end deftypefn + +@deftypefn {C Function} int scm_c_prepare_to_wait_on_cond (scm_i_pthread_mutex_t *mutex, scm_i_pthread_cond_t *cond) +Inform Guile that the current thread is about to sleep, and that if an +asynchronous interrupt is signalled on this thread, Guile should wake up +the thread by acquiring @var{mutex} and signalling @var{cond}. The +caller must already hold @var{mutex} and only drop it as part of the +@code{pthread_cond_wait} call. Returns zero if the prepare succeeded, +or nonzero if the thread already has a pending async and that it should +avoid waiting. +@end deftypefn + +@deftypefn {C Function} void scm_c_wait_finished (void) +Inform Guile that the current thread has finished waiting, and that +asynchronous interrupts no longer need any special wakeup action; the +current thread will periodically poll its internal queue instead. +@end deftypefn + +Guile's own interface to @code{sleep}, @code{wait-condition-variable}, +@code{select}, and so on all call the above routines as appropriate. + +Finally, note that threads can also be interrupted via POSIX signals. +@xref{Signals}. As an implementation detail, signal handlers will +effectively call @code{system-async-mark} in a signal-safe way, +eventually running the signal handler using the same async mechanism. +In this way you can temporarily inhibit signal handlers from running +using the above interfaces. + + +@node Atomics +@subsection Atomics + +When accessing data in parallel from multiple threads, updates made by +one thread are not generally guaranteed to be visible by another thread. +It could be that your hardware requires special instructions to be +emitted to propagate a change from one CPU core to another. Or, it +could be that your hardware updates values with a sequence of +instructions, and a parallel thread could see a value that is in the +process of being updated but not fully updated. + +Atomic references solve this problem. Atomics are a standard, primitive +facility to allow for concurrent access and update of mutable variables +from multiple threads with guaranteed forward-progress and well-defined +intermediate states. + +Atomic references serve not only as a hardware memory barrier but also +as a compiler barrier. Normally a compiler might choose to reorder or +elide certain memory accesses due to optimizations like common +subexpression elimination. Atomic accesses however will not be +reordered relative to each other, and normal memory accesses will not be +reordered across atomic accesses. + +As an implementation detail, currently all atomic accesses and updates +use the sequential consistency memory model from C11. We may relax this +in the future to the acquire/release semantics, which still issues a +memory barrier so that non-atomic updates are not reordered across +atomic accesses or updates. + +To use Guile's atomic operations, load the @code{(ice-9 atomic)} module: + +@example +(use-modules (ice-9 atomic)) +@end example + +@deffn {Scheme Procedure} make-atomic-box init +Return an atomic box initialized to value @var{init}. +@end deffn + +@deffn {Scheme Procedure} atomic-box? obj +Return @code{#t} if @var{obj} is an atomic-box object, else +return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} atomic-box-ref box +Fetch the value stored in the atomic box @var{box} and return it. +@end deffn + +@deffn {Scheme Procedure} atomic-box-set! box val +Store @var{val} into the atomic box @var{box}. +@end deffn + +@deffn {Scheme Procedure} atomic-box-swap! box val +Store @var{val} into the atomic box @var{box}, and return the value that +was previously stored in the box. +@end deffn + +@deffn {Scheme Procedure} atomic-box-compare-and-swap! box expected desired +If the value of the atomic box @var{box} is the same as, @var{expected} +(in the sense of @code{eq?}), replace the contents of the box with +@var{desired}. Otherwise does not update the box. Returns the previous +value of the box in either case, so you can know if the swap worked by +checking if the return value is @code{eq?} to @var{expected}. +@end deffn + + +@node Mutexes and Condition Variables +@subsection Mutexes and Condition Variables +@cindex mutex +@cindex condition variable + +Mutexes are low-level primitives used to coordinate concurrent access to +mutable data. Short for ``mutual exclusion'', the name ``mutex'' +indicates that only one thread at a time can acquire access to data that +is protected by a mutex -- threads are excluded from accessing data at +the same time. If one thread has locked a mutex, then another thread +attempting to lock that same mutex will wait until the first thread is +done. + +Mutexes can be used to build robust multi-threaded programs that take +advantage of multiple cores. However, they provide very low-level +functionality and are somewhat dangerous; usually you end up wanting to +acquire multiple mutexes at the same time to perform a multi-object +access, but this can easily lead to deadlocks if the program is not +carefully written. For example, if objects A and B are protected by +associated mutexes M and N, respectively, then to access both of them +then you need to acquire both mutexes. But what if one thread acquires +M first and then N, at the same time that another thread acquires N them +M? You can easily end up in a situation where one is waiting for the +other. + +There's no easy way around this problem on the language level. A +function A that uses mutexes does not necessarily compose nicely with a +function B that uses mutexes. For this reason we suggest using atomic +variables when you can (@pxref{Atomics}), as they do not have this problem. + +Still, if you as a programmer are responsible for a whole system, then +you can use mutexes as a primitive to provide safe concurrent +abstractions to your users. (For example, given all locks in a system, +if you establish an order such that M is consistently acquired before N, +you can avoid the ``deadly-embrace'' deadlock described above. The +problem is enumerating all mutexes and establishing this order from a +system perspective.) Guile gives you the low-level facilities to build +such systems. + +In Guile there are additional considerations beyond the usual ones in +other programming languages: non-local control flow and asynchronous +interrupts. What happens if you hold a mutex, but somehow you cause an +exception to be thrown? There is no one right answer. You might want +to keep the mutex locked to prevent any other code from ever entering +that critical section again. Or, your critical section might be fine if +you unlock the mutex ``on the way out'', via a catch handler or +@code{dynamic-wind}. @xref{Catch}, and @xref{Dynamic Wind}. + +But if you arrange to unlock the mutex when leaving a dynamic extent via +@code{dynamic-wind}, what to do if control re-enters that dynamic extent +via a continuation invocation? Surely re-entering the dynamic extent +without the lock is a bad idea, so there are two options on the table: +either prevent re-entry via @code{with-continuation-barrier} or similar, +or reacquire the lock in the entry thunk of a @code{dynamic-wind}. + +You might think that because you don't use continuations, that you don't +have to think about this, and you might be right. If you control the +whole system, you can reason about continuation use globally. Or, if +you know all code that can be called in a dynamic extent, and none of +that code can call continuations, then you don't have to worry about +re-entry, and you might not have to worry about early exit either. + +However, do consider the possibility of asynchronous interrupts +(@pxref{Asyncs}). If the user interrupts your code interactively, that +can cause an exception; or your thread might be cancelled, which does +the same; or the user could be running your code under some pre-emptive +system that periodically causes lightweight task switching. (Guile does +not currently include such a system, but it's possible to implement as a +library.) Probably you also want to defer asynchronous interrupt +processing while you hold the mutex, and probably that also means that +you should not hold the mutex for very long. + +All of these additional Guile-specific considerations mean that from a +system perspective, you would do well to avoid these hazards if you can +by not requiring mutexes. Instead, work with immutable data that can be +shared between threads without hazards, or use persistent data +structures with atomic updates based on the atomic variable library +(@pxref{Atomics}). + +There are three types of mutexes in Guile: ``standard'', ``recursive'', +and ``unowned''. + +Calling @code{make-mutex} with no arguments makes a standard mutex. A +standard mutex can only be locked once. If you try to lock it again +from the thread that locked it to begin with (the "owner" thread), it +throws an error. It can only be unlocked from the thread that locked it +in the first place. + +Calling @code{make-mutex} with the symbol @code{recursive} as the +argument, or calling @code{make-recursive-mutex}, will give you a +recursive mutex. A recursive mutex can be locked multiple times by its +owner. It then has to be unlocked the corresponding number of times, +and like standard mutexes can only be unlocked by the owner thread. + +Finally, calling @code{make-mutex} with the symbol +@code{allow-external-unlock} creates an unowned mutex. An unowned mutex +is like a standard mutex, except that it can be unlocked by any thread. +A corollary of this behavior is that a thread's attempt to lock a mutex +that it already owns will block instead of signalling an error, as it +could be that some other thread unlocks the mutex, allowing the owner +thread to proceed. This kind of mutex is a bit strange and is here for +use by SRFI-18. + +The mutex procedures in Guile can operate on all three kinds of mutexes. + +To use these facilities, load the @code{(ice-9 threads)} module. + +@example +(use-modules (ice-9 threads)) +@end example + +@sp 1 +@deffn {Scheme Procedure} make-mutex [kind] +@deffnx {C Function} scm_make_mutex () +@deffnx {C Function} scm_make_mutex_with_kind (SCM kind) +Return a new mutex. It will be a standard non-recursive mutex, unless +the @code{recursive} symbol is passed as the optional @var{kind} +argument, in which case it will be recursive. It's also possible to +pass @code{unowned} for semantics tailored to SRFI-18's use case; see +above for details. +@end deffn + +@deffn {Scheme Procedure} mutex? obj +@deffnx {C Function} scm_mutex_p (obj) +Return @code{#t} if @var{obj} is a mutex; otherwise, return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} make-recursive-mutex +@deffnx {C Function} scm_make_recursive_mutex () +Create a new recursive mutex. It is initially unlocked. Calling this +function is equivalent to calling @code{make-mutex} with the +@code{recursive} kind. +@end deffn + +@deffn {Scheme Procedure} lock-mutex mutex [timeout] +@deffnx {C Function} scm_lock_mutex (mutex) +@deffnx {C Function} scm_timed_lock_mutex (mutex, timeout) +Lock @var{mutex} and return @code{#t}. If the mutex is already locked, +then block and return only when @var{mutex} has been acquired. + +When @var{timeout} is given, it specifies a point in time where the +waiting should be aborted. It can be either an integer as returned +by @code{current-time} or a pair as returned by @code{gettimeofday}. +When the waiting is aborted, @code{#f} is returned. + +For standard mutexes (@code{make-mutex}), an error is signalled if the +thread has itself already locked @var{mutex}. + +For a recursive mutex (@code{make-recursive-mutex}), if the thread has +itself already locked @var{mutex}, then a further @code{lock-mutex} +call increments the lock count. An additional @code{unlock-mutex} +will be required to finally release. + +When an asynchronous interrupt (@pxref{Asyncs}) is scheduled for a +thread blocked in @code{lock-mutex}, Guile will interrupt the wait, run +the interrupts, and then resume the wait. +@end deffn + +@deftypefn {C Function} void scm_dynwind_lock_mutex (SCM mutex) +Arrange for @var{mutex} to be locked whenever the current dynwind +context is entered and to be unlocked when it is exited. +@end deftypefn + +@deffn {Scheme Procedure} try-mutex mx +@deffnx {C Function} scm_try_mutex (mx) +Try to lock @var{mutex} and return @code{#t} if successful, or @code{#f} +otherwise. This is like calling @code{lock-mutex} with an expired +timeout. +@end deffn + +@deffn {Scheme Procedure} unlock-mutex mutex +@deffnx {C Function} scm_unlock_mutex (mutex) +Unlock @var{mutex}. An error is signalled if @var{mutex} is not locked. + +``Standard'' and ``recursive'' mutexes can only be unlocked by the +thread that locked them; Guile detects this situation and signals an +error. ``Unowned'' mutexes can be unlocked by any thread. +@end deffn + +@deffn {Scheme Procedure} mutex-owner mutex +@deffnx {C Function} scm_mutex_owner (mutex) +Return the current owner of @var{mutex}, in the form of a thread or +@code{#f} (indicating no owner). Note that a mutex may be unowned but +still locked. +@end deffn + +@deffn {Scheme Procedure} mutex-level mutex +@deffnx {C Function} scm_mutex_level (mutex) +Return the current lock level of @var{mutex}. If @var{mutex} is +currently unlocked, this value will be 0; otherwise, it will be the +number of times @var{mutex} has been recursively locked by its current +owner. +@end deffn + +@deffn {Scheme Procedure} mutex-locked? mutex +@deffnx {C Function} scm_mutex_locked_p (mutex) +Return @code{#t} if @var{mutex} is locked, regardless of ownership; +otherwise, return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} make-condition-variable +@deffnx {C Function} scm_make_condition_variable () +Return a new condition variable. +@end deffn + +@deffn {Scheme Procedure} condition-variable? obj +@deffnx {C Function} scm_condition_variable_p (obj) +Return @code{#t} if @var{obj} is a condition variable; otherwise, +return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} wait-condition-variable condvar mutex [time] +@deffnx {C Function} scm_wait_condition_variable (condvar, mutex, time) +Wait until @var{condvar} has been signalled. While waiting, +@var{mutex} is atomically unlocked (as with @code{unlock-mutex}) and +is locked again when this function returns. When @var{time} is given, +it specifies a point in time where the waiting should be aborted. It +can be either a integer as returned by @code{current-time} or a pair +as returned by @code{gettimeofday}. When the waiting is aborted, +@code{#f} is returned. When the condition variable has in fact been +signalled, @code{#t} is returned. The mutex is re-locked in any case +before @code{wait-condition-variable} returns. + +When an async is activated for a thread that is blocked in a call to +@code{wait-condition-variable}, the waiting is interrupted, the mutex is +locked, and the async is executed. When the async returns, the mutex is +unlocked again and the waiting is resumed. When the thread block while +re-acquiring the mutex, execution of asyncs is blocked. +@end deffn + +@deffn {Scheme Procedure} signal-condition-variable condvar +@deffnx {C Function} scm_signal_condition_variable (condvar) +Wake up one thread that is waiting for @var{condvar}. +@end deffn + +@deffn {Scheme Procedure} broadcast-condition-variable condvar +@deffnx {C Function} scm_broadcast_condition_variable (condvar) +Wake up all threads that are waiting for @var{condvar}. +@end deffn + +Guile also includes some higher-level abstractions for working with +mutexes. + +@deffn macro with-mutex mutex body1 body2 @dots{} +Lock @var{mutex}, evaluate the body @var{body1} @var{body2} @dots{}, +then unlock @var{mutex}. The return value is that returned by the last +body form. + +The lock, body and unlock form the branches of a @code{dynamic-wind} +(@pxref{Dynamic Wind}), so @var{mutex} is automatically unlocked if an +error or new continuation exits the body, and is re-locked if +the body is re-entered by a captured continuation. +@end deffn + +@deffn macro monitor body1 body2 @dots{} +Evaluate the body form @var{body1} @var{body2} @dots{} with a mutex +locked so only one thread can execute that code at any one time. The +return value is the return from the last body form. + +Each @code{monitor} form has its own private mutex and the locking and +evaluation is as per @code{with-mutex} above. A standard mutex +(@code{make-mutex}) is used, which means the body must not +recursively re-enter the @code{monitor} form. + +The term ``monitor'' comes from operating system theory, where it +means a particular bit of code managing access to some resource and +which only ever executes on behalf of one process at any one time. +@end deffn + + +@node Blocking +@subsection Blocking in Guile Mode + +Up to Guile version 1.8, a thread blocked in guile mode would prevent +the garbage collector from running. Thus threads had to explicitly +leave guile mode with @code{scm_without_guile ()} before making a +potentially blocking call such as a mutex lock, a @code{select ()} +system call, etc. The following functions could be used to temporarily +leave guile mode or to perform some common blocking operations in a +supported way. + +Starting from Guile 2.0, blocked threads no longer hinder garbage +collection. Thus, the functions below are not needed anymore. They can +still be used to inform the GC that a thread is about to block, giving +it a (small) optimization opportunity for ``stop the world'' garbage +collections, should they occur while the thread is blocked. + +@deftypefn {C Function} {void *} scm_without_guile (void *(*func) (void *), void *data) +Leave guile mode, call @var{func} on @var{data}, enter guile mode and +return the result of calling @var{func}. + +While a thread has left guile mode, it must not call any libguile +functions except @code{scm_with_guile} or @code{scm_without_guile} and +must not use any libguile macros. Also, local variables of type +@code{SCM} that are allocated while not in guile mode are not +protected from the garbage collector. + +When used from non-guile mode, calling @code{scm_without_guile} is +still allowed: it simply calls @var{func}. In that way, you can leave +guile mode without having to know whether the current thread is in +guile mode or not. +@end deftypefn + +@deftypefn {C Function} int scm_pthread_mutex_lock (pthread_mutex_t *mutex) +Like @code{pthread_mutex_lock}, but leaves guile mode while waiting for +the mutex. +@end deftypefn + +@deftypefn {C Function} int scm_pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +@deftypefnx {C Function} int scm_pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) +Like @code{pthread_cond_wait} and @code{pthread_cond_timedwait}, but +leaves guile mode while waiting for the condition variable. +@end deftypefn + +@deftypefn {C Function} int scm_std_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +Like @code{select} but leaves guile mode while waiting. Also, the +delivery of an async causes this function to be interrupted with error +code @code{EINTR}. +@end deftypefn + +@deftypefn {C Function} {unsigned int} scm_std_sleep ({unsigned int} seconds) +Like @code{sleep}, but leaves guile mode while sleeping. Also, the +delivery of an async causes this function to be interrupted. +@end deftypefn + +@deftypefn {C Function} {unsigned long} scm_std_usleep ({unsigned long} usecs) +Like @code{usleep}, but leaves guile mode while sleeping. Also, the +delivery of an async causes this function to be interrupted. +@end deftypefn + + +@node Futures +@subsection Futures +@cindex futures +@cindex fine-grain parallelism +@cindex parallelism + +The @code{(ice-9 futures)} module provides @dfn{futures}, a construct +for fine-grain parallelism. A future is a wrapper around an expression +whose computation may occur in parallel with the code of the calling +thread, and possibly in parallel with other futures. Like promises, +futures are essentially proxies that can be queried to obtain the value +of the enclosed expression: + +@lisp +(touch (future (+ 2 3))) +@result{} 5 +@end lisp + +However, unlike promises, the expression associated with a future may be +evaluated on another CPU core, should one be available. This supports +@dfn{fine-grain parallelism}, because even relatively small computations +can be embedded in futures. Consider this sequential code: + +@lisp +(define (find-prime lst1 lst2) + (or (find prime? lst1) + (find prime? lst2))) +@end lisp + +The two arms of @code{or} are potentially computation-intensive. They +are independent of one another, yet, they are evaluated sequentially +when the first one returns @code{#f}. Using futures, one could rewrite +it like this: + +@lisp +(define (find-prime lst1 lst2) + (let ((f (future (find prime? lst2)))) + (or (find prime? lst1) + (touch f)))) +@end lisp + +This preserves the semantics of @code{find-prime}. On a multi-core +machine, though, the computation of @code{(find prime? lst2)} may be +done in parallel with that of the other @code{find} call, which can +reduce the execution time of @code{find-prime}. + +Futures may be nested: a future can itself spawn and then @code{touch} +other futures, leading to a directed acyclic graph of futures. Using +this facility, a parallel @code{map} procedure can be defined along +these lines: + +@lisp +(use-modules (ice-9 futures) (ice-9 match)) + +(define (par-map proc lst) + (match lst + (() + '()) + ((head tail ...) + (let ((tail (future (par-map proc tail))) + (head (proc head))) + (cons head (touch tail)))))) +@end lisp + +Note that futures are intended for the evaluation of purely functional +expressions. Expressions that have side-effects or rely on I/O may +require additional care, such as explicit synchronization +(@pxref{Mutexes and Condition Variables}). + +Guile's futures are implemented on top of POSIX threads +(@pxref{Threads}). Internally, a fixed-size pool of threads is used to +evaluate futures, such that offloading the evaluation of an expression +to another thread doesn't incur thread creation costs. By default, the +pool contains one thread per available CPU core, minus one, to account +for the main thread. The number of available CPU cores is determined +using @code{current-processor-count} (@pxref{Processes}). + +When a thread touches a future that has not completed yet, it processes +any pending future while waiting for it to complete, or just waits if +there are no pending futures. When @code{touch} is called from within a +future, the execution of the calling future is suspended, allowing its +host thread to process other futures, and resumed when the touched +future has completed. This suspend/resume is achieved by capturing the +calling future's continuation, and later reinstating it (@pxref{Prompts, +delimited continuations}). + +@deffn {Scheme Syntax} future exp +Return a future for expression @var{exp}. This is equivalent to: + +@lisp +(make-future (lambda () exp)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} make-future thunk +Return a future for @var{thunk}, a zero-argument procedure. + +This procedure returns immediately. Execution of @var{thunk} may begin +in parallel with the calling thread's computations, if idle CPU cores +are available, or it may start when @code{touch} is invoked on the +returned future. + +If the execution of @var{thunk} throws an exception, that exception will +be re-thrown when @code{touch} is invoked on the returned future. +@end deffn + +@deffn {Scheme Procedure} future? obj +Return @code{#t} if @var{obj} is a future. +@end deffn + +@deffn {Scheme Procedure} touch f +Return the result of the expression embedded in future @var{f}. + +If the result was already computed in parallel, @code{touch} returns +instantaneously. Otherwise, it waits for the computation to complete, +if it already started, or initiates it. In the former case, the calling +thread may process other futures in the meantime. +@end deffn + + +@node Parallel Forms +@subsection Parallel forms +@cindex parallel forms + +The functions described in this section are available from + +@example +(use-modules (ice-9 threads)) +@end example + +They provide high-level parallel constructs. The following functions +are implemented in terms of futures (@pxref{Futures}). Thus they are +relatively cheap as they re-use existing threads, and portable, since +they automatically use one thread per available CPU core. + +@deffn syntax parallel expr @dots{} +Evaluate each @var{expr} expression in parallel, each in its own thread. +Return the results of @var{n} expressions as a set of @var{n} multiple +values (@pxref{Multiple Values}). +@end deffn + +@deffn syntax letpar ((var expr) @dots{}) body1 body2 @dots{} +Evaluate each @var{expr} in parallel, each in its own thread, then bind +the results to the corresponding @var{var} variables, and then evaluate +@var{body1} @var{body2} @enddots{} + +@code{letpar} is like @code{let} (@pxref{Local Bindings}), but all the +expressions for the bindings are evaluated in parallel. +@end deffn + +@deffn {Scheme Procedure} par-map proc lst1 lst2 @dots{} +@deffnx {Scheme Procedure} par-for-each proc lst1 lst2 @dots{} +Call @var{proc} on the elements of the given lists. @code{par-map} +returns a list comprising the return values from @var{proc}. +@code{par-for-each} returns an unspecified value, but waits for all +calls to complete. + +The @var{proc} calls are @code{(@var{proc} @var{elem1} @var{elem2} +@dots{})}, where each @var{elem} is from the corresponding @var{lst} . +Each @var{lst} must be the same length. The calls are potentially made +in parallel, depending on the number of CPU cores available. + +These functions are like @code{map} and @code{for-each} (@pxref{List +Mapping}), but make their @var{proc} calls in parallel. +@end deffn + +Unlike those above, the functions described below take a number of +threads as an argument. This makes them inherently non-portable since +the specified number of threads may differ from the number of available +CPU cores as returned by @code{current-processor-count} +(@pxref{Processes}). In addition, these functions create the specified +number of threads when they are called and terminate them upon +completion, which makes them quite expensive. + +Therefore, they should be avoided. + +@deffn {Scheme Procedure} n-par-map n proc lst1 lst2 @dots{} +@deffnx {Scheme Procedure} n-par-for-each n proc lst1 lst2 @dots{} +Call @var{proc} on the elements of the given lists, in the same way as +@code{par-map} and @code{par-for-each} above, but use no more than +@var{n} threads at any one time. The order in which calls are +initiated within that threads limit is unspecified. + +These functions are good for controlling resource consumption if +@var{proc} calls might be costly, or if there are many to be made. On +a dual-CPU system for instance @math{@var{n}=4} might be enough to +keep the CPUs utilized, and not consume too much memory. +@end deffn + +@deffn {Scheme Procedure} n-for-each-par-map n sproc pproc lst1 lst2 @dots{} +Apply @var{pproc} to the elements of the given lists, and apply +@var{sproc} to each result returned by @var{pproc}. The final return +value is unspecified, but all calls will have been completed before +returning. + +The calls made are @code{(@var{sproc} (@var{pproc} @var{elem1} @dots{} +@var{elemN}))}, where each @var{elem} is from the corresponding +@var{lst}. Each @var{lst} must have the same number of elements. + +The @var{pproc} calls are made in parallel, in separate threads. No more +than @var{n} threads are used at any one time. The order in which +@var{pproc} calls are initiated within that limit is unspecified. + +The @var{sproc} calls are made serially, in list element order, one at +a time. @var{pproc} calls on later elements may execute in parallel +with the @var{sproc} calls. Exactly which thread makes each +@var{sproc} call is unspecified. + +This function is designed for individual calculations that can be done +in parallel, but with results needing to be handled serially, for +instance to write them to a file. The @var{n} limit on threads +controls system resource usage when there are many calculations or +when they might be costly. + +It will be seen that @code{n-for-each-par-map} is like a combination +of @code{n-par-map} and @code{for-each}, + +@example +(for-each sproc (n-par-map n pproc lst1 ... lstN)) +@end example + +@noindent +But the actual implementation is more efficient since each @var{sproc} +call, in turn, can be initiated once the relevant @var{pproc} call has +completed, it doesn't need to wait for all to finish. +@end deffn + + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-scm.texi b/doc/ref/api-scm.texi new file mode 100644 index 000000000..54bb3eb3f --- /dev/null +++ b/doc/ref/api-scm.texi @@ -0,0 +1,45 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + + +@node The SCM Type +@section The SCM Type + +Guile represents all Scheme values with the single C type @code{SCM}. +For an introduction to this topic, @xref{Dynamic Types}. + +@deftp {C Type} SCM +@code{SCM} is the user level abstract C type that is used to represent +all of Guile's Scheme objects, no matter what the Scheme object type is. +No C operation except assignment is guaranteed to work with variables of +type @code{SCM}, so you should only use macros and functions to work +with @code{SCM} values. Values are converted between C data types and +the @code{SCM} type with utility functions and macros. +@end deftp +@cindex SCM data type + +@deftp {C Type} scm_t_bits +@code{scm_t_bits} is an unsigned integral data type that is guaranteed +to be large enough to hold all information that is required to +represent any Scheme object. While this data type is mostly used to +implement Guile's internals, the use of this type is also necessary to +write certain kinds of extensions to Guile. +@end deftp + +@deftp {C Type} scm_t_signed_bits +This is a signed integral type of the same size as @code{scm_t_bits}. +@end deftp + +@deftypefn {C Macro} scm_t_bits SCM_UNPACK (SCM @var{x}) +Transforms the @code{SCM} value @var{x} into its representation as an +integral type. Only after applying @code{SCM_UNPACK} it is possible to +access the bits and contents of the @code{SCM} value. +@end deftypefn + +@deftypefn {C Macro} SCM SCM_PACK (scm_t_bits @var{x}) +Takes a valid integral representation of a Scheme object and transforms +it into its representation as a @code{SCM} value. +@end deftypefn diff --git a/doc/ref/api-smobs.texi b/doc/ref/api-smobs.texi new file mode 100644 index 000000000..f09474eef --- /dev/null +++ b/doc/ref/api-smobs.texi @@ -0,0 +1,221 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2013, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Smobs +@section Smobs + +@cindex smob + +A @dfn{smob} is a ``small object''. Before foreign objects were +introduced in Guile 2.0.12 (@pxref{Foreign Objects}), smobs were the +preferred way to for C code to define new kinds of Scheme objects. With +the exception of the so-called ``applicable SMOBs'' discussed below, +smobs are now a legacy interface and are headed for eventual +deprecation. @xref{Deprecation}. New code should use the foreign +object interface. + +This section contains reference information related to defining and +working with smobs. For a tutorial-like introduction to smobs, see +``Defining New Types (Smobs)'' in previous versions of this manual. + +@deftypefun scm_t_bits scm_make_smob_type (const char *name, size_t size) +This function adds a new smob type, named @var{name}, with instance size +@var{size}, to the system. The return value is a tag that is used in +creating instances of the type. + +If @var{size} is 0, the default @emph{free} function will do nothing. + +If @var{size} is not 0, the default @emph{free} function will +deallocate the memory block pointed to by @code{SCM_SMOB_DATA} with +@code{scm_gc_free}. The @var{what} parameter in the call to +@code{scm_gc_free} will be @var{name}. + +Default values are provided for the @emph{mark}, @emph{free}, +@emph{print}, and @emph{equalp} functions. If you want to customize any +of these functions, the call to @code{scm_make_smob_type} should be +immediately followed by calls to one or several of +@code{scm_set_smob_mark}, @code{scm_set_smob_free}, +@code{scm_set_smob_print}, and/or @code{scm_set_smob_equalp}. +@end deftypefun + +@cindex finalizer +@cindex finalization + +@deftypefn {C Function} void scm_set_smob_free (scm_t_bits tc, size_t (*free) (SCM obj)) +This function sets the smob freeing procedure (sometimes referred to as +a @dfn{finalizer}) for the smob type specified by the tag +@var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}. + +The @var{free} procedure must deallocate all resources that are +directly associated with the smob instance @var{obj}. It must assume +that all @code{SCM} values that it references have already been freed +and are thus invalid. + +It must also not call any libguile function or macro except +@code{scm_gc_free}, @code{SCM_SMOB_FLAGS}, @code{SCM_SMOB_DATA}, +@code{SCM_SMOB_DATA_2}, and @code{SCM_SMOB_DATA_3}. + +The @var{free} procedure must return 0. + +Note that defining a freeing procedure is not necessary if the resources +associated with @var{obj} consists only of memory allocated with +@code{scm_gc_malloc} or @code{scm_gc_malloc_pointerless} because this +memory is automatically reclaimed by the garbage collector when it is no +longer needed (@pxref{Memory Blocks, @code{scm_gc_malloc}}). +@end deftypefn + +Smob free functions must be thread-safe. @xref{Foreign Object Memory +Management}, for a discussion on finalizers and concurrency. If you are +embedding Guile in an application that is not thread-safe, and you +define smob types that need finalization, you might want to disable +automatic finalization, and arrange to call +@code{scm_manually_run_finalizers ()} yourself. @xref{Foreign Objects}. + +@deftypefn {C Function} void scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM obj)) +This function sets the smob marking procedure for the smob type specified by +the tag @var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}. + +Defining a marking procedure is almost always the wrong thing to do. It +is much, much preferable to allocate smob data with the +@code{scm_gc_malloc} and @code{scm_gc_malloc_pointerless} functions, and +allow the GC to trace pointers automatically. + +Any mark procedures you see currently almost surely date from the time +of Guile 1.8, before the switch to the Boehm-Demers-Weiser collector. +Such smob implementations should be changed to just use +@code{scm_gc_malloc} and friends, and to lose their mark function. + +If you decide to keep the mark function, note that it may be called on +objects that are on the free list. Please read and digest the comments +from the BDW GC's @code{gc/gc_mark.h} header. + +The @var{mark} procedure must cause @code{scm_gc_mark} to be called +for every @code{SCM} value that is directly referenced by the smob +instance @var{obj}. One of these @code{SCM} values can be returned +from the procedure and Guile will call @code{scm_gc_mark} for it. +This can be used to avoid deep recursions for smob instances that form +a list. + +It must not call any libguile function or macro except +@code{scm_gc_mark}, @code{SCM_SMOB_FLAGS}, @code{SCM_SMOB_DATA}, +@code{SCM_SMOB_DATA_2}, and @code{SCM_SMOB_DATA_3}. +@end deftypefn + + +@deftypefn {C Function} void scm_set_smob_print (scm_t_bits tc, int (*print) (SCM obj, SCM port, scm_print_state* pstate)) +This function sets the smob printing procedure for the smob type +specified by the tag @var{tc}. @var{tc} is the tag returned by +@code{scm_make_smob_type}. + +The @var{print} procedure should output a textual representation of +the smob instance @var{obj} to @var{port}, using information in +@var{pstate}. + +The textual representation should be of the form @code{#<name ...>}. +This ensures that @code{read} will not interpret it as some other +Scheme value. + +It is often best to ignore @var{pstate} and just print to @var{port} +with @code{scm_display}, @code{scm_write}, @code{scm_simple_format}, +and @code{scm_puts}. +@end deftypefn + +@deftypefn {C Function} void scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp) (SCM obj1, SCM obj2)) +This function sets the smob equality-testing predicate for the smob +type specified by the tag @var{tc}. @var{tc} is the tag returned by +@code{scm_make_smob_type}. + +The @var{equalp} procedure should return @code{SCM_BOOL_T} when +@var{obj1} is @code{equal?} to @var{obj2}. Else it should return +@code{SCM_BOOL_F}. Both @var{obj1} and @var{obj2} are instances of the +smob type @var{tc}. +@end deftypefn + +@deftypefn {C Function} void scm_assert_smob_type (scm_t_bits tag, SCM val) +When @var{val} is a smob of the type indicated by @var{tag}, do nothing. +Else, signal an error. +@end deftypefn + +@deftypefn {C Macro} int SCM_SMOB_PREDICATE (scm_t_bits tag, SCM exp) +Return true if @var{exp} is a smob instance of the type indicated by +@var{tag}, or false otherwise. The expression @var{exp} can be +evaluated more than once, so it shouldn't contain any side effects. +@end deftypefn + +@deftypefn {C Function} SCM scm_new_smob (scm_t_bits tag, void *data) +@deftypefnx {C Function} SCM scm_new_double_smob (scm_t_bits tag, void *data, void *data2, void *data3) +Make a new smob of the type with tag @var{tag} and smob data @var{data}, +@var{data2}, and @var{data3}, as appropriate. + +The @var{tag} is what has been returned by @code{scm_make_smob_type}. +The initial values @var{data}, @var{data2}, and @var{data3} are of +type @code{scm_t_bits}; when you want to use them for @code{SCM} +values, these values need to be converted to a @code{scm_t_bits} first +by using @code{SCM_UNPACK}. + +The flags of the smob instance start out as zero. +@end deftypefn + +@deftypefn {C Macro} scm_t_bits SCM_SMOB_FLAGS (SCM obj) +Return the 16 extra bits of the smob @var{obj}. No meaning is +predefined for these bits, you can use them freely. +@end deftypefn + +@deftypefn {C Macro} scm_t_bits SCM_SET_SMOB_FLAGS (SCM obj, scm_t_bits flags) +Set the 16 extra bits of the smob @var{obj} to @var{flags}. No +meaning is predefined for these bits, you can use them freely. +@end deftypefn + +@deftypefn {C Macro} scm_t_bits SCM_SMOB_DATA (SCM obj) +@deftypefnx {C Macro} scm_t_bits SCM_SMOB_DATA_2 (SCM obj) +@deftypefnx {C Macro} scm_t_bits SCM_SMOB_DATA_3 (SCM obj) +Return the first (second, third) immediate word of the smob @var{obj} +as a @code{scm_t_bits} value. When the word contains a @code{SCM} +value, use @code{SCM_SMOB_OBJECT} (etc.) instead. +@end deftypefn + +@deftypefn {C Macro} void SCM_SET_SMOB_DATA (SCM obj, scm_t_bits val) +@deftypefnx {C Macro} void SCM_SET_SMOB_DATA_2 (SCM obj, scm_t_bits val) +@deftypefnx {C Macro} void SCM_SET_SMOB_DATA_3 (SCM obj, scm_t_bits val) +Set the first (second, third) immediate word of the smob @var{obj} to +@var{val}. When the word should be set to a @code{SCM} value, use +@code{SCM_SMOB_SET_OBJECT} (etc.) instead. +@end deftypefn + +@deftypefn {C Macro} SCM SCM_SMOB_OBJECT (SCM obj) +@deftypefnx {C Macro} SCM SCM_SMOB_OBJECT_2 (SCM obj) +@deftypefnx {C Macro} SCM SCM_SMOB_OBJECT_3 (SCM obj) +Return the first (second, third) immediate word of the smob @var{obj} +as a @code{SCM} value. When the word contains a @code{scm_t_bits} +value, use @code{SCM_SMOB_DATA} (etc.) instead. +@end deftypefn + +@deftypefn {C Macro} void SCM_SET_SMOB_OBJECT (SCM obj, SCM val) +@deftypefnx {C Macro} void SCM_SET_SMOB_OBJECT_2 (SCM obj, SCM val) +@deftypefnx {C Macro} void SCM_SET_SMOB_OBJECT_3 (SCM obj, SCM val) +Set the first (second, third) immediate word of the smob @var{obj} to +@var{val}. When the word should be set to a @code{scm_t_bits} value, use +@code{SCM_SMOB_SET_DATA} (etc.) instead. +@end deftypefn + +@deftypefn {C Macro} {SCM *} SCM_SMOB_OBJECT_LOC (SCM obj) +@deftypefnx {C Macro} {SCM *} SCM_SMOB_OBJECT_2_LOC (SCM obj) +@deftypefnx {C Macro} {SCM *} SCM_SMOB_OBJECT_3_LOC (SCM obj) +Return a pointer to the first (second, third) immediate word of the +smob @var{obj}. Note that this is a pointer to @code{SCM}. If you +need to work with @code{scm_t_bits} values, use @code{SCM_PACK} and +@code{SCM_UNPACK}, as appropriate. +@end deftypefn + +@deftypefun SCM scm_markcdr (SCM @var{x}) +Mark the references in the smob @var{x}, assuming that @var{x}'s first +data word contains an ordinary Scheme object, and @var{x} refers to no +other objects. This function simply returns @var{x}'s first data word. +@end deftypefun + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api-snarf.texi b/doc/ref/api-snarf.texi new file mode 100644 index 000000000..fbefda670 --- /dev/null +++ b/doc/ref/api-snarf.texi @@ -0,0 +1,143 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + + +@node Snarfing Macros +@section Snarfing Macros +@cindex guile-snarf recognized macros +@cindex guile-snarf deprecated macros + +The following macros do two different things: when compiled normally, +they expand in one way; when processed during snarfing, they cause the +@code{guile-snarf} program to pick up some initialization code, +@xref{Function Snarfing}. + +The descriptions below use the term `normally' to refer to the case +when the code is compiled normally, and `while snarfing' when the code +is processed by @code{guile-snarf}. + +@deffn {C Macro} SCM_SNARF_INIT (code) + +Normally, @code{SCM_SNARF_INIT} expands to nothing; while snarfing, it +causes @var{code} to be included in the initialization action file, +followed by a semicolon. + +This is the fundamental macro for snarfing initialization actions. +The more specialized macros below use it internally. +@end deffn + + +@deffn {C Macro} SCM_DEFINE (c_name, scheme_name, req, opt, var, arglist, docstring) + +Normally, this macro expands into + +@smallexample +static const char s_@var{c_name}[] = @var{scheme_name}; +SCM +@var{c_name} @var{arglist} +@end smallexample + +While snarfing, it causes + +@smallexample +scm_c_define_gsubr (s_@var{c_name}, @var{req}, @var{opt}, @var{var}, + @var{c_name}); +@end smallexample + +to be added to the initialization actions. Thus, you can use it to +declare a C function named @var{c_name} that will be made available to +Scheme with the name @var{scheme_name}. + +Note that the @var{arglist} argument must have parentheses around it. +@end deffn + +@deffn {C Macro} SCM_SYMBOL (c_name, scheme_name) +@deffnx {C Macro} SCM_GLOBAL_SYMBOL (c_name, scheme_name) +Normally, these macros expand into + +@smallexample +static SCM @var{c_name} +@end smallexample + +or + +@smallexample +SCM @var{c_name} +@end smallexample + +respectively. While snarfing, they both expand into the +initialization code + +@smallexample +@var{c_name} = scm_permanent_object (scm_from_locale_symbol (@var{scheme_name})); +@end smallexample + +Thus, you can use them declare a static or global variable of type +@code{SCM} that will be initialized to the symbol named +@var{scheme_name}. +@end deffn + +@deffn {C Macro} SCM_KEYWORD (c_name, scheme_name) +@deffnx {C Macro} SCM_GLOBAL_KEYWORD (c_name, scheme_name) +Normally, these macros expand into + +@smallexample +static SCM @var{c_name} +@end smallexample + +or + +@smallexample +SCM @var{c_name} +@end smallexample + +respectively. While snarfing, they both expand into the +initialization code + +@smallexample +@var{c_name} = scm_permanent_object (scm_c_make_keyword (@var{scheme_name})); +@end smallexample + +Thus, you can use them declare a static or global variable of type +@code{SCM} that will be initialized to the keyword named +@var{scheme_name}. +@end deffn + +@deffn {C Macro} SCM_VARIABLE (c_name, scheme_name) +@deffnx {C Macro} SCM_GLOBAL_VARIABLE (c_name, scheme_name) +These macros are equivalent to @code{SCM_VARIABLE_INIT} and +@code{SCM_GLOBAL_VARIABLE_INIT}, respectively, with a @var{value} of +@code{SCM_BOOL_F}. +@end deffn + +@deffn {C Macro} SCM_VARIABLE_INIT (c_name, scheme_name, value) +@deffnx {C Macro} SCM_GLOBAL_VARIABLE_INIT (c_name, scheme_name, value) + +Normally, these macros expand into + +@smallexample +static SCM @var{c_name} +@end smallexample + +or + +@smallexample +SCM @var{c_name} +@end smallexample + +respectively. While snarfing, they both expand into the +initialization code + +@smallexample +@var{c_name} = scm_permanent_object (scm_c_define (@var{scheme_name}, @var{value})); +@end smallexample + +Thus, you can use them declare a static or global C variable of type +@code{SCM} that will be initialized to the object representing the +Scheme variable named @var{scheme_name} in the current module. The +variable will be defined when it doesn't already exist. It is always +set to @var{value}. +@end deffn diff --git a/doc/ref/api-undocumented.texi b/doc/ref/api-undocumented.texi new file mode 100644 index 000000000..4e478f4c4 --- /dev/null +++ b/doc/ref/api-undocumented.texi @@ -0,0 +1,675 @@ +This file gathers entries that have been automatically generated from +docstrings in libguile. They are not included in the manual, however, +for various reasons, mostly because they have been deprecated. They +are here in this file to give docstring.el a chance to update them +automatically. + +- GOOPS is documented in its own manual. + + + +@deffn {Scheme Procedure} substring-move-right! +implemented by the C function "scm_substring_move_x" +@end deffn + +@deffn {Scheme Procedure} substring-move-left! +implemented by the C function "scm_substring_move_x" +@end deffn + +@deffn {Scheme Procedure} gentemp [prefix [obarray]] +@deffnx {C Function} scm_gentemp (prefix, obarray) +Create a new symbol with a name unique in an obarray. +The name is constructed from an optional string @var{prefix} +and a counter value. The default prefix is @code{t}. The +@var{obarray} is specified as a second optional argument. +Default is the system obarray where all normal symbols are +interned. The counter is increased by 1 at each +call. There is no provision for resetting the counter. +@end deffn + +@deffn {Scheme Procedure} symbol-set! o s v +@deffnx {C Function} scm_symbol_set_x (o, s, v) +Find the symbol in @var{obarray} whose name is @var{string}, and rebind +it to @var{value}. An error is signalled if @var{string} is not present +in @var{obarray}. +@end deffn + +@deffn {Scheme Procedure} symbol-bound? o s +@deffnx {C Function} scm_symbol_bound_p (o, s) +Return @code{#t} if @var{obarray} contains a symbol with name +@var{string} bound to a defined value. This differs from +@var{symbol-interned?} in that the mere mention of a symbol +usually causes it to be interned; @code{symbol-bound?} +determines whether a symbol has been given any meaningful +value. +@end deffn + +@deffn {Scheme Procedure} symbol-binding o s +@deffnx {C Function} scm_symbol_binding (o, s) +Look up in @var{obarray} the symbol whose name is @var{string}, and +return the value to which it is bound. If @var{obarray} is @code{#f}, +use the global symbol table. If @var{string} is not interned in +@var{obarray}, an error is signalled. +@end deffn + +@deffn {Scheme Procedure} unintern-symbol o s +@deffnx {C Function} scm_unintern_symbol (o, s) +Remove the symbol with name @var{string} from @var{obarray}. This +function returns @code{#t} if the symbol was present and @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} intern-symbol o s +@deffnx {C Function} scm_intern_symbol (o, s) +Add a new symbol to @var{obarray} with name @var{string}, bound to an +unspecified initial value. The symbol table is not modified if a symbol +with this name is already present. +@end deffn + +@deffn {Scheme Procedure} string->obarray-symbol o s [softp] +@deffnx {C Function} scm_string_to_obarray_symbol (o, s, softp) +Intern a new symbol in @var{obarray}, a symbol table, with name +@var{string}. + +If @var{obarray} is @code{#f}, use the default system symbol table. If +@var{obarray} is @code{#t}, the symbol should not be interned in any +symbol table; merely return the pair (@var{symbol} +. @var{#<undefined>}). + +The @var{soft?} argument determines whether new symbol table entries +should be created when the specified symbol is not already present in +@var{obarray}. If @var{soft?} is specified and is a true value, then +new entries should not be added for symbols not already present in the +table; instead, simply return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} read-and-eval! [port] +@deffnx {C Function} scm_read_and_eval_x (port) +Read a form from @var{port} (standard input by default), and evaluate it +(memoizing it in the process) in the top-level environment. If no data +is left to be read from @var{port}, an @code{end-of-file} error is +signalled. +@end deffn + +@deffn {Scheme Procedure} sloppy-member x lst +@deffnx {C Function} scm_sloppy_member (x, lst) +This procedure behaves like @code{member}, but does no type or error checking. +Its use is recommended only in writing Guile internals, +not for high-level Scheme programs. +@end deffn + +@deffn {Scheme Procedure} sloppy-memv x lst +@deffnx {C Function} scm_sloppy_memv (x, lst) +This procedure behaves like @code{memv}, but does no type or error checking. +Its use is recommended only in writing Guile internals, +not for high-level Scheme programs. +@end deffn + +@deffn {Scheme Procedure} sloppy-memq x lst +@deffnx {C Function} scm_sloppy_memq (x, lst) +This procedure behaves like @code{memq}, but does no type or error checking. +Its use is recommended only in writing Guile internals, +not for high-level Scheme programs. +@end deffn + +@deffn {Scheme Procedure} builtin-variable name +@deffnx {C Function} scm_builtin_variable (name) +Do not use this function. +@end deffn + +@deffn {Scheme Procedure} variable-set-name-hint! var hint +@deffnx {C Function} scm_variable_set_name_hint (var, hint) +Do not use this function. +@end deffn + +@deffn {Scheme Procedure} close-all-ports-except . ports +@deffnx {C Function} scm_close_all_ports_except (ports) +[DEPRECATED] Close all open file ports used by the interpreter +except for those supplied as arguments. This procedure +was intended to be used before an exec call to close file descriptors +which are not needed in the new process. However it has the +undesirable side effect of flushing buffers, so it's deprecated. +Use port-for-each instead. +@end deffn + +@deffn {Scheme Procedure} c-clear-registered-modules +@deffnx {C Function} scm_clear_registered_modules () +Destroy the list of modules registered with the current Guile process. +The return value is unspecified. @strong{Warning:} this function does +not actually unlink or deallocate these modules, but only destroys the +records of which modules have been loaded. It should therefore be used +only by module bookkeeping operations. +@end deffn + +@deffn {Scheme Procedure} c-registered-modules +@deffnx {C Function} scm_registered_modules () +Return a list of the object code modules that have been imported into +the current Guile process. Each element of the list is a pair whose +car is the name of the module, and whose cdr is the function handle +for that module's initializer function. The name is the string that +has been passed to scm_register_module_xxx. +@end deffn + +@deffn {Scheme Procedure} module-import-interface module sym +@deffnx {C Function} scm_module_import_interface (module, sym) +Return the module or interface from which @var{sym} is imported in @var{module}. If @var{sym} is not imported (i.e., it is not defined in @var{module} or it is a module-local binding instead of an imported one), then @code{#f} is returned. +@end deffn + + +@deffn {Scheme Procedure} self-evaluating? obj +@deffnx {C Function} scm_self_evaluating_p (obj) +Return #t for objects which Guile considers self-evaluating +@end deffn + +@deffn {Scheme Procedure} unmemoize-expr m +@deffnx {C Function} scm_i_unmemoize_expr (m) +Unmemoize the memoized expression @var{m}, +@end deffn + +@deffn {Scheme Procedure} weak-key-alist-vector? obj +@deffnx {Scheme Procedure} weak-value-alist-vector? obj +@deffnx {Scheme Procedure} doubly-weak-alist-vector? obj +@deffnx {C Function} scm_weak_key_alist_vector_p (obj) +Return @code{#t} if @var{obj} is the specified weak hash +table. Note that a doubly weak hash table is neither a weak key +nor a weak value hash table. +@end deffn + +@deffn {Scheme Procedure} make-weak-key-alist-vector [size] +@deffnx {Scheme Procedure} make-weak-value-alist-vector size +@deffnx {Scheme Procedure} make-doubly-weak-alist-vector size +@deffnx {C Function} scm_make_weak_key_alist_vector (size) +Return a weak hash table with @var{size} buckets. As with any +hash table, choosing a good size for the table requires some +caution. + +You can modify weak hash tables in exactly the same way you +would modify regular hash tables. (@pxref{Hash Tables}) +@end deffn + +@deffn {Scheme Procedure} include-deprecated-features +Return @code{#t} if deprecated features should be included in public +interfaces, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} issue-deprecation-warning . msgs +Output @var{msgs} to @code{(current-error-port)} when this +is the first call to @code{issue-deprecation-warning} with +this specific @var{msg}. Do nothing otherwise. +The argument @var{msgs} should be a list of strings; +they are printed in turn, each one followed by a newline. +@end deffn + +@deffn {Scheme Procedure} valid-object-procedure? proc +@deffnx {C Function} scm_valid_object_procedure_p (proc) +Return @code{#t} ff @var{proc} is a procedure that can be used with @code{set-object-procedure}. It is always valid to use a closure constructed by @code{lambda}. +@end deffn + +@deffn {Scheme Procedure} %get-pre-modules-obarray +@deffnx {C Function} scm_get_pre_modules_obarray () +Return the obarray that is used for all new bindings before the module system is booted. The first call to @code{set-current-module} will boot the module system. +@end deffn + +@deffn {Scheme Procedure} standard-interface-eval-closure module +@deffnx {C Function} scm_standard_interface_eval_closure (module) +Return a interface eval closure for the module @var{module}. Such a closure does not allow new bindings to be added. +@end deffn + +@deffn {Scheme Procedure} env-module env +@deffnx {C Function} scm_env_module (env) +Return the module of @var{ENV}, a lexical environment. +@end deffn + +@deffn {Scheme Procedure} single-active-thread? +implemented by the C function "scm_single_thread_p" +@end deffn + +@deffn {Scheme Procedure} set-debug-cell-accesses! flag +@deffnx {C Function} scm_set_debug_cell_accesses_x (flag) +This function is used to turn on checking for a debug version of GUILE. This version does not support this functionality + +@end deffn + +@deffn {Scheme Procedure} standard-eval-closure module +@deffnx {C Function} scm_standard_eval_closure (module) +Return an eval closure for the module @var{module}. +@end deffn + +@deffn {Scheme Procedure} mask-signals +@deffnx {C Function} scm_mask_signals () +Mask signals. The returned value is not specified. +@end deffn + +@deffn {Scheme Procedure} unmask-signals +@deffnx {C Function} scm_unmask_signals () +Unmask signals. The returned value is not specified. +@end deffn + +@deffn {Scheme Procedure} noop . args +@deffnx {C Function} scm_noop (args) +Do nothing. When called without arguments, return @code{#f}, +otherwise return the first argument. +@end deffn + +@deffn {Scheme Procedure} system-async thunk +@deffnx {C Function} scm_system_async (thunk) +This function is deprecated. You can use @var{thunk} directly +instead of explicitly creating an async object. + +@end deffn + +@deffn {Scheme Procedure} object-address obj +@deffnx {C Function} scm_object_address (obj) +Return an integer that for the lifetime of @var{obj} is uniquely +returned by this function for @var{obj} +@end deffn + +@deffn {Scheme Procedure} %compute-slots class +@deffnx {C Function} scm_sys_compute_slots (class) +Return a list consisting of the names of all slots belonging to +class @var{class}, i.e.@: the slots of @var{class} and of all of +its superclasses. +@end deffn + +@deffn {Scheme Procedure} get-keyword key l default_value +@deffnx {C Function} scm_get_keyword (key, l, default_value) +Determine an associated value for the keyword @var{key} from +the list @var{l}. The list @var{l} has to consist of an even +number of elements, where, starting with the first, every +second element is a keyword, followed by its associated value. +If @var{l} does not hold a value for @var{key}, the value +@var{default_value} is returned. +@end deffn + +@deffn {Scheme Procedure} slot-ref-using-class class obj slot_name +@deffnx {C Function} scm_slot_ref_using_class (class, obj, slot_name) + +@end deffn + +@deffn {Scheme Procedure} slot-set-using-class! class obj slot_name value +@deffnx {C Function} scm_slot_set_using_class_x (class, obj, slot_name, value) + +@end deffn + +@deffn {Scheme Procedure} class-of x +@deffnx {C Function} scm_class_of (x) +Return the class of @var{x}. +@end deffn + +@deffn {Scheme Procedure} %goops-loaded +@deffnx {C Function} scm_sys_goops_loaded () +Announce that GOOPS is loaded and perform initialization +on the C level which depends on the loaded GOOPS modules. +@end deffn + +@deffn {Scheme Procedure} %method-more-specific? m1 m2 targs +@deffnx {C Function} scm_sys_method_more_specific_p (m1, m2, targs) +Return true if method @var{m1} is more specific than @var{m2} given the argument types (classes) listed in @var{targs}. +@end deffn + +@deffn {Scheme Procedure} find-method . l +@deffnx {C Function} scm_find_method (l) + +@end deffn + +@deffn {Scheme Procedure} primitive-generic-generic subr +@deffnx {C Function} scm_primitive_generic_generic (subr) + +@end deffn + +@deffn {Scheme Procedure} enable-primitive-generic! . subrs +@deffnx {C Function} scm_enable_primitive_generic_x (subrs) + +@end deffn + +@deffn {Scheme Procedure} generic-capability? proc +@deffnx {C Function} scm_generic_capability_p (proc) + +@end deffn + +@deffn {Scheme Procedure} %invalidate-method-cache! gf +@deffnx {C Function} scm_sys_invalidate_method_cache_x (gf) + +@end deffn + +@deffn {Scheme Procedure} %invalidate-class class +@deffnx {C Function} scm_sys_invalidate_class (class) + +@end deffn + +@deffn {Scheme Procedure} %modify-class old new +@deffnx {C Function} scm_sys_modify_class (old, new) + +@end deffn + +@deffn {Scheme Procedure} %modify-instance old new +@deffnx {C Function} scm_sys_modify_instance (old, new) + +@end deffn + +@deffn {Scheme Procedure} %set-object-setter! obj setter +@deffnx {C Function} scm_sys_set_object_setter_x (obj, setter) + +@end deffn + +@deffn {Scheme Procedure} %allocate-instance class initargs +@deffnx {C Function} scm_sys_allocate_instance (class, initargs) +Create a new instance of class @var{class} and initialize it +from the arguments @var{initargs}. +@end deffn + +@deffn {Scheme Procedure} slot-exists? obj slot_name +@deffnx {C Function} scm_slot_exists_p (obj, slot_name) +Return @code{#t} if @var{obj} has a slot named @var{slot_name}. +@end deffn + +@deffn {Scheme Procedure} slot-bound? obj slot_name +@deffnx {C Function} scm_slot_bound_p (obj, slot_name) +Return @code{#t} if the slot named @var{slot_name} of @var{obj} +is bound. +@end deffn + +@deffn {Scheme Procedure} slot-set! obj slot_name value +@deffnx {C Function} scm_slot_set_x (obj, slot_name, value) +Set the slot named @var{slot_name} of @var{obj} to @var{value}. +@end deffn + +@deffn {Scheme Procedure} slot-exists-using-class? class obj slot_name +@deffnx {C Function} scm_slot_exists_using_class_p (class, obj, slot_name) + +@end deffn + +@deffn {Scheme Procedure} slot-bound-using-class? class obj slot_name +@deffnx {C Function} scm_slot_bound_using_class_p (class, obj, slot_name) + +@end deffn + +@deffn {Scheme Procedure} %fast-slot-set! obj index value +@deffnx {C Function} scm_sys_fast_slot_set_x (obj, index, value) +Set the slot with index @var{index} in @var{obj} to +@var{value}. +@end deffn + +@deffn {Scheme Procedure} %fast-slot-ref obj index +@deffnx {C Function} scm_sys_fast_slot_ref (obj, index) +Return the slot value with index @var{index} from @var{obj}. +@end deffn + +@deffn {Scheme Procedure} @@assert-bound-ref obj index +@deffnx {C Function} scm_at_assert_bound_ref (obj, index) +Like @code{assert-bound}, but use @var{index} for accessing +the value from @var{obj}. +@end deffn + +@deffn {Scheme Procedure} assert-bound value obj +@deffnx {C Function} scm_assert_bound (value, obj) +Return @var{value} if it is bound, and invoke the +@var{slot-unbound} method of @var{obj} if it is not. +@end deffn + +@deffn {Scheme Procedure} unbound? obj +@deffnx {C Function} scm_unbound_p (obj) +Return @code{#t} if @var{obj} is unbound. +@end deffn + +@deffn {Scheme Procedure} make-unbound +@deffnx {C Function} scm_make_unbound () +Return the unbound value. +@end deffn + +@deffn {Scheme Procedure} accessor-method-slot-definition obj +@deffnx {C Function} scm_accessor_method_slot_definition (obj) +Return the slot definition of the accessor @var{obj}. +@end deffn + +@deffn {Scheme Procedure} method-procedure obj +@deffnx {C Function} scm_method_procedure (obj) +Return the procedure of the method @var{obj}. +@end deffn + +@deffn {Scheme Procedure} method-specializers obj +@deffnx {C Function} scm_method_specializers (obj) +Return specializers of the method @var{obj}. +@end deffn + +@deffn {Scheme Procedure} method-generic-function obj +@deffnx {C Function} scm_method_generic_function (obj) +Return the generic function for the method @var{obj}. +@end deffn + +@deffn {Scheme Procedure} generic-function-methods obj +@deffnx {C Function} scm_generic_function_methods (obj) +Return the methods of the generic function @var{obj}. +@end deffn + +@deffn {Scheme Procedure} generic-function-name obj +@deffnx {C Function} scm_generic_function_name (obj) +Return the name of the generic function @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-environment obj +@deffnx {C Function} scm_class_environment (obj) +Return the environment of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-slots obj +@deffnx {C Function} scm_class_slots (obj) +Return the slot list of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-precedence-list obj +@deffnx {C Function} scm_class_precedence_list (obj) +Return the class precedence list of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-direct-methods obj +@deffnx {C Function} scm_class_direct_methods (obj) +Return the direct methods of the class @var{obj} +@end deffn + +@deffn {Scheme Procedure} class-direct-subclasses obj +@deffnx {C Function} scm_class_direct_subclasses (obj) +Return the direct subclasses of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-direct-slots obj +@deffnx {C Function} scm_class_direct_slots (obj) +Return the direct slots of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-direct-supers obj +@deffnx {C Function} scm_class_direct_supers (obj) +Return the direct superclasses of the class @var{obj}. +@end deffn + +@deffn {Scheme Procedure} class-name obj +@deffnx {C Function} scm_class_name (obj) +Return the class name of @var{obj}. +@end deffn + +@deffn {Scheme Procedure} instance? obj +@deffnx {C Function} scm_instance_p (obj) +Return @code{#t} if @var{obj} is an instance. +@end deffn + +@deffn {Scheme Procedure} %inherit-magic! class dsupers +@deffnx {C Function} scm_sys_inherit_magic_x (class, dsupers) + +@end deffn + +@deffn {Scheme Procedure} %prep-layout! class +@deffnx {C Function} scm_sys_prep_layout_x (class) + +@end deffn + +@deffn {Scheme Procedure} %initialize-object obj initargs +@deffnx {C Function} scm_sys_initialize_object (obj, initargs) +Initialize the object @var{obj} with the given arguments +@var{initargs}. +@end deffn + +@deffn {Scheme Procedure} make . args +@deffnx {C Function} scm_make (args) +Make a new object. @var{args} must contain the class and +all necessary initialization information. +@end deffn + +@deffn {Scheme Procedure} slot-ref obj slot_name +@deffnx {C Function} scm_slot_ref (obj, slot_name) +Return the value from @var{obj}'s slot with the name +@var{slot_name}. +@end deffn + +@deffn {Scheme Procedure} %tag-body body +@deffnx {C Function} scm_sys_tag_body (body) +Internal GOOPS magic---don't use this function! +@end deffn + +@deffn {Scheme Procedure} make-keyword-from-dash-symbol symbol +@deffnx {C Function} scm_make_keyword_from_dash_symbol (symbol) +Make a keyword object from a @var{symbol} that starts with a dash. +@end deffn + +@deffn {Scheme Procedure} keyword-dash-symbol keyword +@deffnx {C Function} scm_keyword_dash_symbol (keyword) +Return the dash symbol for @var{keyword}. +This is the inverse of @code{make-keyword-from-dash-symbol}. +@end deffn + +@deffn {Scheme Procedure} dimensions->uniform-array dims prot [fill] +@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill] +@deffnx {C Function} scm_dimensions_to_uniform_array (dims, prot, fill) +Create and return a uniform array or vector of type +corresponding to @var{prototype} with dimensions @var{dims} or +length @var{length}. If @var{fill} is supplied, it's used to +fill the array, otherwise @var{prototype} is used. +@end deffn + +@deffn {Scheme Procedure} list->uniform-array ndim prot lst +@deffnx {C Function} scm_list_to_uniform_array (ndim, prot, lst) +Return a uniform array of the type indicated by prototype +@var{prot} with elements the same as those of @var{lst}. +Elements must be of the appropriate type, no coercions are +done. + +The argument @var{ndim} determines the number of dimensions +of the array. It is either an exact integer, giving the +number directly, or a list of exact integers, whose length +specifies the number of dimensions and each element is the +lower index bound of its dimension. +@end deffn + +@deffn {Scheme Procedure} array-prototype ra +@deffnx {C Function} scm_array_prototype (ra) +Return an object that would produce an array of the same type +as @var{array}, if used as the @var{prototype} for +@code{make-uniform-array}. +@end deffn + +@deffn {Scheme Procedure} call-with-dynamic-root thunk handler +@deffnx {C Function} scm_call_with_dynamic_root (thunk, handler) +Call @var{thunk} with a new dynamic state and within a continuation barrier. The @var{handler} catches all otherwise uncaught throws and executes within the same dynamic context as @var{thunk}. +@end deffn + +@deffn {Scheme Procedure} dynamic-root +@deffnx {C Function} scm_dynamic_root () +Return an object representing the current dynamic root. + +These objects are only useful for comparison using @code{eq?}. + +@end deffn + +@deffn {Scheme Procedure} uniform-vector? obj +@deffnx {C Function} scm_uniform_vector_p (obj) +Return @code{#t} if @var{obj} is a uniform vector. +@end deffn + +@deffn {Scheme Procedure} uniform-vector-ref v idx +@deffnx {C Function} scm_uniform_vector_ref (v, idx) +Return the element at index @var{idx} of the +homogeneous numeric vector @var{v}. +@end deffn + +@deffn {Scheme Procedure} uniform-vector-set! v idx val +@deffnx {C Function} scm_uniform_vector_set_x (v, idx, val) +Set the element at index @var{idx} of the +homogeneous numeric vector @var{v} to @var{val}. +@end deffn + +@deffn {Scheme Procedure} uniform-vector->list uvec +@deffnx {C Function} scm_uniform_vector_to_list (uvec) +Convert the uniform numeric vector @var{uvec} to a list. +@end deffn + +@deffn {Scheme Procedure} uniform-vector-length v +@deffnx {C Function} scm_uniform_vector_length (v) +Return the number of elements in the uniform vector @var{v}. +@end deffn + +@deffn {Scheme Procedure} make-u8vector len [fill] +@deffnx {C Function} scm_make_u8vector (len, fill) +Return a newly allocated uniform numeric vector which can +hold @var{len} elements. If @var{fill} is given, it is used to +initialize the elements, otherwise the contents of the vector +is unspecified. +@end deffn + +@deffn {Scheme Procedure} u8vector . l +@deffnx {C Function} scm_u8vector (l) +Return a newly allocated uniform numeric vector containing +all argument values. +@end deffn + +@deffn {Scheme Procedure} list->u8vector l +@deffnx {C Function} scm_list_to_u8vector (l) +Convert the list @var{l} to a numeric uniform vector. +@end deffn + +@deffn {Scheme Procedure} any->u8vector obj +@deffnx {C Function} scm_any_to_u8vector (obj) +Convert @var{obj}, which can be a list, vector, or +uniform vector, to a numeric uniform vector of +type u8. +@end deffn + +@deffn {Scheme Procedure} string-any-c-code char_pred s [start [end]] +@deffnx {C Function} scm_string_any (char_pred, s, start, end) +Check if the predicate @var{pred} is true for any character in +the string @var{s}. + +Calls to @var{pred} are made from left to right across @var{s}. +When it returns true (ie.@: non-@code{#f}), that return value +is the return from @code{string-any}. + +The SRFI-13 specification requires that the call to @var{pred} +on the last character of @var{s} (assuming that point is +reached) be a tail call, but currently in Guile this is not the +case. +@end deffn + +@deffn {Scheme Procedure} string-every-c-code char_pred s [start [end]] +@deffnx {C Function} scm_string_every (char_pred, s, start, end) +Check if the predicate @var{pred} is true for every character +in the string @var{s}. + +Calls to @var{pred} are made from left to right across @var{s}. +If the predicate is true for every character then the return +value from the last @var{pred} call is the return from +@code{string-every}. + +If there are no characters in @var{s} (ie.@: @var{start} equals +@var{end}) then the return is @code{#t}. + +The SRFI-13 specification requires that the call to @var{pred} +on the last character of @var{s} (assuming that point is +reached) be a tail call, but currently in Guile this is not the +case. +@end deffn + +@deffn {Scheme Procedure} inf? x +@deffnx {C Function} scm_inf_p (x) +Return @code{#t} if @var{x} is either @samp{+inf.0} +or @samp{-inf.0}, @code{#f} otherwise. +@end deffn + + diff --git a/doc/ref/api-utility.texi b/doc/ref/api-utility.texi new file mode 100644 index 000000000..d82d31a48 --- /dev/null +++ b/doc/ref/api-utility.texi @@ -0,0 +1,782 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011, 2012, 2013, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Utility Functions +@section General Utility Functions + +@c FIXME::martin: Review me! + +This chapter contains information about procedures which are not cleanly +tied to a specific data type. Because of their wide range of +applications, they are collected in a @dfn{utility} chapter. + +@menu +* Equality:: When are two values `the same'? +* Object Properties:: A modern interface to object properties. +* Sorting:: Sort utility procedures. +* Copying:: Copying deep structures. +* General Conversion:: Converting objects to strings. +* Hooks:: User-customizable event lists. +@end menu + + +@node Equality +@subsection Equality +@cindex sameness +@cindex equality + +There are three kinds of core equality predicates in Scheme, described +below. The same kinds of comparisons arise in other functions, like +@code{memq} and friends (@pxref{List Searching}). + +For all three tests, objects of different types are never equal. So +for instance a list and a vector are not @code{equal?}, even if their +contents are the same. Exact and inexact numbers are considered +different types too, and are hence not equal even if their values are +the same. + +@code{eq?} tests just for the same object (essentially a pointer +comparison). This is fast, and can be used when searching for a +particular object, or when working with symbols or keywords (which are +always unique objects). + +@code{eqv?} extends @code{eq?} to look at the value of numbers and +characters. It can for instance be used somewhat like @code{=} +(@pxref{Comparison}) but without an error if one operand isn't a +number. + +@code{equal?} goes further, it looks (recursively) into the contents +of lists, vectors, etc. This is good for instance on lists that have +been read or calculated in various places and are the same, just not +made up of the same pairs. Such lists look the same (when printed), +and @code{equal?} will consider them the same. + +@sp 1 +@deffn {Scheme Procedure} eq? x y +@deffnx {C Function} scm_eq_p (x, y) +@rnindex eq? +Return @code{#t} if @var{x} and @var{y} are the same object, except +for numbers and characters. For example, + +@example +(define x (vector 1 2 3)) +(define y (vector 1 2 3)) + +(eq? x x) @result{} #t +(eq? x y) @result{} #f +@end example + +Numbers and characters are not equal to any other object, but the +problem is they're not necessarily @code{eq?} to themselves either. +This is even so when the number comes directly from a variable, + +@example +(let ((n (+ 2 3))) + (eq? n n)) @result{} *unspecified* +@end example + +Generally @code{eqv?} below should be used when comparing numbers or +characters. @code{=} (@pxref{Comparison}) or @code{char=?} +(@pxref{Characters}) can be used too. + +It's worth noting that end-of-list @code{()}, @code{#t}, @code{#f}, a +symbol of a given name, and a keyword of a given name, are unique +objects. There's just one of each, so for instance no matter how +@code{()} arises in a program, it's the same object and can be +compared with @code{eq?}, + +@example +(define x (cdr '(123))) +(define y (cdr '(456))) +(eq? x y) @result{} #t + +(define x (string->symbol "foo")) +(eq? x 'foo) @result{} #t +@end example +@end deffn + +@deftypefn {C Function} int scm_is_eq (SCM x, SCM y) +Return @code{1} when @var{x} and @var{y} are equal in the sense of +@code{eq?}, otherwise return @code{0}. + +@findex == +The @code{==} operator should not be used on @code{SCM} values, an +@code{SCM} is a C type which cannot necessarily be compared using +@code{==} (@pxref{The SCM Type}). +@end deftypefn + +@sp 1 +@deffn {Scheme Procedure} eqv? x y +@deffnx {C Function} scm_eqv_p (x, y) +@rnindex eqv? +Return @code{#t} if @var{x} and @var{y} are the same object, or for +characters and numbers the same value. + +On objects except characters and numbers, @code{eqv?} is the same as +@code{eq?} above, it's true if @var{x} and @var{y} are the same +object. + +If @var{x} and @var{y} are numbers or characters, @code{eqv?} compares +their type and value. An exact number is not @code{eqv?} to an +inexact number (even if their value is the same). + +@example +(eqv? 3 (+ 1 2)) @result{} #t +(eqv? 1 1.0) @result{} #f +@end example +@end deffn + +@sp 1 +@deffn {Scheme Procedure} equal? x y +@deffnx {C Function} scm_equal_p (x, y) +@rnindex equal? +Return @code{#t} if @var{x} and @var{y} are the same type, and their +contents or value are equal. + +For a pair, string, vector, array or structure, @code{equal?} compares the +contents, and does so using the same @code{equal?} recursively, +so a deep structure can be traversed. + +@example +(equal? (list 1 2 3) (list 1 2 3)) @result{} #t +(equal? (list 1 2 3) (vector 1 2 3)) @result{} #f +@end example + +For other objects, @code{equal?} compares as per @code{eqv?} above, +which means characters and numbers are compared by type and value (and +like @code{eqv?}, exact and inexact numbers are not @code{equal?}, +even if their value is the same). + +@example +(equal? 3 (+ 1 2)) @result{} #t +(equal? 1 1.0) @result{} #f +@end example + +Hash tables are currently only compared as per @code{eq?}, so two +different tables are not @code{equal?}, even if their contents are the +same. + +@code{equal?} does not support circular data structures, it may go +into an infinite loop if asked to compare two circular lists or +similar. + +GOOPS object types (@pxref{GOOPS}), including foreign object types +(@pxref{Defining New Foreign Object Types}), can have an @code{equal?} +implementation specialized on two values of the same type. If +@code{equal?} is called on two GOOPS objects of the same type, +@code{equal?} will dispatch out to a generic function. This lets an +application traverse the contents or control what is considered +@code{equal?} for two objects of such a type. If there's no such +handler, the default is to just compare as per @code{eq?}. +@end deffn + + +@node Object Properties +@subsection Object Properties + +It's often useful to associate a piece of additional information with a +Scheme object even though that object does not have a dedicated slot +available in which the additional information could be stored. Object +properties allow you to do just that. + +Guile's representation of an object property is a procedure-with-setter +(@pxref{Procedures with Setters}) that can be used with the generalized +form of @code{set!} (REFFIXME) to set and retrieve that property for any +Scheme object. So, setting a property looks like this: + +@lisp +(set! (my-property obj1) value-for-obj1) +(set! (my-property obj2) value-for-obj2) +@end lisp + +@noindent +And retrieving values of the same property looks like this: + +@lisp +(my-property obj1) +@result{} +value-for-obj1 + +(my-property obj2) +@result{} +value-for-obj2 +@end lisp + +To create an object property in the first place, use the +@code{make-object-property} procedure: + +@lisp +(define my-property (make-object-property)) +@end lisp + +@deffn {Scheme Procedure} make-object-property +Create and return an object property. An object property is a +procedure-with-setter that can be called in two ways. @code{(set! +(@var{property} @var{obj}) @var{val})} sets @var{obj}'s @var{property} +to @var{val}. @code{(@var{property} @var{obj})} returns the current +setting of @var{obj}'s @var{property}. +@end deffn + +A single object property created by @code{make-object-property} can +associate distinct property values with all Scheme values that are +distinguishable by @code{eq?} (ruling out numeric values). + +Internally, object properties are implemented using a weak key hash +table. This means that, as long as a Scheme value with property values +is protected from garbage collection, its property values are also +protected. When the Scheme value is collected, its entry in the +property table is removed and so the (ex-) property values are no longer +protected by the table. + +Guile also implements a more traditional Lispy interface to properties, +in which each object has an list of key-value pairs associated with it. +Properties in that list are keyed by symbols. This is a legacy +interface; you should use weak hash tables or object properties instead. + +@deffn {Scheme Procedure} object-properties obj +@deffnx {C Function} scm_object_properties (obj) +Return @var{obj}'s property list. +@end deffn + +@deffn {Scheme Procedure} set-object-properties! obj alist +@deffnx {C Function} scm_set_object_properties_x (obj, alist) +Set @var{obj}'s property list to @var{alist}. +@end deffn + +@deffn {Scheme Procedure} object-property obj key +@deffnx {C Function} scm_object_property (obj, key) +Return the property of @var{obj} with name @var{key}. +@end deffn + +@deffn {Scheme Procedure} set-object-property! obj key value +@deffnx {C Function} scm_set_object_property_x (obj, key, value) +In @var{obj}'s property list, set the property named @var{key} +to @var{value}. +@end deffn + + +@node Sorting +@subsection Sorting + +@c FIXME::martin: Review me! + +@cindex sorting +@cindex sorting lists +@cindex sorting vectors + +Sorting is very important in computer programs. Therefore, Guile comes +with several sorting procedures built-in. As always, procedures with +names ending in @code{!} are side-effecting, that means that they may +modify their parameters in order to produce their results. + +The first group of procedures can be used to merge two lists (which must +be already sorted on their own) and produce sorted lists containing +all elements of the input lists. + +@deffn {Scheme Procedure} merge alist blist less +@deffnx {C Function} scm_merge (alist, blist, less) +Merge two already sorted lists into one. +Given two lists @var{alist} and @var{blist}, such that +@code{(sorted? alist less?)} and @code{(sorted? blist less?)}, +return a new list in which the elements of @var{alist} and +@var{blist} have been stably interleaved so that +@code{(sorted? (merge alist blist less?) less?)}. +Note: this does _not_ accept vectors. +@end deffn + +@deffn {Scheme Procedure} merge! alist blist less +@deffnx {C Function} scm_merge_x (alist, blist, less) +Takes two lists @var{alist} and @var{blist} such that +@code{(sorted? alist less?)} and @code{(sorted? blist less?)} and +returns a new list in which the elements of @var{alist} and +@var{blist} have been stably interleaved so that + @code{(sorted? (merge alist blist less?) less?)}. +This is the destructive variant of @code{merge} +Note: this does _not_ accept vectors. +@end deffn + +The following procedures can operate on sequences which are either +vectors or list. According to the given arguments, they return sorted +vectors or lists, respectively. The first of the following procedures +determines whether a sequence is already sorted, the other sort a given +sequence. The variants with names starting with @code{stable-} are +special in that they maintain a special property of the input sequences: +If two or more elements are the same according to the comparison +predicate, they are left in the same order as they appeared in the +input. + +@deffn {Scheme Procedure} sorted? items less +@deffnx {C Function} scm_sorted_p (items, less) +Return @code{#t} if @var{items} is a list or vector such that, +for each element @var{x} and the next element @var{y} of +@var{items}, @code{(@var{less} @var{y} @var{x})} returns +@code{#f}. Otherwise return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} sort items less +@deffnx {C Function} scm_sort (items, less) +Sort the sequence @var{items}, which may be a list or a +vector. @var{less} is used for comparing the sequence +elements. This is not a stable sort. +@end deffn + +@deffn {Scheme Procedure} sort! items less +@deffnx {C Function} scm_sort_x (items, less) +Sort the sequence @var{items}, which may be a list or a +vector. @var{less} is used for comparing the sequence +elements. The sorting is destructive, that means that the +input sequence is modified to produce the sorted result. +This is not a stable sort. +@end deffn + +@deffn {Scheme Procedure} stable-sort items less +@deffnx {C Function} scm_stable_sort (items, less) +Sort the sequence @var{items}, which may be a list or a +vector. @var{less} is used for comparing the sequence elements. +This is a stable sort. +@end deffn + +@deffn {Scheme Procedure} stable-sort! items less +@deffnx {C Function} scm_stable_sort_x (items, less) +Sort the sequence @var{items}, which may be a list or a +vector. @var{less} is used for comparing the sequence elements. +The sorting is destructive, that means that the input sequence +is modified to produce the sorted result. +This is a stable sort. +@end deffn + +The procedures in the last group only accept lists or vectors as input, +as their names indicate. + +@deffn {Scheme Procedure} sort-list items less +@deffnx {C Function} scm_sort_list (items, less) +Sort the list @var{items}, using @var{less} for comparing the +list elements. This is a stable sort. +@end deffn + +@deffn {Scheme Procedure} sort-list! items less +@deffnx {C Function} scm_sort_list_x (items, less) +Sort the list @var{items}, using @var{less} for comparing the +list elements. The sorting is destructive, that means that the +input list is modified to produce the sorted result. +This is a stable sort. +@end deffn + +@deffn {Scheme Procedure} restricted-vector-sort! vec less startpos endpos +@deffnx {C Function} scm_restricted_vector_sort_x (vec, less, startpos, endpos) +Sort the vector @var{vec}, using @var{less} for comparing +the vector elements. @var{startpos} (inclusively) and +@var{endpos} (exclusively) delimit +the range of the vector which gets sorted. The return value +is not specified. +@end deffn + + +@node Copying +@subsection Copying Deep Structures + +@c FIXME::martin: Review me! + +The procedures for copying lists (@pxref{Lists}) only produce a flat +copy of the input list, and currently Guile does not even contain +procedures for copying vectors. @code{copy-tree} can be used for these +application, as it does not only copy the spine of a list, but also +copies any pairs in the cars of the input lists. + +@deffn {Scheme Procedure} copy-tree obj +@deffnx {C Function} scm_copy_tree (obj) +Recursively copy the data tree that is bound to @var{obj}, and return +the new data structure. @code{copy-tree} recurses down the +contents of both pairs and vectors (since both cons cells and vector +cells may point to arbitrary objects), and stops recursing when it hits +any other object. +@end deffn + + +@node General Conversion +@subsection General String Conversion + +@c FIXME::martin: Review me! + +When debugging Scheme programs, but also for providing a human-friendly +interface, a procedure for converting any Scheme object into string +format is very useful. Conversion from/to strings can of course be done +with specialized procedures when the data type of the object to convert +is known, but with this procedure, it is often more comfortable. + +@code{object->string} converts an object by using a print procedure for +writing to a string port, and then returning the resulting string. +Converting an object back from the string is only possible if the object +type has a read syntax and the read syntax is preserved by the printing +procedure. + +@deffn {Scheme Procedure} object->string obj [printer] +@deffnx {C Function} scm_object_to_string (obj, printer) +Return a Scheme string obtained by printing @var{obj}. +Printing function can be specified by the optional second +argument @var{printer} (default: @code{write}). +@end deffn + + +@node Hooks +@subsection Hooks +@tpindex Hooks + +A hook is a list of procedures to be called at well defined points in +time. Typically, an application provides a hook @var{h} and promises +its users that it will call all of the procedures in @var{h} at a +defined point in the application's processing. By adding its own +procedure to @var{h}, an application user can tap into or even influence +the progress of the application. + +Guile itself provides several such hooks for debugging and customization +purposes: these are listed in a subsection below. + +When an application first creates a hook, it needs to know how many +arguments will be passed to the hook's procedures when the hook is run. +The chosen number of arguments (which may be none) is declared when the +hook is created, and all the procedures that are added to that hook must +be capable of accepting that number of arguments. + +A hook is created using @code{make-hook}. A procedure can be added to +or removed from a hook using @code{add-hook!} or @code{remove-hook!}, +and all of a hook's procedures can be removed together using +@code{reset-hook!}. When an application wants to run a hook, it does so +using @code{run-hook}. + +@menu +* Hook Example:: Hook usage by example. +* Hook Reference:: Reference of all hook procedures. +* C Hooks:: Hooks for use from C code. +* GC Hooks:: Garbage collection hooks. +* REPL Hooks:: Hooks into the Guile REPL. +@end menu + + +@node Hook Example +@subsubsection Hook Usage by Example + +Hook usage is shown by some examples in this section. First, we will +define a hook of arity 2 --- that is, the procedures stored in the hook +will have to accept two arguments. + +@lisp +(define hook (make-hook 2)) +hook +@result{} #<hook 2 40286c90> +@end lisp + +Now we are ready to add some procedures to the newly created hook with +@code{add-hook!}. In the following example, two procedures are added, +which print different messages and do different things with their +arguments. + +@lisp +(add-hook! hook (lambda (x y) + (display "Foo: ") + (display (+ x y)) + (newline))) +(add-hook! hook (lambda (x y) + (display "Bar: ") + (display (* x y)) + (newline))) +@end lisp + +Once the procedures have been added, we can invoke the hook using +@code{run-hook}. + +@lisp +(run-hook hook 3 4) +@print{} Bar: 12 +@print{} Foo: 7 +@end lisp + +Note that the procedures are called in the reverse of the order with +which they were added. This is because the default behaviour of +@code{add-hook!} is to add its procedure to the @emph{front} of the +hook's procedure list. You can force @code{add-hook!} to add its +procedure to the @emph{end} of the list instead by providing a third +@code{#t} argument on the second call to @code{add-hook!}. + +@lisp +(add-hook! hook (lambda (x y) + (display "Foo: ") + (display (+ x y)) + (newline))) +(add-hook! hook (lambda (x y) + (display "Bar: ") + (display (* x y)) + (newline)) + #t) ; @r{<- Change here!} + +(run-hook hook 3 4) +@print{} Foo: 7 +@print{} Bar: 12 +@end lisp + + +@node Hook Reference +@subsubsection Hook Reference + +When you create a hook with @code{make-hook}, you must specify the arity +of the procedures which can be added to the hook. If the arity is not +given explicitly as an argument to @code{make-hook}, it defaults to +zero. All procedures of a given hook must have the same arity, and when +the procedures are invoked using @code{run-hook}, the number of +arguments passed must match the arity specified at hook creation time. + +The order in which procedures are added to a hook matters. If the third +parameter to @code{add-hook!} is omitted or is equal to @code{#f}, the +procedure is added in front of the procedures which might already be on +that hook, otherwise the procedure is added at the end. The procedures +are always called from the front to the end of the list when they are +invoked via @code{run-hook}. + +The ordering of the list of procedures returned by @code{hook->list} +matches the order in which those procedures would be called if the hook +was run using @code{run-hook}. + +Note that the C functions in the following entries are for handling +@dfn{Scheme-level} hooks in C. There are also @dfn{C-level} hooks which +have their own interface (@pxref{C Hooks}). + +@deffn {Scheme Procedure} make-hook [n_args] +@deffnx {C Function} scm_make_hook (n_args) +Create a hook for storing procedure of arity @var{n_args}. +@var{n_args} defaults to zero. The returned value is a hook +object to be used with the other hook procedures. +@end deffn + +@deffn {Scheme Procedure} hook? x +@deffnx {C Function} scm_hook_p (x) +Return @code{#t} if @var{x} is a hook, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} hook-empty? hook +@deffnx {C Function} scm_hook_empty_p (hook) +Return @code{#t} if @var{hook} is an empty hook, @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} add-hook! hook proc [append_p] +@deffnx {C Function} scm_add_hook_x (hook, proc, append_p) +Add the procedure @var{proc} to the hook @var{hook}. The +procedure is added to the end if @var{append_p} is true, +otherwise it is added to the front. The return value of this +procedure is not specified. +@end deffn + +@deffn {Scheme Procedure} remove-hook! hook proc +@deffnx {C Function} scm_remove_hook_x (hook, proc) +Remove the procedure @var{proc} from the hook @var{hook}. The +return value of this procedure is not specified. +@end deffn + +@deffn {Scheme Procedure} reset-hook! hook +@deffnx {C Function} scm_reset_hook_x (hook) +Remove all procedures from the hook @var{hook}. The return +value of this procedure is not specified. +@end deffn + +@deffn {Scheme Procedure} hook->list hook +@deffnx {C Function} scm_hook_to_list (hook) +Convert the procedure list of @var{hook} to a list. +@end deffn + +@deffn {Scheme Procedure} run-hook hook arg @dots{} +@deffnx {C Function} scm_run_hook (hook, args) +Apply all procedures from the hook @var{hook} to the arguments @var{arg} +@enddots{}. The order of the procedure application is first to last. +The return value of this procedure is not specified. +@end deffn + +If, in C code, you are certain that you have a hook object and well +formed argument list for that hook, you can also use +@code{scm_c_run_hook}, which is identical to @code{scm_run_hook} but +does no type checking. + +@deftypefn {C Function} void scm_c_run_hook (SCM hook, SCM args) +The same as @code{scm_run_hook} but without any type checking to confirm +that @var{hook} is actually a hook object and that @var{args} is a +well-formed list matching the arity of the hook. +@end deftypefn + +For C code, @code{SCM_HOOKP} is a faster alternative to +@code{scm_hook_p}: + +@deftypefn {C Macro} int SCM_HOOKP (x) +Return 1 if @var{x} is a Scheme-level hook, 0 otherwise. +@end deftypefn + + +@node C Hooks +@subsubsection Hooks For C Code. + +The hooks already described are intended to be populated by Scheme-level +procedures. In addition to this, the Guile library provides an +independent set of interfaces for the creation and manipulation of hooks +that are designed to be populated by functions implemented in C. + +The original motivation here was to provide a kind of hook that could +safely be invoked at various points during garbage collection. +Scheme-level hooks are unsuitable for this purpose as running them could +itself require memory allocation, which would then invoke garbage +collection recursively @dots{} However, it is also the case that these +hooks are easier to work with than the Scheme-level ones if you only +want to register C functions with them. So if that is mainly what your +code needs to do, you may prefer to use this interface. + +To create a C hook, you should allocate storage for a structure of type +@code{scm_t_c_hook} and then initialize it using @code{scm_c_hook_init}. + +@deftp {C Type} scm_t_c_hook +Data type for a C hook. The internals of this type should be treated as +opaque. +@end deftp + +@deftp {C Enum} scm_t_c_hook_type +Enumeration of possible hook types, which are: + +@table @code +@item SCM_C_HOOK_NORMAL +@vindex SCM_C_HOOK_NORMAL +Type of hook for which all the registered functions will always be called. +@item SCM_C_HOOK_OR +@vindex SCM_C_HOOK_OR +Type of hook for which the sequence of registered functions will be +called only until one of them returns C true (a non-NULL pointer). +@item SCM_C_HOOK_AND +@vindex SCM_C_HOOK_AND +Type of hook for which the sequence of registered functions will be +called only until one of them returns C false (a NULL pointer). +@end table +@end deftp + +@deftypefn {C Function} void scm_c_hook_init (scm_t_c_hook *hook, void *hook_data, scm_t_c_hook_type type) +Initialize the C hook at memory pointed to by @var{hook}. @var{type} +should be one of the values of the @code{scm_t_c_hook_type} enumeration, +and controls how the hook functions will be called. @var{hook_data} is +a closure parameter that will be passed to all registered hook functions +when they are called. +@end deftypefn + +To add or remove a C function from a C hook, use @code{scm_c_hook_add} +or @code{scm_c_hook_remove}. A hook function must expect three +@code{void *} parameters which are, respectively: + +@table @var +@item hook_data +The hook closure data that was specified at the time the hook was +initialized by @code{scm_c_hook_init}. + +@item func_data +The function closure data that was specified at the time that that +function was registered with the hook by @code{scm_c_hook_add}. + +@item data +The call closure data specified by the @code{scm_c_hook_run} call that +runs the hook. +@end table + +@deftp {C Type} scm_t_c_hook_function +Function type for a C hook function: takes three @code{void *} +parameters and returns a @code{void *} result. +@end deftp + +@deftypefn {C Function} void scm_c_hook_add (scm_t_c_hook *hook, scm_t_c_hook_function func, void *func_data, int appendp) +Add function @var{func}, with function closure data @var{func_data}, to +the C hook @var{hook}. The new function is appended to the hook's list +of functions if @var{appendp} is non-zero, otherwise prepended. +@end deftypefn + +@deftypefn {C Function} void scm_c_hook_remove (scm_t_c_hook *hook, scm_t_c_hook_function func, void *func_data) +Remove function @var{func}, with function closure data @var{func_data}, +from the C hook @var{hook}. @code{scm_c_hook_remove} checks both +@var{func} and @var{func_data} so as to allow for the same @var{func} +being registered multiple times with different closure data. +@end deftypefn + +Finally, to invoke a C hook, call the @code{scm_c_hook_run} function +specifying the hook and the call closure data for this run: + +@deftypefn {C Function} {void *} scm_c_hook_run (scm_t_c_hook *hook, void *data) +Run the C hook @var{hook} will call closure data @var{data}. Subject to +the variations for hook types @code{SCM_C_HOOK_OR} and +@code{SCM_C_HOOK_AND}, @code{scm_c_hook_run} calls @var{hook}'s +registered functions in turn, passing them the hook's closure data, each +function's closure data, and the call closure data. + +@code{scm_c_hook_run}'s return value is the return value of the last +function to be called. +@end deftypefn + + +@node GC Hooks +@subsubsection Hooks for Garbage Collection + +Whenever Guile performs a garbage collection, it calls the following +hooks in the order shown. + +@defvr {C Hook} scm_before_gc_c_hook +C hook called at the very start of a garbage collection, after setting +@code{scm_gc_running_p} to 1, but before entering the GC critical +section. + +If garbage collection is blocked because @code{scm_block_gc} is +non-zero, GC exits early soon after calling this hook, and no further +hooks will be called. +@end defvr + +@defvr {C Hook} scm_before_mark_c_hook +C hook called before beginning the mark phase of garbage collection, +after the GC thread has entered a critical section. +@end defvr + +@defvr {C Hook} scm_before_sweep_c_hook +C hook called before beginning the sweep phase of garbage collection. +This is the same as at the end of the mark phase, since nothing else +happens between marking and sweeping. +@end defvr + +@defvr {C Hook} scm_after_sweep_c_hook +C hook called after the end of the sweep phase of garbage collection, +but while the GC thread is still inside its critical section. +@end defvr + +@defvr {C Hook} scm_after_gc_c_hook +C hook called at the very end of a garbage collection, after the GC +thread has left its critical section. +@end defvr + +@defvr {Scheme Hook} after-gc-hook +@vindex scm_after_gc_hook +Scheme hook with arity 0. This hook is run asynchronously +(@pxref{Asyncs}) soon after the GC has completed and any other events +that were deferred during garbage collection have been processed. (Also +accessible from C with the name @code{scm_after_gc_hook}.) +@end defvr + +All the C hooks listed here have type @code{SCM_C_HOOK_NORMAL}, are +initialized with hook closure data NULL, are invoked by +@code{scm_c_hook_run} with call closure data NULL. + +@cindex guardians, testing for GC'd objects +The Scheme hook @code{after-gc-hook} is particularly useful in +conjunction with guardians (@pxref{Guardians}). Typically, if you are +using a guardian, you want to call the guardian after garbage collection +to see if any of the objects added to the guardian have been collected. +By adding a thunk that performs this call to @code{after-gc-hook}, you +can ensure that your guardian is tested after every garbage collection +cycle. + + +@node REPL Hooks +@subsubsection Hooks into the Guile REPL + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/api.txt b/doc/ref/api.txt new file mode 100644 index 000000000..cc26b839f --- /dev/null +++ b/doc/ref/api.txt @@ -0,0 +1,185 @@ +Scheme objects +============== + +There are two basic C data types to represent objects in guile: + +- SCM: SCM is the user level abstract C type that is used to represent all of +guile's scheme objects, no matter what the scheme object type is. No C +operation except assignment is guaranteed to work with variables of type SCM. +Only use macros and functions to work with SCM values. Values are converted +between C data types and the SCM type with utility functions and macros. + +- scm_bits_t: An integral data type that is guaranteed to be large enough to +hold all information that is required to represent any scheme object. While +this data type is used to implement guile internals, the use of this type is +also necessary to write certain kinds of extensions to guile. + + +Relationship between SCM and scm_bits_t +======================================= + +A variable of type SCM is guaranteed to hold a valid scheme object. A +variable of type scm_bits_t, however, may either 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_bits_t variable y by using the +SCM_UNPACK macro. After this has been done, the type of the scheme object x +can be derived from the content of the bits of the scm_bits_t value y, as is +described in -->data-rep. A valid bit encoding of a scheme value as a +scm_bits_t variable can be transformed into the corresponding SCM value by +using the SCM_PACK macro. + +- scm_bits_t SCM_UNPACK (SCM x): Transforms the SCM value x into it's +representation as an integral type. Only after applying SCM_UNPACK it is +possible to access the bits and contents of the SCM value. + +- SCM SCM_PACK (scm_bits_t x): Takes a valid integral representation of a +scheme object and transforms it into its representation as a SCM value. + + +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 'cell' with +additional information on the heap. While the fact, whether an object is an +immediate or not should be irrelevant for user code, within guile's own code +the distinction is sometimes of importance. Thus, the following low level +macro is provided: + +- int SCM_IMP (SCM x): A scheme object is an immediate if it fullfills the +SCM_IMP predicate, otherwise it holds an encoded reference to a heap cell. +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: +* For 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_bits_t value that is delivered by SCM_UNPACK (x). + + +Non immediate objects +===================== + +- (scm_t_cell *) SCM2PTR (SCM x) (FIXME:: this name should be changed) +- SCM PTR2SCM (scm_t_cell * x) (FIXME:: this name should be changed) + +A scheme object of type SCM that does not fullfill the SCM_IMP predicate holds +an encoded reference to a heap cell. This reference can be decoded to a C +pointer to a heap cell using the SCM2PTR macro. The encoding of a pointer to +a heap cell into a SCM value is done using the PTR2SCM macro. + +Note that it is also possible to transform a non immediate SCM value by using +SCM_UNPACK into a scm_bits_t variable. Hower, the result of SCM_UNPACK may +not be used as a pointer to a scm_t_cell: Only SCM2PTR is guaranteed to +transform a SCM object into a valid pointer to a heap cell. Also, it is not +allowed to apply PTR2SCM to anything that is not a valid pointer to a heap +cell. + +Summary: +* Only use SCM2PTR for SCM values for which SCM_IMP is false! +* Don't use '(scm_t_cell*) SCM_UNPACK (x)'! Use 'SCM2PTR (x)' instead! +* Don't use PTR2SCM for anything but a cell pointer! + + +Heap Cell Type Information +========================== + +Heap cells contain a number of entries, each of which is either a scheme +object of type SCM or a raw C value of type scm_bits_t. Which of the cell +entries contain scheme objects and which contain raw C values is determined by +the first entry of the cell, which holds the cell type information. + +- scm_bits_t SCM_CELL_TYPE (SCM x): For a non immediate scheme object x, +deliver the content of the first entry of the heap cell referenced by x. This +value holds the information about the cell type as described in -->data-rep. + +- void SCM_SET_CELL_TYPE (SCM x, scm_bits_t t): For a non immediate scheme +object x, write the value t into the first entry of the heap cell referenced +by x. The value t must hold a valid cell type as described in -->data-rep. + + +Accessing Cell Entries +====================== + +For a non immediate scheme object x, the object type can be determined by +reading the cell type entry using the SCM_CELL_TYPE macro. For the different +types of cells it is known which cell entry holds scheme objects and which cell +entry holds raw C data. To access the different cell entries appropriately, +the following macros are provided: + +- scm_bits_t SCM_CELL_WORD (SCM x, unsigned int n): Deliver the cell entry n +of the heap cell referenced by the non immediate scheme object x as raw data. +It is illegal, to access cell entries that hold scheme objects by using these +macros. For convenience, the following macros are also provided: + SCM_CELL_WORD_0 (x) --> SCM_CELL_WORD (x, 0) + SCM_CELL_WORD_1 (x) --> SCM_CELL_WORD (x, 1) + ... + SCM_CELL_WORD_n (x) --> SCM_CELL_WORD (x, n) + +- SCM SCM_CELL_OBJECT (SCM x, unsigned int n): Deliver the cell entry n of +the heap cell referenced by the non immediate scheme object x as a scheme +object. It is illegal, to access cell entries that do not hold scheme objects +by using these macros. For convenience, the following macros are also +provided: + SCM_CELL_OBJECT_0 (x) --> SCM_CELL_OBJECT (x, 0) + SCM_CELL_OBJECT_1 (x) --> SCM_CELL_OBJECT (x, 1) + ... + SCM_CELL_OBJECT_n (x) --> SCM_CELL_OBJECT (x, n) + +- void SCM_SET_CELL_WORD (SCM x, unsigned int n, scm_bits_t w): Write the raw +C value w into entry number n of the heap cell referenced by the non immediate +scheme value x. Values that are written into cells this way may only be read +from the cells using the SCM_CELL_WORD macros or, in case cell entry 0 is +written, using the SCM_CELL_TYPE macro. For the special case of cell entry 0 +it has to be made sure that w contains a cell type information (see +-->data-rep) which does not describe a scheme object. For convenience, the +following macros are also provided: + SCM_SET_CELL_WORD_0 (x, w) --> SCM_SET_CELL_WORD (x, 0, w) + SCM_SET_CELL_WORD_1 (x, w) --> SCM_SET_CELL_WORD (x, 1, w) + ... + SCM_SET_CELL_WORD_n (x, w) --> SCM_SET_CELL_WORD (x, n, w) + +- void SCM_SET_CELL_OBJECT (SCM x, unsigned int n, SCM o): Write the scheme +object o into entry number n of the heap cell referenced by the non immediate +scheme value x. Values that are written into cells this way may only be read +from the cells using the SCM_CELL_OBJECT macros or, in case cell entry 0 is +written, using the SCM_CELL_TYPE macro. For the special case of cell entry 0 +the writing of a scheme object into this cell is only allowed, if the cell +forms a scheme pair. For convenience, the following macros are also provided: + SCM_SET_CELL_OBJECT_0 (x, o) --> SCM_SET_CELL_OBJECT (x, 0, o) + SCM_SET_CELL_OBJECT_1 (x, o) --> SCM_SET_CELL_OBJECT (x, 1, o) + ... + SCM_SET_CELL_OBJECT_n (x, o) --> SCM_SET_CELL_OBJECT (x, n, o) + +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 cell type information is available, only use the appropriate + access methods to read and write data to the different cell entries. + + +Basic Rules for Accessing Cell Entries +====================================== + +For each cell type it is generally up to the implementation of that type which +of the corresponding cell entries hold scheme objects and which hold raw C +values. However, there is one basic rules that has to be followed: Scheme +pairs consist of exactly two cell entries, which both contain scheme objects. +Further, a cell which contains a scheme object in it first entry has to be a +scheme pair. In other words, it is not allowed to store a scheme object in +the first cell entry and a non scheme object in the second cell entry. + +Fixme:shouldn't this rather be SCM_PAIRP / SCM_PAIR_P ? +- int SCM_CONSP (SCM x): Determine, whether the scheme object x is a scheme +pair, i. e. whether x references a heap cell consisting of exactly two +entries, where both entries contain a scheme object. In this case, both +entries will have to be accessed using the SCM_CELL_OBJECT macros. On the +contrary, if the SCM_CONSP predicate is not fulfilled, the first entry of the +scheme cell is guaranteed not to be a scheme value and thus the first cell +entry must be accessed using the SCM_CELL_WORD_0 macro. diff --git a/doc/ref/compiler.texi b/doc/ref/compiler.texi new file mode 100644 index 000000000..7e1f29fcb --- /dev/null +++ b/doc/ref/compiler.texi @@ -0,0 +1,1388 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008-2016, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Compiling to the Virtual Machine +@section Compiling to the Virtual Machine + +Compilers! The word itself inspires excitement and awe, even among +experienced practitioners. But a compiler is just a program: an +eminently hackable thing. This section aims to to describe Guile's +compiler in such a way that interested Scheme hackers can feel +comfortable reading and extending it. + +@xref{Read/Load/Eval/Compile}, if you're lost and you just wanted to +know how to compile your @code{.scm} file. + +@menu +* Compiler Tower:: +* The Scheme Compiler:: +* Tree-IL:: +* Continuation-Passing Style:: +* Bytecode:: +* Writing New High-Level Languages:: +* Extending the Compiler:: +@end menu + +@node Compiler Tower +@subsection Compiler Tower + +Guile's compiler is quite simple -- its @emph{compilers}, to put it more +accurately. Guile defines a tower of languages, starting at Scheme and +progressively simplifying down to languages that resemble the VM +instruction set (@pxref{Instruction Set}). + +Each language knows how to compile to the next, so each step is simple +and understandable. Furthermore, this set of languages is not hardcoded +into Guile, so it is possible for the user to add new high-level +languages, new passes, or even different compilation targets. + +Languages are registered in the module, @code{(system base language)}: + +@example +(use-modules (system base language)) +@end example + +They are registered with the @code{define-language} form. + +@deffn {Scheme Syntax} define-language @ + [#:name] [#:title] [#:reader] [#:printer] @ + [#:parser=#f] [#:compilers='()] @ + [#:decompilers='()] [#:evaluator=#f] @ + [#:joiner=#f] [#:for-humans?=#t] @ + [#:make-default-environment=make-fresh-user-module] +Define a language. + +This syntax defines a @code{<language>} object, bound to @var{name} in +the current environment. In addition, the language will be added to the +global language set. For example, this is the language definition for +Scheme: + +@example +(define-language scheme + #:title "Scheme" + #:reader (lambda (port env) ...) + #:compilers `((tree-il . ,compile-tree-il)) + #:decompilers `((tree-il . ,decompile-tree-il)) + #:evaluator (lambda (x module) (primitive-eval x)) + #:printer write + #:make-default-environment (lambda () ...)) +@end example +@end deffn + +The interesting thing about having languages defined this way is that +they present a uniform interface to the read-eval-print loop. This +allows the user to change the current language of the REPL: + +@example +scheme@@(guile-user)> ,language tree-il +Happy hacking with Tree Intermediate Language! To switch back, type `,L scheme'. +tree-il@@(guile-user)> ,L scheme +Happy hacking with Scheme! To switch back, type `,L tree-il'. +scheme@@(guile-user)> +@end example + +Languages can be looked up by name, as they were above. + +@deffn {Scheme Procedure} lookup-language name +Looks up a language named @var{name}, autoloading it if necessary. + +Languages are autoloaded by looking for a variable named @var{name} in +a module named @code{(language @var{name} spec)}. + +The language object will be returned, or @code{#f} if there does not +exist a language with that name. +@end deffn + +Defining languages this way allows us to programmatically determine +the necessary steps for compiling code from one language to another. + +@deffn {Scheme Procedure} lookup-compilation-order from to +Recursively traverses the set of languages to which @var{from} can +compile, depth-first, and return the first path that can transform +@var{from} to @var{to}. Returns @code{#f} if no path is found. + +This function memoizes its results in a cache that is invalidated by +subsequent calls to @code{define-language}, so it should be quite +fast. +@end deffn + +There is a notion of a ``current language'', which is maintained in the +@code{current-language} parameter, defined in the core @code{(guile)} +module. This language is normally Scheme, and may be rebound by the +user. The run-time compilation interfaces +(@pxref{Read/Load/Eval/Compile}) also allow you to choose other source +and target languages. + +The normal tower of languages when compiling Scheme goes like this: + +@itemize +@item Scheme +@item Tree Intermediate Language (Tree-IL) +@item Continuation-Passing Style (CPS) +@item Bytecode +@end itemize + +As discussed before (@pxref{Object File Format}), bytecode is in ELF +format, ready to be serialized to disk. But when compiling Scheme at +run time, you want a Scheme value: for example, a compiled procedure. +For this reason, so as not to break the abstraction, Guile defines a +fake language at the bottom of the tower: + +@itemize +@item Value +@end itemize + +Compiling to @code{value} loads the bytecode into a procedure, turning +cold bytes into warm code. + +Perhaps this strangeness can be explained by example: +@code{compile-file} defaults to compiling to bytecode, because it +produces object code that has to live in the barren world outside the +Guile runtime; but @code{compile} defaults to compiling to @code{value}, +as its product re-enters the Guile world. + +@c FIXME: This doesn't work anymore :( Should we add some kind of +@c special GC pass, or disclaim this kind of code, or what? + +Indeed, the process of compilation can circulate through these +different worlds indefinitely, as shown by the following quine: + +@example +((lambda (x) ((compile x) x)) '(lambda (x) ((compile x) x))) +@end example + +@node The Scheme Compiler +@subsection The Scheme Compiler + +The job of the Scheme compiler is to expand all macros and all of Scheme +to its most primitive expressions. The definition of ``primitive +expression'' is given by the inventory of constructs provided by +Tree-IL, the target language of the Scheme compiler: procedure calls, +conditionals, lexical references, and so on. This is described more +fully in the next section. + +The tricky and amusing thing about the Scheme-to-Tree-IL compiler is +that it is completely implemented by the macro expander. Since the +macro expander has to run over all of the source code already in order +to expand macros, it might as well do the analysis at the same time, +producing Tree-IL expressions directly. + +Because this compiler is actually the macro expander, it is extensible. +Any macro which the user writes becomes part of the compiler. + +The Scheme-to-Tree-IL expander may be invoked using the generic +@code{compile} procedure: + +@lisp +(compile '(+ 1 2) #:from 'scheme #:to 'tree-il) +@result{} +#<tree-il (call (toplevel +) (const 1) (const 2))> +@end lisp + +@code{(compile @var{foo} #:from 'scheme #:to 'tree-il)} is entirely +equivalent to calling the macro expander as @code{(macroexpand @var{foo} +'c '(compile load eval))}. @xref{Macro Expansion}. +@code{compile-tree-il}, the procedure dispatched by @code{compile} to +@code{'tree-il}, is a small wrapper around @code{macroexpand}, to make +it conform to the general form of compiler procedures in Guile's +language tower. + +Compiler procedures take three arguments: an expression, an +environment, and a keyword list of options. They return three values: +the compiled expression, the corresponding environment for the target +language, and a ``continuation environment''. The compiled expression +and environment will serve as input to the next language's compiler. +The ``continuation environment'' can be used to compile another +expression from the same source language within the same module. + +For example, you might compile the expression, @code{(define-module +(foo))}. This will result in a Tree-IL expression and environment. But +if you compiled a second expression, you would want to take into +account the compile-time effect of compiling the previous expression, +which puts the user in the @code{(foo)} module. That is purpose of the +``continuation environment''; you would pass it as the environment +when compiling the subsequent expression. + +For Scheme, an environment is a module. By default, the @code{compile} +and @code{compile-file} procedures compile in a fresh module, such +that bindings and macros introduced by the expression being compiled +are isolated: + +@example +(eq? (current-module) (compile '(current-module))) +@result{} #f + +(compile '(define hello 'world)) +(defined? 'hello) +@result{} #f + +(define / *) +(eq? (compile '/) /) +@result{} #f +@end example + +Similarly, changes to the @code{current-reader} fluid (@pxref{Loading, +@code{current-reader}}) are isolated: + +@example +(compile '(fluid-set! current-reader (lambda args 'fail))) +(fluid-ref current-reader) +@result{} #f +@end example + +Nevertheless, having the compiler and @dfn{compilee} share the same name +space can be achieved by explicitly passing @code{(current-module)} as +the compilation environment: + +@example +(define hello 'world) +(compile 'hello #:env (current-module)) +@result{} world +@end example + +@node Tree-IL +@subsection Tree-IL + +Tree Intermediate Language (Tree-IL) is a structured intermediate +language that is close in expressive power to Scheme. It is an +expanded, pre-analyzed Scheme. + +Tree-IL is ``structured'' in the sense that its representation is +based on records, not S-expressions. This gives a rigidity to the +language that ensures that compiling to a lower-level language only +requires a limited set of transformations. For example, the Tree-IL +type @code{<const>} is a record type with two fields, @code{src} and +@code{exp}. Instances of this type are created via @code{make-const}. +Fields of this type are accessed via the @code{const-src} and +@code{const-exp} procedures. There is also a predicate, @code{const?}. +@xref{Records}, for more information on records. + +@c alpha renaming + +All Tree-IL types have a @code{src} slot, which holds source location +information for the expression. This information, if present, will be +residualized into the compiled object code, allowing backtraces to +show source information. The format of @code{src} is the same as that +returned by Guile's @code{source-properties} function. @xref{Source +Properties}, for more information. + +Although Tree-IL objects are represented internally using records, +there is also an equivalent S-expression external representation for +each kind of Tree-IL. For example, the S-expression representation +of @code{#<const src: #f exp: 3>} expression would be: + +@example +(const 3) +@end example + +Users may program with this format directly at the REPL: + +@example +scheme@@(guile-user)> ,language tree-il +Happy hacking with Tree Intermediate Language! To switch back, type `,L scheme'. +tree-il@@(guile-user)> (call (primitive +) (const 32) (const 10)) +@result{} 42 +@end example + +The @code{src} fields are left out of the external representation. + +One may create Tree-IL objects from their external representations via +calling @code{parse-tree-il}, the reader for Tree-IL. If any source +information is attached to the input S-expression, it will be +propagated to the resulting Tree-IL expressions. This is probably the +easiest way to compile to Tree-IL: just make the appropriate external +representations in S-expression format, and let @code{parse-tree-il} +take care of the rest. + +@deftp {Scheme Variable} <void> src +@deftpx {External Representation} (void) +An empty expression. In practice, equivalent to Scheme's @code{(if #f +#f)}. +@end deftp + +@deftp {Scheme Variable} <const> src exp +@deftpx {External Representation} (const @var{exp}) +A constant. +@end deftp + +@deftp {Scheme Variable} <primitive-ref> src name +@deftpx {External Representation} (primitive @var{name}) +A reference to a ``primitive''. A primitive is a procedure that, when +compiled, may be open-coded. For example, @code{cons} is usually +recognized as a primitive, so that it compiles down to a single +instruction. + +Compilation of Tree-IL usually begins with a pass that resolves some +@code{<module-ref>} and @code{<toplevel-ref>} expressions to +@code{<primitive-ref>} expressions. The actual compilation pass has +special cases for calls to certain primitives, like @code{apply} or +@code{cons}. +@end deftp + +@deftp {Scheme Variable} <lexical-ref> src name gensym +@deftpx {External Representation} (lexical @var{name} @var{gensym}) +A reference to a lexically-bound variable. The @var{name} is the +original name of the variable in the source program. @var{gensym} is a +unique identifier for this variable. +@end deftp + +@deftp {Scheme Variable} <lexical-set> src name gensym exp +@deftpx {External Representation} (set! (lexical @var{name} @var{gensym}) @var{exp}) +Sets a lexically-bound variable. +@end deftp + +@deftp {Scheme Variable} <module-ref> src mod name public? +@deftpx {External Representation} (@@ @var{mod} @var{name}) +@deftpx {External Representation} (@@@@ @var{mod} @var{name}) +A reference to a variable in a specific module. @var{mod} should be +the name of the module, e.g.@: @code{(guile-user)}. + +If @var{public?} is true, the variable named @var{name} will be looked +up in @var{mod}'s public interface, and serialized with @code{@@}; +otherwise it will be looked up among the module's private bindings, +and is serialized with @code{@@@@}. +@end deftp + +@deftp {Scheme Variable} <module-set> src mod name public? exp +@deftpx {External Representation} (set! (@@ @var{mod} @var{name}) @var{exp}) +@deftpx {External Representation} (set! (@@@@ @var{mod} @var{name}) @var{exp}) +Sets a variable in a specific module. +@end deftp + +@deftp {Scheme Variable} <toplevel-ref> src name +@deftpx {External Representation} (toplevel @var{name}) +References a variable from the current procedure's module. +@end deftp + +@deftp {Scheme Variable} <toplevel-set> src name exp +@deftpx {External Representation} (set! (toplevel @var{name}) @var{exp}) +Sets a variable in the current procedure's module. +@end deftp + +@deftp {Scheme Variable} <toplevel-define> src name exp +@deftpx {External Representation} (define @var{name} @var{exp}) +Defines a new top-level variable in the current procedure's module. +@end deftp + +@deftp {Scheme Variable} <conditional> src test then else +@deftpx {External Representation} (if @var{test} @var{then} @var{else}) +A conditional. Note that @var{else} is not optional. +@end deftp + +@deftp {Scheme Variable} <call> src proc args +@deftpx {External Representation} (call @var{proc} . @var{args}) +A procedure call. +@end deftp + +@deftp {Scheme Variable} <primcall> src name args +@deftpx {External Representation} (primcall @var{name} . @var{args}) +A call to a primitive. Equivalent to @code{(call (primitive @var{name}) +. @var{args})}. This construct is often more convenient to generate and +analyze than @code{<call>}. + +As part of the compilation process, instances of @code{(call (primitive +@var{name}) . @var{args})} are transformed into primcalls. +@end deftp + +@deftp {Scheme Variable} <seq> src head tail +@deftpx {External Representation} (seq @var{head} @var{tail}) +A sequence. The semantics is that @var{head} is evaluated first, and +any resulting values are ignored. Then @var{tail} is evaluated, in tail +position. +@end deftp + +@deftp {Scheme Variable} <lambda> src meta body +@deftpx {External Representation} (lambda @var{meta} @var{body}) +A closure. @var{meta} is an association list of properties for the +procedure. @var{body} is a single Tree-IL expression of type +@code{<lambda-case>}. As the @code{<lambda-case>} clause can chain to +an alternate clause, this makes Tree-IL's @code{<lambda>} have the +expressiveness of Scheme's @code{case-lambda}. +@end deftp + +@deftp {Scheme Variable} <lambda-case> req opt rest kw inits gensyms body alternate +@deftpx {External Representation} @ + (lambda-case ((@var{req} @var{opt} @var{rest} @var{kw} @var{inits} @var{gensyms})@ + @var{body})@ + [@var{alternate}]) +One clause of a @code{case-lambda}. A @code{lambda} expression in +Scheme is treated as a @code{case-lambda} with one clause. + +@var{req} is a list of the procedure's required arguments, as symbols. +@var{opt} is a list of the optional arguments, or @code{#f} if there +are no optional arguments. @var{rest} is the name of the rest +argument, or @code{#f}. + +@var{kw} is a list of the form, @code{(@var{allow-other-keys?} +(@var{keyword} @var{name} @var{var}) ...)}, where @var{keyword} is the +keyword corresponding to the argument named @var{name}, and whose +corresponding gensym is @var{var}. @var{inits} are tree-il expressions +corresponding to all of the optional and keyword arguments, evaluated to +bind variables whose value is not supplied by the procedure caller. +Each @var{init} expression is evaluated in the lexical context of +previously bound variables, from left to right. + +@var{gensyms} is a list of gensyms corresponding to all arguments: +first all of the required arguments, then the optional arguments if +any, then the rest argument if any, then all of the keyword arguments. + +@var{body} is the body of the clause. If the procedure is called with +an appropriate number of arguments, @var{body} is evaluated in tail +position. Otherwise, if there is an @var{alternate}, it should be a +@code{<lambda-case>} expression, representing the next clause to try. +If there is no @var{alternate}, a wrong-number-of-arguments error is +signaled. +@end deftp + +@deftp {Scheme Variable} <let> src names gensyms vals exp +@deftpx {External Representation} (let @var{names} @var{gensyms} @var{vals} @var{exp}) +Lexical binding, like Scheme's @code{let}. @var{names} are the original +binding names, @var{gensyms} are gensyms corresponding to the +@var{names}, and @var{vals} are Tree-IL expressions for the values. +@var{exp} is a single Tree-IL expression. +@end deftp + +@deftp {Scheme Variable} <letrec> in-order? src names gensyms vals exp +@deftpx {External Representation} (letrec @var{names} @var{gensyms} @var{vals} @var{exp}) +@deftpx {External Representation} (letrec* @var{names} @var{gensyms} @var{vals} @var{exp}) +A version of @code{<let>} that creates recursive bindings, like +Scheme's @code{letrec}, or @code{letrec*} if @var{in-order?} is true. +@end deftp + +@deftp {Scheme Variable} <prompt> escape-only? tag body handler +@deftpx {External Representation} (prompt @var{escape-only?} @var{tag} @var{body} @var{handler}) +A dynamic prompt. Instates a prompt named @var{tag}, an expression, +during the dynamic extent of the execution of @var{body}, also an +expression. If an abort occurs to this prompt, control will be passed +to @var{handler}, also an expression, which should be a procedure. The +first argument to the handler procedure will be the captured +continuation, followed by all of the values passed to the abort. If +@var{escape-only?} is true, the handler should be a @code{<lambda>} with +a single @code{<lambda-case>} body expression with no optional or +keyword arguments, and no alternate, and whose first argument is +unreferenced. @xref{Prompts}, for more information. +@end deftp + +@deftp {Scheme Variable} <abort> tag args tail +@deftpx {External Representation} (abort @var{tag} @var{args} @var{tail}) +An abort to the nearest prompt with the name @var{tag}, an expression. +@var{args} should be a list of expressions to pass to the prompt's +handler, and @var{tail} should be an expression that will evaluate to +a list of additional arguments. An abort will save the partial +continuation, which may later be reinstated, resulting in the +@code{<abort>} expression evaluating to some number of values. +@end deftp + +There are two Tree-IL constructs that are not normally produced by +higher-level compilers, but instead are generated during the +source-to-source optimization and analysis passes that the Tree-IL +compiler does. Users should not generate these expressions directly, +unless they feel very clever, as the default analysis pass will generate +them as necessary. + +@deftp {Scheme Variable} <let-values> src names gensyms exp body +@deftpx {External Representation} (let-values @var{names} @var{gensyms} @var{exp} @var{body}) +Like Scheme's @code{receive} -- binds the values returned by +evaluating @code{exp} to the @code{lambda}-like bindings described by +@var{gensyms}. That is to say, @var{gensyms} may be an improper list. + +@code{<let-values>} is an optimization of a @code{<call>} to the +primitive, @code{call-with-values}. +@end deftp + +@deftp {Scheme Variable} <fix> src names gensyms vals body +@deftpx {External Representation} (fix @var{names} @var{gensyms} @var{vals} @var{body}) +Like @code{<letrec>}, but only for @var{vals} that are unset +@code{lambda} expressions. + +@code{fix} is an optimization of @code{letrec} (and @code{let}). +@end deftp + +Tree-IL is a convenient compilation target from source languages. It +can be convenient as a medium for optimization, though CPS is usually +better. The strength of Tree-IL is that it does not fix order of +evaluation, so it makes some code motion a bit easier. + +Optimization passes performed on Tree-IL currently include: + +@itemize +@item Open-coding (turning toplevel-refs into primitive-refs, +and calls to primitives to primcalls) +@item Partial evaluation (comprising inlining, copy propagation, and +constant folding) +@end itemize + +@node Continuation-Passing Style +@subsection Continuation-Passing Style + +@cindex CPS +Continuation-passing style (CPS) is Guile's principal intermediate +language, bridging the gap between languages for people and languages +for machines. CPS gives a name to every part of a program: every +control point, and every intermediate value. This makes it an excellent +medium for reasoning about programs, which is the principal job of a +compiler. + +@menu +* An Introduction to CPS:: +* CPS in Guile:: +* Building CPS:: +* CPS Soup:: +* Compiling CPS:: +@end menu + +@node An Introduction to CPS +@subsubsection An Introduction to CPS + +Consider the following Scheme expression: + +@lisp +(begin + (display "The sum of 32 and 10 is: ") + (display 42) + (newline)) +@end lisp + +Let us identify all of the sub-expressions in this expression, +annotating them with unique labels: + +@lisp +(begin + (display "The sum of 32 and 10 is: ") + |k1 k2 + k0 + (display 42) + |k4 k5 + k3 + (newline)) + |k7 + k6 +@end lisp + +Each of these labels identifies a point in a program. One label may be +the continuation of another label. For example, the continuation of +@code{k7} is @code{k6}. This is because after evaluating the value of +@code{newline}, performed by the expression labelled @code{k7}, we +continue to apply it in @code{k6}. + +Which expression has @code{k0} as its continuation? It is either the +expression labelled @code{k1} or the expression labelled @code{k2}. +Scheme does not have a fixed order of evaluation of arguments, though it +does guarantee that they are evaluated in some order. Unlike general +Scheme, continuation-passing style makes evaluation order explicit. In +Guile, this choice is made by the higher-level language compilers. + +Let us assume a left-to-right evaluation order. In that case the +continuation of @code{k1} is @code{k2}, and the continuation of +@code{k2} is @code{k0}. + +With this example established, we are ready to give an example of CPS in +Scheme: + +@smalllisp +(lambda (ktail) + (let ((k1 (lambda () + (let ((k2 (lambda (proc) + (let ((k0 (lambda (arg0) + (proc k4 arg0)))) + (k0 "The sum of 32 and 10 is: "))))) + (k2 display)))) + (k4 (lambda _ + (let ((k5 (lambda (proc) + (let ((k3 (lambda (arg0) + (proc k7 arg0)))) + (k3 42))))) + (k5 display)))) + (k7 (lambda _ + (let ((k6 (lambda (proc) + (proc ktail)))) + (k6 newline))))) + (k1)) +@end smalllisp + +Holy code explosion, Batman! What's with all the lambdas? Indeed, CPS +is by nature much more verbose than ``direct-style'' intermediate +languages like Tree-IL. At the same time, CPS is simpler than full +Scheme, because it makes things more explicit. + +In the original program, the expression labelled @code{k0} is in effect +context. Any values it returns are ignored. In Scheme, this fact is +implicit. In CPS, we can see it explicitly by noting that its +continuation, @code{k4}, takes any number of values and ignores them. +Compare this to @code{k2}, which takes a single value; in this way we +can say that @code{k1} is in a ``value'' context. Likewise @code{k6} is +in tail context with respect to the expression as a whole, because its +continuation is the tail continuation, @code{ktail}. CPS makes these +details manifest, and gives them names. + +@node CPS in Guile +@subsubsection CPS in Guile + +@cindex continuation, CPS +Guile's CPS language is composed of @dfn{continuations}. A continuation +is a labelled program point. If you are used to traditional compilers, +think of a continuation as a trivial basic block. A program is a +``soup'' of continuations, represented as a map from labels to +continuations. + +@cindex term, CPS +@cindex expression, CPS +Like basic blocks, each continuation belongs to only one function. Some +continuations are special, like the continuation corresponding to a +function's entry point, or the continuation that represents the tail of +a function. Others contain a @dfn{term}. A term contains an +@dfn{expression}, which evaluates to zero or more values. The term also +records the continuation to which it will pass its values. Some terms, +like conditional branches, may continue to one of a number of +continuations. + +Continuation labels are small integers. This makes it easy to sort them +and to group them into sets. Whenever a term refers to a continuation, +it does so by name, simply recording the label of the continuation. +Continuation labels are unique among the set of labels in a program. + +Variables are also named by small integers. Variable names are unique +among the set of variables in a program. + +For example, a simple continuation that receives two values and adds +them together can be matched like this, using the @code{match} form from +@code{(ice-9 match)}: + +@smallexample +(match cont + (($ $kargs (x-name y-name) (x-var y-var) + ($ $continue k src ($ $primcall '+ #f (x-var y-var)))) + (format #t "Add ~a and ~a and pass the result to label ~a" + x-var y-var k))) +@end smallexample + +Here we see the most common kind of continuation, @code{$kargs}, which +binds some number of values to variables and then evaluates a term. + +@deftp {CPS Continuation} $kargs names vars term +Bind the incoming values to the variables @var{vars}, with original +names @var{names}, and then evaluate @var{term}. +@end deftp + +The @var{names} of a @code{$kargs} are just for debugging, and will end +up residualized in the object file for use by the debugger. + +The @var{term} in a @code{$kargs} is always a @code{$continue}, which +evaluates an expression and continues to a continuation. + +@deftp {CPS Term} $continue k src exp +Evaluate the expression @var{exp} and pass the resulting values (if any) +to the continuation labelled @var{k}. The source information associated +with the expression may be found in @var{src}, which is either an alist +as in @code{source-properties} or is @code{#f} if there is no associated +source. +@end deftp + +There are a number of expression kinds. Above you see an example of +@code{$primcall}. + +@deftp {CPS Expression} $primcall name param args +Perform the primitive operation identified by @code{name}, a well-known +symbol, passing it the arguments @var{args}, and pass all resulting +values to the continuation. + +@var{param} is a constant parameter whose interpretation is up to the +primcall in question. Usually it's @code{#f} but for a primcall that +might need some compile-time constant information -- such as +@code{add/immediate}, which adds a constant number to a value -- the +parameter holds this information. + +The set of available primitives includes many primitives known to +Tree-IL and then some more; see the source code for details. Note that +some Tree-IL primcalls need to be converted to a sequence of lower-level +CPS primcalls. Again, see @code{(language tree-il compile-cps)} for +full details. +@end deftp + +@cindex dominate, CPS +The variables that are used by @code{$primcall}, or indeed by any +expression, must be defined before the expression is evaluated. An +equivalent way of saying this is that predecessor @code{$kargs} +continuation(s) that bind the variables(s) used by the expression must +@dfn{dominate} the continuation that uses the expression: definitions +dominate uses. This condition is trivially satisfied in our example +above, but in general to determine the set of variables that are in +``scope'' for a given term, you need to do a flow analysis to see what +continuations dominate a term. The variables that are in scope are +those variables defined by the continuations that dominate a term. + +Here is an inventory of the kinds of expressions in Guile's CPS +language, besides @code{$primcall} which has already been described. +Recall that all expressions are wrapped in a @code{$continue} term which +specifies their continuation. + +@deftp {CPS Expression} $const val +Continue with the constant value @var{val}. +@end deftp + +@deftp {CPS Expression} $prim name +Continue with the procedure that implements the primitive operation +named by @var{name}. +@end deftp + +@deftp {CPS Expression} $call proc args +Call @var{proc} with the arguments @var{args}, and pass all values to +the continuation. @var{proc} and the elements of the @var{args} list +should all be variable names. The continuation identified by the term's +@var{k} should be a @code{$kreceive} or a @code{$ktail} instance. +@end deftp + +@deftp {CPS Expression} $values args +Pass the values named by the list @var{args} to the continuation. +@end deftp + +@deftp {CPS Expression} $prompt escape? tag handler +@end deftp + +@cindex higher-order CPS +@cindex CPS, higher-order +@cindex first-order CPS +@cindex CPS, first-order +There are two sub-languages of CPS, @dfn{higher-order CPS} and +@dfn{first-order CPS}. The difference is that in higher-order CPS, +there are @code{$fun} and @code{$rec} expressions that bind functions or +mutually-recursive functions in the implicit scope of their use sites. +Guile transforms higher-order CPS into first-order CPS by @dfn{closure +conversion}, which chooses representations for all closures and which +arranges to access free variables through the implicit closure parameter +that is passed to every function call. + +@deftp {CPS Expression} $fun body +Continue with a procedure. @var{body} names the entry point of the +function, which should be a @code{$kfun}. This expression kind is only +valid in higher-order CPS, which is the CPS language before closure +conversion. +@end deftp + +@deftp {CPS Expression} $rec names vars funs +Continue with a set of mutually recursive procedures denoted by +@var{names}, @var{vars}, and @var{funs}. @var{names} is a list of +symbols, @var{vars} is a list of variable names (unique integers), and +@var{funs} is a list of @code{$fun} values. Note that the @code{$kargs} +continuation should also define @var{names}/@var{vars} bindings. +@end deftp + +The contification pass will attempt to transform the functions declared +in a @code{$rec} into local continuations. Any remaining @code{$fun} +instances are later removed by the closure conversion pass. If the +function has no free variables, it gets allocated as a constant. + +@deftp {CPS Expression} $const-fun label +A constant which is a function whose entry point is @var{label}. As a +constant, instances of @code{$const-fun} with the same @var{label} will +not allocate; the space for the function is allocated as part of the +compilation unit. + +In practice, @code{$const-fun} expressions are reified by CPS-conversion +for functions whose call sites are not all visible within the +compilation unit and which have no free variables. This expression kind +is part of first-order CPS. +@end deftp + +Otherwise, if the closure has free variables, it will be allocated at +its definition site via an @code{allocate-words} primcall and its free +variables initialized there. The code pointer in the closure is +initialized from a @code{$code} expression. + +@deftp {CPS Expression} $code label +Continue with the value of @var{label}, which should denote some +@code{$kfun} continuation in the program. Used when initializing the +code pointer of closure objects. +@end deftp + +However, If the closure can be proven to never escape its scope then +other lighter-weight representations can be chosen. Additionally, if +all call sites are known, closure conversion will hard-wire the calls by +lowering @code{$call} to @code{$callk}. + +@deftp {CPS Expression} $callk label proc args +Like @code{$call}, but for the case where the call target is known to be +in the same compilation unit. @var{label} should denote some +@code{$kfun} continuation in the program. In this case the @var{proc} +is simply an additional argument, since it is not used to determine the +call target at run-time. +@end deftp + +To summarize: a @code{$continue} is a CPS term that continues to a +single label. But there are other kinds of CPS terms that can continue +to a different number of labels: @code{$branch}, @code{$throw}, and +@code{$prompt}. + +@deftp {CPS Term} $branch kf kt src op param args +Evaluate the branching primcall @var{op}, with arguments @var{args} and +constant parameter @var{param}, and continue to @var{kt} with zero +values if the test is true. Otherwise continue to @var{kf}. + +The @code{$branch} term is like a @code{$continue} term with a +@code{$primcall} expression, except that instead of binding a value and +continuing to a single label, the result of the test is not bound but +instead used to choose the continuation label. + +The set of operations (corresponding to @var{op} values) that are valid +in a @var{$branch} is limited. In the general case, bind the result of +a test expression to a variable, and then make a @code{$branch} on a +@code{true?} op referencing that variable. The optimizer should inline +the branch if possible. +@end deftp + +@deftp {CPS Term} $throw src op param args +Throw a non-resumable exception. Throw terms do not continue at all. +The usual value of @var{op} is @code{throw}, with two arguments +@var{key} and @var{args}. There are also some specific primcalls that +compile to the VM @code{throw/value} and @code{throw/value+data} +instructions; see the code for full details. + +The advantage of having @code{$throw} as a term is that, because it does +not continue, this allows the optimizer to gather more information from +type predicates. For example, if the predicate is @code{char?} and the +@var{kf} continues to a throw, the set of labels dominated by @var{kt} +is larger than if the throw notationally continued to some label that +would never be reached by the throw. +@end deftp + +@deftp {CPS Term} $prompt k kh src escape? tag +Push a prompt on the stack identified by the variable name @var{tag}, +which may be escape-only if @var{escape?} is true, and continue to +@var{kh} with zero values. If the body aborts to this prompt, control +will proceed at the continuation labelled @var{kh}, which should be a +@code{$kreceive} continuation. Prompts are later popped by +@code{pop-prompt} primcalls. +@end deftp + +At this point we have described terms, expressions, and the most common +kind of continuation, @code{$kargs}. @code{$kargs} is used when the +predecessors of the continuation can be instructed to pass the values +where the continuation wants them. For example, if a @code{$kargs} +continuation @var{k} binds a variable @var{v}, and the compiler decides +to allocate @var{v} to slot 6, all predecessors of @var{k} should put +the value for @var{v} in slot 6 before jumping to @var{k}. One +situation in which this isn't possible is receiving values from function +calls. Guile has a calling convention for functions which currently +places return values on the stack. A continuation of a call must check +that the number of values returned from a function matches the expected +number of values, and then must shuffle or collect those values to named +variables. @code{$kreceive} denotes this kind of continuation. + +@deftp {CPS Continuation} $kreceive arity k +Receive values on the stack. Parse them according to @var{arity}, and +then proceed with the parsed values to the @code{$kargs} continuation +labelled @var{k}. As a limitation specific to @code{$kreceive}, +@var{arity} may only contain required and rest arguments. +@end deftp + +@code{$arity} is a helper data structure used by @code{$kreceive} and +also by @code{$kclause}, described below. + +@deftp {CPS Data} $arity req opt rest kw allow-other-keys? +A data type declaring an arity. @var{req} and @var{opt} are lists of +source names of required and optional arguments, respectively. +@var{rest} is either the source name of the rest variable, or @code{#f} +if this arity does not accept additional values. @var{kw} is a list of +the form @code{((@var{keyword} @var{name} @var{var}) ...)}, describing +the keyword arguments. @var{allow-other-keys?} is true if other keyword +arguments are allowed and false otherwise. + +Note that all of these names with the exception of the @var{var}s in the +@var{kw} list are source names, not unique variable names. +@end deftp + +Additionally, there are three specific kinds of continuations that are +only used in function entries. + +@deftp {CPS Continuation} $kfun src meta self tail clauses +Declare a function entry. @var{src} is the source information for the +procedure declaration, and @var{meta} is the metadata alist as described +above in Tree-IL's @code{<lambda>}. @var{self} is a variable bound to +the procedure being called, and which may be used for self-references. +@var{tail} is the label of the @code{$ktail} for this function, +corresponding to the function's tail continuation. @var{clause} is the +label of the first @code{$kclause} for the first @code{case-lambda} +clause in the function, or otherwise @code{#f}. +@end deftp + +@deftp {CPS Continuation} $ktail +A tail continuation. +@end deftp + +@deftp {CPS Continuation} $kclause arity cont alternate +A clause of a function with a given arity. Applications of a function +with a compatible set of actual arguments will continue to the +continuation labelled @var{cont}, a @code{$kargs} instance representing +the clause body. If the arguments are incompatible, control proceeds to +@var{alternate}, which is a @code{$kclause} for the next clause, or +@code{#f} if there is no next clause. +@end deftp + +@node Building CPS +@subsubsection Building CPS + +Unlike Tree-IL, the CPS language is built to be constructed and +deconstructed with abstract macros instead of via procedural +constructors or accessors, or instead of S-expression matching. + +Deconstruction and matching is handled adequately by the @code{match} +form from @code{(ice-9 match)}. @xref{Pattern Matching}. Construction +is handled by a set of mutually builder macros: +@code{build-term}, @code{build-cont}, and @code{build-exp}. + +In the following interface definitions, consider @code{term} and +@code{exp} to be built by @code{build-term} or @code{build-exp}, +respectively. Consider any other name to be evaluated as a Scheme +expression. Many of these forms recognize @code{unquote} in some +contexts, to splice in a previously-built value; see the specifications +below for full details. + +@deffn {Scheme Syntax} build-term ,val +@deffnx {Scheme Syntax} build-term ($continue k src exp) +@deffnx {Scheme Syntax} build-exp ,val +@deffnx {Scheme Syntax} build-exp ($const val) +@deffnx {Scheme Syntax} build-exp ($prim name) +@deffnx {Scheme Syntax} build-exp ($fun kentry) +@deffnx {Scheme Syntax} build-exp ($const-fun kentry) +@deffnx {Scheme Syntax} build-exp ($code kentry) +@deffnx {Scheme Syntax} build-exp ($rec names syms funs) +@deffnx {Scheme Syntax} build-exp ($call proc (arg ...)) +@deffnx {Scheme Syntax} build-exp ($call proc args) +@deffnx {Scheme Syntax} build-exp ($callk k proc (arg ...)) +@deffnx {Scheme Syntax} build-exp ($callk k proc args) +@deffnx {Scheme Syntax} build-exp ($primcall name param (arg ...)) +@deffnx {Scheme Syntax} build-exp ($primcall name param args) +@deffnx {Scheme Syntax} build-exp ($values (arg ...)) +@deffnx {Scheme Syntax} build-exp ($values args) +@deffnx {Scheme Syntax} build-exp ($prompt escape? tag handler) +@deffnx {Scheme Syntax} build-term ($branch kf kt src op param (arg ...)) +@deffnx {Scheme Syntax} build-term ($branch kf kt src op param args) +@deffnx {Scheme Syntax} build-term ($throw src op param (arg ...)) +@deffnx {Scheme Syntax} build-term ($throw src op param args) +@deffnx {Scheme Syntax} build-term ($prompt k kh src escape? tag) +@deffnx {Scheme Syntax} build-cont ,val +@deffnx {Scheme Syntax} build-cont ($kargs (name ...) (sym ...) term) +@deffnx {Scheme Syntax} build-cont ($kargs names syms term) +@deffnx {Scheme Syntax} build-cont ($kreceive req rest kargs) +@deffnx {Scheme Syntax} build-cont ($kfun src meta self ktail kclause) +@deffnx {Scheme Syntax} build-cont ($kclause ,arity kbody kalt) +@deffnx {Scheme Syntax} build-cont ($kclause (req opt rest kw aok?) kbody) +Construct a CPS term, expression, or continuation. +@end deffn + +There are a few more miscellaneous interfaces as well. + +@deffn {Scheme Procedure} make-arity req opt rest kw allow-other-keywords? +A procedural constructor for @code{$arity} objects. +@end deffn + +@deffn {Scheme Syntax} rewrite-term val (pat term) ... +@deffnx {Scheme Syntax} rewrite-exp val (pat exp) ... +@deffnx {Scheme Syntax} rewrite-cont val (pat cont) ... +Match @var{val} against the series of patterns @var{pat...}, using +@code{match}. The body of the matching clause should be a template in +the syntax of @code{build-term}, @code{build-exp}, or @code{build-cont}, +respectively. +@end deffn + +@node CPS Soup +@subsubsection CPS Soup + +We describe programs in Guile's CPS language as being a kind of ``soup'' +because all continuations in the program are mixed into the same +``pot'', so to speak, without explicit markers as to what function or +scope a continuation is in. A program in CPS is a map from continuation +labels to continuation values. As discussed in the introduction, a +continuation label is an integer. No label may be negative. + +As a matter of convention, label 0 should map to the @code{$kfun} +continuation of the entry to the program, which should be a function of +no arguments. The body of a function consists of the labelled +continuations that are reachable from the function entry. A program can +refer to other functions, either via @code{$fun} and @code{$rec} in +higher-order CPS, or via @code{$const-fun}, @code{$callk}, and allocated +closures in first-order CPS. The program logically contains all +continuations of all functions reachable from the entry function. A +compiler pass may leave unreachable continuations in a program; +subsequent compiler passes should ensure that their transformations and +analyses only take reachable continuations into account. It's OK though +if transformation runs over all continuations if including the +unreachable continuations has no effect on the transformations on the +live continuations. + +@cindex intmap +The ``soup'' itself is implemented as an @dfn{intmap}, a functional +array-mapped trie specialized for integer keys. Intmaps associate +integers with values of any kind. Currently intmaps are a private data +structure only used by the CPS phase of the compiler. To work with +intmaps, load the @code{(language cps intmap)} module: + +@example +(use-modules (language cps intmap)) +@end example + +Intmaps are functional data structures, so there is no constructor as +such: one can simply start with the empty intmap and add entries to it. + +@example +(intmap? empty-intmap) @result{} #t +(define x (intmap-add empty-intmap 42 "hi")) +(intmap? x) @result{} #t +(intmap-ref x 42) @result{} "hi" +(intmap-ref x 43) @result{} @i{error: 43 not present} +(intmap-ref x 43 (lambda (k) "yo!")) @result{} "yo" +(intmap-add x 42 "hej") @result{} @i{error: 42 already present} +@end example + +@code{intmap-ref} and @code{intmap-add} are the core of the intmap +interface. There is also @code{intmap-replace}, which replaces the +value associated with a given key, requiring that the key was present +already, and @code{intmap-remove}, which removes a key from an intmap. + +Intmaps have a tree-like structure that is well-suited to set operations +such as union and intersection, so there is are also the binary +@code{intmap-union} and @code{intmap-intersect} procedures. If the +result is equivalent to either argument, that argument is returned +as-is; in that way, one can detect whether the set operation produced a +new result simply by checking with @code{eq?}. This makes intmaps +useful when computing fixed points. + +If a key is present in both intmaps and the associated values are not +the same in the sense of @code{eq?}, the resulting value is determined +by a ``meet'' procedure, which is the optional last argument to +@code{intmap-union}, @code{intmap-intersect}, and also to +@code{intmap-add}, @code{intmap-replace}, and similar functions. The +meet procedure will be called with the two values and should return the +intersected or unioned value in some domain-specific way. If no meet +procedure is given, the default meet procedure will raise an error. + +To traverse over the set of values in an intmap, there are the +@code{intmap-next} and @code{intmap-prev} procedures. For example, if +intmap @var{x} has one entry mapping 42 to some value, we would have: + +@example +(intmap-next x) @result{} 42 +(intmap-next x 0) @result{} 42 +(intmap-next x 42) @result{} 42 +(intmap-next x 43) @result{} #f +(intmap-prev x) @result{} 42 +(intmap-prev x 42) @result{} 42 +(intmap-prev x 41) @result{} #f +@end example + +There is also the @code{intmap-fold} procedure, which folds over keys +and values in the intmap from lowest to highest value, and +@code{intmap-fold-right} which does so in the opposite direction. These +procedures may take up to 3 seed values. The number of values that the +fold procedure returns is the number of seed values. + +@example +(define q (intmap-add (intmap-add empty-intmap 1 2) 3 4)) +(intmap-fold acons q '()) @result{} ((3 . 4) (1 . 2)) +(intmap-fold-right acons q '()) @result{} ((1 . 2) (3 . 4)) +@end example + +When an entry in an intmap is updated (removed, added, or changed), a +new intmap is created that shares structure with the original intmap. +This operation ensures that the result of existing computations is not +affected by future computations: no mutation is ever visible to user +code. This is a great property in a compiler data structure, as it lets +us hold a copy of a program before a transformation and use it while we +build a post-transformation program. Updating an intmap is O(log +@var{n}) in the size of the intmap. + +However, the O(log @var{n}) allocation costs are sometimes too much, +especially in cases when we know that we can just update the intmap in +place. As an example, say we have an intmap mapping the integers 1 to +100 to the integers 42 to 141. Let's say that we want to transform this +map by adding 1 to each value. There is already an efficient +@code{intmap-map} procedure in the @code{(language cps utils}) module, +but if we didn't know about that we might do: + +@example +(define (intmap-increment map) + (let lp ((k 0) (map map)) + (let ((k (intmap-next map k))) + (if k + (let ((v (intmap-ref map k))) + (lp (1+ k) (intmap-replace map k (1+ v)))) + map)))) +@end example + +@cindex intmap, transient +@cindex transient intmaps +Observe that the intermediate values created by @code{intmap-replace} +are completely invisible to the program -- only the last result of +@code{intmap-replace} value is needed. The rest might as well share +state with the last one, and we could update in place. Guile allows +this kind of interface via @dfn{transient intmaps}, inspired by +Clojure's transient interface (@uref{http://clojure.org/transients}). + +The in-place @code{intmap-add!} and @code{intmap-replace!} procedures +return transient intmaps. If one of these in-place procedures is called +on a normal persistent intmap, a new transient intmap is created. This +is an O(1) operation. In all other respects the interface is like their +persistent counterparts, @code{intmap-add} and @code{intmap-replace}. +If an in-place procedure is called on a transient intmap, the intmap is +mutated in-place and the same value is returned. + +If a persistent operation like @code{intmap-add} is called on a +transient intmap, the transient's mutable substructure is then marked as +persistent, and @code{intmap-add} then runs on a new persistent intmap +sharing structure but not state with the original transient. Mutating a +transient will cause enough copying to ensure that it can make its +change, but if part of its substructure is already ``owned'' by it, no +more copying is needed. + +We can use transients to make @code{intmap-increment} more efficient. +The two changed elements have been marked @strong{like this}. + +@example +(define (intmap-increment map) + (let lp ((k 0) (map map)) + (let ((k (intmap-next map k))) + (if k + (let ((v (intmap-ref map k))) + (lp (1+ k) (@strong{intmap-replace!} map k (1+ v)))) + (@strong{persistent-intmap} map))))) +@end example + +Be sure to tag the result as persistent using the +@code{persistent-intmap} procedure to prevent the mutability from +leaking to other parts of the program. For added paranoia, you could +call @code{persistent-intmap} on the incoming map, to ensure that if it +were already transient, that the mutations in the body of +@code{intmap-increment} wouldn't affect the incoming value. + +In summary, programs in CPS are intmaps whose values are continuations. +See the source code of @code{(language cps utils)} for a number of +useful facilities for working with CPS values. + +@node Compiling CPS +@subsubsection Compiling CPS + +Compiling CPS in Guile has three phases: conversion, optimization, and +code generation. + +CPS conversion is the process of taking a higher-level language and +compiling it to CPS. Source languages can do this directly, or they can +convert to Tree-IL (which is probably easier) and let Tree-IL convert to +CPS later. Going through Tree-IL has the advantage of running Tree-IL +optimization passes, like partial evaluation. Also, the compiler from +Tree-IL to CPS handles assignment conversion, in which assigned local +variables (in Tree-IL, locals that are @code{<lexical-set>}) are +converted to being boxed values on the heap. @xref{Variables and the +VM}. + +After CPS conversion, Guile runs some optimization passes over the CPS. +Most optimization in Guile is done on the CPS language. The one major +exception is partial evaluation, which for historic reasons is done on +Tree-IL. + +The major optimization performed on CPS is contification, in which +functions that are always called with the same continuation are +incorporated directly into a function's body. This opens up space for +more optimizations, and turns procedure calls into @code{goto}. It can +also make loops out of recursive function nests. Guile also does dead +code elimination, common subexpression elimination, loop peeling and +invariant code motion, and range and type inference. + +The rest of the optimization passes are really cleanups and +canonicalizations. CPS spans the gap between high-level languages and +low-level bytecodes, which allows much of the compilation process to be +expressed as source-to-source transformations. Such is the case for +closure conversion, in which references to variables that are free in a +function are converted to closure references, and in which functions are +converted to closures. There are a few more passes to ensure that the +only primcalls left in the term are those that have a corresponding +instruction in the virtual machine, and that their continuations expect +the right number of values. + +Finally, the backend of the CPS compiler emits bytecode for each +function, one by one. To do so, it determines the set of live variables +at all points in the function. Using this liveness information, it +allocates stack slots to each variable, such that a variable can live in +one slot for the duration of its lifetime, without shuffling. (Of +course, variables with disjoint lifetimes can share a slot.) Finally +the backend emits code, typically just one VM instruction, for each +continuation in the function. + + +@node Bytecode +@subsection Bytecode + +As mentioned before, Guile compiles all code to bytecode, and that +bytecode is contained in ELF images. @xref{Object File Format}, for +more on Guile's use of ELF. + +To produce a bytecode image, Guile provides an assembler and a linker. + +The assembler, defined in the @code{(system vm assembler)} module, has a +relatively straightforward imperative interface. It provides a +@code{make-assembler} function to instantiate an assembler and a set of +@code{emit-@var{inst}} procedures to emit instructions of each kind. + +The @code{emit-@var{inst}} procedures are actually generated at +compile-time from a machine-readable description of the VM. With a few +exceptions for certain operand types, each operand of an emit procedure +corresponds to an operand of the corresponding instruction. + +Consider @code{allocate-words}, from @pxref{Memory Access Instructions}. +It is documented as: + +@deftypefn Instruction {} allocate-words s12:@var{dst} s12:@var{nwords} +@end deftypefn + +Therefore the emit procedure has the form: + +@deffn {Scheme Procedure} emit-allocate-words asm dst nwords +@end deffn + +All emit procedure take the assembler as their first argument, and +return no useful values. + +The argument types depend on the operand types. @xref{Instruction Set}. +Most are integers within a restricted range, though labels are generally +expressed as opaque symbols. Besides the emitters that correspond to +instructions, there are a few additional helpers defined in the +assembler module. + +@deffn {Scheme Procedure} emit-label asm label +Define a label at the current program point. +@end deffn + +@deffn {Scheme Procedure} emit-source asm source +Associate @var{source} with the current program point. +@end deffn + +@deffn {Scheme Procedure} emit-cache-ref asm dst key +@deffnx {Scheme Procedure} emit-cache-set! asm key val +Macro-instructions to implement compilation-unit caches. A single cache +cell corresponding to @var{key} will be allocated for the compilation +unit. +@end deffn + +@deffn {Scheme Procedure} emit-load-constant asm dst constant +Load the Scheme datum @var{constant} into @var{dst}. +@end deffn + +@deffn {Scheme Procedure} emit-begin-program asm label properties +@deffnx {Scheme Procedure} emit-end-program asm +Delimit the bounds of a procedure, with the given @var{label} and the +metadata @var{properties}. +@end deffn + +@deffn {Scheme Procedure} emit-load-static-procedure asm dst label +Load a procedure with the given @var{label} into local @var{dst}. This +macro-instruction should only be used with procedures without free +variables -- procedures that are not closures. +@end deffn + +@deffn {Scheme Procedure} emit-begin-standard-arity asm req nlocals alternate +@deffnx {Scheme Procedure} emit-begin-opt-arity asm req opt rest nlocals alternate +@deffnx {Scheme Procedure} emit-begin-kw-arity asm req opt rest kw-indices allow-other-keys? nlocals alternate +@deffnx {Scheme Procedure} emit-end-arity asm +Delimit a clause of a procedure. +@end deffn + +The linker is a complicated beast. Hackers interested in how it works +would do well do read Ian Lance Taylor's series of articles on linkers. +Searching the internet should find them easily. From the user's +perspective, there is only one knob to control: whether the resulting +image will be written out to a file or not. If the user passes +@code{#:to-file? #t} as part of the compiler options (@pxref{The Scheme +Compiler}), the linker will align the resulting segments on page +boundaries, and otherwise not. + +@deffn {Scheme Procedure} link-assembly asm #:page-aligned?=#t +Link an ELF image, and return the bytevector. If @var{page-aligned?} is +true, Guile will align the segments with different permissions on +page-sized boundaries, in order to maximize code sharing between +different processes. Otherwise, padding is minimized, to minimize +address space consumption. +@end deffn + +To write an image to disk, just use @code{put-bytevector} from +@code{(ice-9 binary-ports)}. + +Compiling object code to the fake language, @code{value}, is performed +via loading objcode into a program, then executing that thunk with +respect to the compilation environment. Normally the environment +propagates through the compiler transparently, but users may specify the +compilation environment manually as well, as a module. Procedures to +load images can be found in the @code{(system vm loader)} module: + +@lisp +(use-modules (system vm loader)) +@end lisp + +@deffn {Scheme Variable} load-thunk-from-file file +@deffnx {C Function} scm_load_thunk_from_file (file) +Load object code from a file named @var{file}. The file will be mapped +into memory via @code{mmap}, so this is a very fast operation. +@end deffn + +@deffn {Scheme Variable} load-thunk-from-memory bv +@deffnx {C Function} scm_load_thunk_from_memory (bv) +Load object code from a bytevector. The data will be copied out of the +bytevector in order to ensure proper alignment of embedded Scheme +values. +@end deffn + +Additionally there are procedures to find the ELF image for a given +pointer, or to list all mapped ELF images: + +@deffn {Scheme Variable} find-mapped-elf-image ptr +Given the integer value @var{ptr}, find and return the ELF image that +contains that pointer, as a bytevector. If no image is found, return +@code{#f}. This routine is mostly used by debuggers and other +introspective tools. +@end deffn + +@deffn {Scheme Variable} all-mapped-elf-images +Return all mapped ELF images, as a list of bytevectors. +@end deffn + + +@node Writing New High-Level Languages +@subsection Writing New High-Level Languages + +In order to integrate a new language @var{lang} into Guile's compiler +system, one has to create the module @code{(language @var{lang} spec)} +containing the language definition and referencing the parser, +compiler and other routines processing it. The module hierarchy in +@code{(language brainfuck)} defines a very basic Brainfuck +implementation meant to serve as easy-to-understand example on how to +do this. See for instance @url{http://en.wikipedia.org/wiki/Brainfuck} +for more information about the Brainfuck language itself. + + +@node Extending the Compiler +@subsection Extending the Compiler + +At this point we take a detour from the impersonal tone of the rest of +the manual. Admit it: if you've read this far into the compiler +internals manual, you are a junkie. Perhaps a course at your university +left you unsated, or perhaps you've always harbored a desire to hack the +holy of computer science holies: a compiler. Well you're in good +company, and in a good position. Guile's compiler needs your help. + +There are many possible avenues for improving Guile's compiler. +Probably the most important improvement, speed-wise, will be some form +of optimized ahead-of-time native compilation with global register +allocation. A first pass could simply extend the compiler to also emit +machine code in addition to bytecode, pre-filling the corresponding JIT +data structures referenced by the @code{instrument-entry} bytecodes. +@xref{Instrumentation Instructions}. + +The compiler also needs help at the top end, enhancing the Scheme that +it knows to also understand R7RS, and adding new high-level compilers. +We have JavaScript and Emacs Lisp mostly complete, but they could use +some love; Lua would be nice as well, but whatever language it is +that strikes your fancy would be welcome too. + +Compilers are for hacking, not for admiring or for complaining about. +Get to it! diff --git a/doc/ref/curried.texi b/doc/ref/curried.texi new file mode 100644 index 000000000..25430b4f0 --- /dev/null +++ b/doc/ref/curried.texi @@ -0,0 +1,56 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2012 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Curried Definitions +@section Curried Definitions + +The macros in this section are provided by +@lisp +(use-modules (ice-9 curried-definitions)) +@end lisp +@noindent +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 +@code{define} so that you can conveniently define procedures that return +procedures, up to any desired depth. + +For example, +@example +(define ((foo x) y) + (list x y)) +@end example +is a convenience form of +@example +(define foo + (lambda (x) + (lambda (y) + (list x y)))) +@end example + +@deffn {Scheme Syntax} define (@dots{} (name args @dots{}) @dots{}) body @dots{} +@deffnx {Scheme Syntax} define* (@dots{} (name args @dots{}) @dots{}) body @dots{} +@deffnx {Scheme Syntax} define-public (@dots{} (name args @dots{}) @dots{}) body @dots{} + +Create a top level variable @var{name} bound to the procedure with +parameter list @var{args}. If @var{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 +@var{args}. This nesting may occur to arbitrary depth. + +@code{define*} is similar but the formal parameter lists take additional +options as described in @ref{lambda* and define*}. For example, +@example +(define* ((foo #:keys (bar 'baz) (quux 'zot)) frotz #:rest rest) + (list bar quux frotz rest)) + +((foo #:quux 'foo) 1 2 3 4 5) +@result{} (baz foo 1 (2 3 4 5)) +@end example + +@code{define-public} is similar to @code{define} but it also adds +@var{name} to the list of exported bindings of the current module. +@end deffn diff --git a/doc/ref/data-rep.texi b/doc/ref/data-rep.texi new file mode 100644 index 000000000..23a1bb4bf --- /dev/null +++ b/doc/ref/data-rep.texi @@ -0,0 +1,663 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010, 2015, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Data Representation +@section 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 @code{pair?} and +@code{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 @code{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:: +@end menu + +@node A Simple Representation +@subsection 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 @code{SCM} is +the name of our universal type, we can write: + +@example +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; +@}; +@end example +with the ellipses replaced with code for the remaining Scheme types. + +This representation is sufficient to implement all of Scheme's +semantics. If @var{x} is an @code{SCM} value: +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{@var{x}->type == integer}. +@item + To find its value, we can write @code{@var{x}->value.integer}. +@item + To test if @var{x} is a vector, we can write @code{@var{x}->type == vector}. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element. +@item + If we know @var{x} is a pair, we can write + @code{@var{x}->value.pair.car} to extract its car. +@end itemize + + +@node Faster Integers +@subsection Faster Integers + +Unfortunately, the above representation has a serious disadvantage. In +order to return an integer, an expression must allocate a @code{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 +@code{malloc}) must be aligned on an eight-byte boundary. (Whether or +not the machine actually requires it, we can write our own allocator for +@code{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: +@itemize @bullet +@item +If the lower three bits of an @code{SCM} value are zero, then the SCM +value is a pointer to a @code{struct value}, and everything proceeds as +before. +@item +Otherwise, the @code{SCM} value represents an integer, whose value +appears in its upper bits. +@end itemize + +Here is C code implementing this convention: +@example +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)) +@end example + +Notice that @code{integer} no longer appears as an element of @code{enum +type}, and the union has lost its @code{integer} member. Instead, we +use the @code{POINTER_P} and @code{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 +@var{x} is an @code{SCM} value): +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{INTEGER_P (@var{x})}. +@item + To find its value, we can write @code{GET_INTEGER (@var{x})}. +@item + To test if @var{x} is a vector, we can write: +@example + @code{POINTER_P (@var{x}) && @var{x}->type == vector} +@end example + Given the new representation, we must make sure @var{x} is truly a + pointer before we dereference it to determine its complete type. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element, as + before. +@item + If we know @var{x} is a pair, we can write + @code{@var{x}->value.pair.car} to extract its car, just as before. +@end itemize + +This representation allows us to operate more efficiently on integers +than the first. For example, if @var{x} and @var{y} are known to be +integers, we can compute their sum as follows: +@example +MAKE_INTEGER (GET_INTEGER (@var{x}) + GET_INTEGER (@var{y})) +@end example +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?) + + +@node Cheaper Pairs +@subsection 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 @code{SCM}-sized words per pair --- one for the type, and two for +the @sc{car} and @sc{cdr}. Is there any way to represent pairs using +only two words? + +Let us refine the convention we established earlier. Let us assert +that: +@itemize @bullet +@item + If the bottom three bits of an @code{SCM} value are @code{#b000}, then + it is a pointer, as before. +@item + If the bottom three bits are @code{#b001}, then the upper bits are an + integer. This is a bit more restrictive than before. +@item + If the bottom two bits are @code{#b010}, then the value, with the bottom + three bits masked out, is the address of a pair. +@end itemize + +Here is the new C code: +@example +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)) +@end example + +Notice that @code{enum type} and @code{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 @code{int} is large +enough to hold a pointer, which isn't generally true. + + +Our list of examples is now as follows: +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{INTEGER_P + (@var{x})}; this is as before. +@item + To find its value, we can write @code{GET_INTEGER (@var{x})}, as + before. +@item + To test if @var{x} is a vector, we can write: +@example + @code{POINTER_P (@var{x}) && @var{x}->type == vector} +@end example + We must still make sure that @var{x} is a pointer to a @code{struct + value} before dereferencing it to find its type. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element, as + before. +@item + We can write @code{PAIR_P (@var{x})} to determine if @var{x} is a + pair, and then write @code{GET_PAIR (@var{x})->car} to refer to its + car. +@end itemize + +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 @code{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 @code{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. + + +@node Conservative GC +@subsection 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 @dfn{mark} phase, in which +the set of live objects is enumerated, and a @dfn{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 @dfn{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 +@dfn{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 @emph{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 +@uref{http://www.hboehm.info/gc/}, for more information on conservative +GC in general and the BDW-GC implementation in particular. + +@node The SCM Type in Guile +@subsection The SCM Type in Guile + +Guile classifies Scheme objects into two kinds: those that fit entirely +within an @code{SCM}, and those that require heap storage. + +The former class are called @dfn{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, @dfn{non-immediates}. +They include pairs, procedures, strings, vectors, and all other data +types in Guile. For non-immediates, the @code{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 @code{SCM} type is actually represented +and used at the C level. Interested readers should see +@code{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: @code{SCM} and @code{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:: +@end menu + + +@node Relationship Between SCM and scm_t_bits +@subsubsection Relationship Between @code{SCM} and @code{scm_t_bits} + +A variable of type @code{SCM} is guaranteed to hold a valid Scheme +object. A variable of type @code{scm_t_bits}, on the other hand, may +hold a representation of a @code{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 @var{x} of type @code{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 @code{SCM} +variable has to be transformed into the corresponding representation as +a @code{scm_t_bits} variable @var{y} by using the @code{SCM_UNPACK} +macro. Once this has been done, the type of the scheme object @var{x} +can be derived from the content of the bits of the @code{scm_t_bits} +value @var{y}, in the way illustrated by the example earlier in this +chapter (@pxref{Cheaper Pairs}). Conversely, a valid bit encoding of a +Scheme value as a @code{scm_t_bits} variable can be transformed into the +corresponding @code{SCM} value using the @code{SCM_PACK} macro. + +@node Immediate Objects +@subsubsection 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 +@dfn{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: + +@deftypefn Macro int SCM_IMP (SCM @var{x}) +A Scheme object is an immediate if it fulfills the @code{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. +@end deftypefn + +@noindent +Summary: +@itemize @bullet +@item +Given a Scheme object @var{x} of unknown type, check first +with @code{SCM_IMP (@var{x})} if it is an immediate object. +@item +If so, all of the type and value information can be determined from the +@code{scm_t_bits} value that is delivered by @code{SCM_UNPACK +(@var{x})}. +@end itemize + +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: + +@deftypefn Macro SCM SCM_EOL +The Scheme empty list object, or ``End Of List'' object, usually written +in Scheme as @code{'()}. +@end deftypefn + +@deftypefn Macro SCM SCM_EOF_VAL +The Scheme end-of-file value. It has no standard written +representation, for obvious reasons. +@end deftypefn + +@deftypefn 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. +@end deftypefn + +@deftypefn 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 +@code{SCM_UNDEFINED} for any arguments you did not receive. + +We also use this to mark unbound variables. +@end deftypefn + +@deftypefn Macro int SCM_UNBNDP (SCM @var{x}) +Return true if @var{x} is @code{SCM_UNDEFINED}. Note that this is not a +check to see if @var{x} is @code{SCM_UNBOUND}. History will not be kind +to us. +@end deftypefn + + +@node Non-Immediate Objects +@subsubsection Non-Immediate Objects + +A Scheme object of type @code{SCM} that does not fulfill the +@code{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 +@code{SCM_UNPACK_POINTER} macro. The encoding of a pointer to a heap +object into a @code{SCM} value is done using the @code{SCM_PACK_POINTER} +macro. + +@cindex cells, deprecated concept +Before Guile 2.0, Guile had a custom garbage collector that allocated +heap objects in units of 2-word @dfn{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. + +@deftypefn Macro {scm_t_bits *} SCM_UNPACK_POINTER (SCM @var{x}) +@deftypefnx Macro {scm_t_cell *} SCM2PTR (SCM @var{x}) +Extract and return the heap object pointer from a non-immediate +@code{SCM} object @var{x}. The name @code{SCM2PTR} is deprecated but +still common. +@end deftypefn + +@deftypefn Macro SCM_PACK_POINTER (scm_t_bits * @var{x}) +@deftypefnx Macro SCM PTR2SCM (scm_t_cell * @var{x}) +Return a @code{SCM} value that encodes a reference to the heap object +pointer @var{x}. The name @code{PTR2SCM} is deprecated but still +common. +@end deftypefn + +Note that it is also possible to transform a non-immediate @code{SCM} +value by using @code{SCM_UNPACK} into a @code{scm_t_bits} variable. +However, the result of @code{SCM_UNPACK} may not be used as a pointer to +a heap object: only @code{SCM_UNPACK_POINTER} is guaranteed to transform +a @code{SCM} object into a valid pointer to a heap object. Also, it is +not allowed to apply @code{SCM_PACK_POINTER} to anything that is not a +valid pointer to a heap object. + +@noindent +Summary: +@itemize @bullet +@item +Only use @code{SCM_UNPACK_POINTER} on @code{SCM} values for which +@code{SCM_IMP} is false! +@item +Don't use @code{(scm_t_cell *) SCM_UNPACK (@var{x})}! Use +@code{SCM_UNPACK_POINTER (@var{x})} instead! +@item +Don't use @code{SCM_PACK_POINTER} for anything but a heap object pointer! +@end itemize + +@node Allocating Heap Objects +@subsubsection Allocating Heap Objects + +Heap objects are heap-allocated data pointed to by non-immediate +@code{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 +@code{<libguile/scm.h>}. + +If you just want to allocate pairs, use @code{scm_cons}. + +@deftypefn Function SCM scm_words (scm_t_bits word_0, uint32_t n_words) +Allocate a new heap object containing @var{n_words}, and initialize the +first slot to @var{word_0}, and return a non-immediate @code{SCM} value +encoding a pointer to the object. Typically @var{word_0} will contain +the type tag. +@end deftypefn + +There are also deprecated but common variants of @code{scm_words} that +use the term ``cell'' to indicate 2-word objects. + +@deftypefn 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 +@var{word_0} and @var{word_1}, and return it. Just like calling +@code{scm_words (@var{word_0}, 2)}, then initializing the second slot to +@var{word_1}. + +Note that @var{word_0} and @var{word_1} are of type @code{scm_t_bits}. +If you want to pass a @code{SCM} object, you need to use +@code{SCM_UNPACK}. +@end deftypefn + +@deftypefn 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 @code{scm_cell}, but allocates a 4-word heap object. +@end deftypefn + +@node Heap Object Type Information +@subsubsection 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. + +@deftypefn Macro scm_t_bits SCM_CELL_TYPE (SCM @var{x}) +Extract the first word of the heap object pointed to by @var{x}. This +value holds the information about the cell type. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_TYPE (SCM @var{x}, scm_t_bits @var{t}) +For a non-immediate Scheme object @var{x}, write the value @var{t} into +the first word of the heap object referenced by @var{x}. The value +@var{t} must hold a valid cell type. +@end deftypefn + + +@node Accessing Heap Object Fields +@subsubsection Accessing Heap Object Fields + +For a non-immediate Scheme object @var{x}, the object type can be +determined by using the @code{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. + +@deftypefn Macro scm_t_bits SCM_CELL_WORD (SCM @var{x}, unsigned int @var{n}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_0 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_1 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_2 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_3 (@var{x}) +Deliver the field @var{n} of the heap object referenced by the +non-immediate Scheme object @var{x} as raw untagged data. Only use this +macro for fields containing untagged data; don't use it for fields +containing tagged @code{SCM} objects. +@end deftypefn + +@deftypefn Macro SCM SCM_CELL_OBJECT (SCM @var{x}, unsigned int @var{n}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_0 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_1 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_2 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_3 (SCM @var{x}) +Deliver the field @var{n} of the heap object referenced by the +non-immediate Scheme object @var{x} as a Scheme object. Only use this +macro for fields containing tagged @code{SCM} objects; don't use it for +fields containing untagged data. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_WORD (SCM @var{x}, unsigned int @var{n}, scm_t_bits @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_0 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_1 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_2 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_3 (@var{x}, @var{w}) +Write the raw value @var{w} into field number @var{n} of the heap object +referenced by the non-immediate Scheme value @var{x}. Values that are +written into heap objects as raw values should only be read later using +the @code{SCM_CELL_WORD} macros. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_OBJECT (SCM @var{x}, unsigned int @var{n}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_0 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_1 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_2 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_3 (SCM @var{x}, SCM @var{o}) +Write the Scheme object @var{o} into field number @var{n} of the heap +object referenced by the non-immediate Scheme value @var{x}. Values +that are written into heap objects as objects should only be read using +the @code{SCM_CELL_OBJECT} macros. +@end deftypefn + +@noindent +Summary: +@itemize @bullet +@item +For a non-immediate Scheme object @var{x} of unknown type, get the type +information by using @code{SCM_CELL_TYPE (@var{x})}. +@item +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. +@item +Note that field 0 stores the cell type information. Generally speaking, +other data associated with a heap object is stored starting from field +1. +@end itemize + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/effective-version.texi.in b/doc/ref/effective-version.texi.in new file mode 100644 index 000000000..80b56b751 --- /dev/null +++ b/doc/ref/effective-version.texi.in @@ -0,0 +1 @@ +@set EFFECTIVE-VERSION @GUILE_EFFECTIVE_VERSION@ diff --git a/doc/ref/expect.texi b/doc/ref/expect.texi new file mode 100644 index 000000000..140fd477e --- /dev/null +++ b/doc/ref/expect.texi @@ -0,0 +1,147 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Expect +@section Expect + +The macros in this section are made available with: + +@lisp +(use-modules (ice-9 expect)) +@end lisp + +@code{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 @code{expect} macro +is described below; @code{expect-strings} is a front-end to @code{expect} +based on regexec (see the regular expression documentation). + +@defmac expect-strings clause @dots{} +By default, @code{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: + +@lisp +(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"))))) +@end lisp + +The regular expression is compiled with the @code{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 @code{=>} can be used to indicate that the expression is a +procedure which will accept the result of a successful regular expression +match. E.g., + +@lisp +("^daemon" => write) +("^d(aemon)" => (lambda args (for-each write args))) +("^da(em)on" => (lambda (all sub) + (write all) (newline) + (write sub) (newline))) +@end lisp + +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 behaviour +of @code{expect} (and @code{expect-strings}). +Most have default top-level bindings to the value @code{#f}, +which produces the default behaviour. +They can be redefined at the +top level or locally bound in a form enclosing the expect expression. + +@table @code +@item expect-port +A port to read characters from, instead of the current input port. +@item expect-timeout +@code{expect} will terminate after this number of +seconds, returning @code{#f} or the value returned by expect-timeout-proc. +@item expect-timeout-proc +A procedure called if timeout occurs. The procedure takes a single argument: +the accumulated string. +@item 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. +@item 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. +@item expect-strings-compile-flags +Flags to be used when compiling a regular expression, which are passed +to @code{make-regexp} @xref{Regexp Functions}. The default value +is @code{regexp/newline}. +@item expect-strings-exec-flags +Flags to be used when executing a regular expression, which are +passed to regexp-exec @xref{Regexp Functions}. +The default value is @code{regexp/noteol}, which prevents @code{$} +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. +@end table + +Here's an example using all of the variables: + +@smalllisp +(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")))) +@end smalllisp +@end defmac + +@defmac expect clause @dots{} +@code{expect} is used in the same way as @code{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 @code{#f}, but if end-of-file is reached, the procedures +are called an additional time with the final accumulated string and +@code{#t}. + +The test is successful if the procedure returns a non-false value. + +If the @code{=>} 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: + +@lisp +(let ((expect-port (open-input-file "/etc/passwd"))) + (expect + ((lambda (s eof?) (string=? s "fnord!")) + (display "Got a nobody user!\n")))) +@end lisp + +The control variables described for @code{expect-strings} also +influence the behaviour of @code{expect}, with the exception of +variables whose names begin with @code{expect-strings-}. +@end defmac diff --git a/doc/ref/fdl.texi b/doc/ref/fdl.texi new file mode 100644 index 000000000..8805f1a47 --- /dev/null +++ b/doc/ref/fdl.texi @@ -0,0 +1,506 @@ +@c The GNU Free Documentation License. +@center Version 1.3, 3 November 2008 + +@c This file is intended to be included within another document, +@c hence no sectioning command or @node. + +@display +Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. +@uref{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +@sc{ascii} without markup, Texinfo input format, La@TeX{} input +format, @acronym{SGML} or @acronym{XML} using a publicly available +@acronym{DTD}, and standard-conforming simple @acronym{HTML}, +PostScript or @acronym{PDF} designed for human modification. Examples +of transparent image formats include @acronym{PNG}, @acronym{XCF} and +@acronym{JPG}. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, @acronym{SGML} or +@acronym{XML} for which the @acronym{DTD} and/or processing tools are +not generally available, and the machine-generated @acronym{HTML}, +PostScript or @acronym{PDF} produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The ``publisher'' means any person or entity that distributes copies +of the Document to the public. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +@item +RELICENSING + +``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the +site means any set of copyrightable works thus published on the MMC +site. + +``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +``Incorporate'' means to publish or republish a Document, in whole or +in part, as part of another Document. + +An MMC is ``eligible for relicensing'' if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole +or in part into the MMC, (1) had no cover texts or invariant sections, +and (2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + +@end enumerate + +@page +@heading ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + 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''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with@dots{}Texts.'' line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: + diff --git a/doc/ref/gds.dia b/doc/ref/gds.dia Binary files differnew file mode 100644 index 000000000..b134d0438 --- /dev/null +++ b/doc/ref/gds.dia diff --git a/doc/ref/gds.eps b/doc/ref/gds.eps new file mode 100644 index 000000000..e37b6a47e --- /dev/null +++ b/doc/ref/gds.eps @@ -0,0 +1,449 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: /home/bjg/guile/doc/ref/gds.dia +%%Creator: Dia v0.95-1 +%%CreationDate: Tue Dec 8 14:11:12 2009 +%%For: bjg +%%Orientation: Portrait +%%Magnification: 1.0000 +%%BoundingBox: 0 0 949 421 +%%BeginSetup +%%EndSetup +%%EndComments +%%BeginProlog +[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright +/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E +/F /G /H /I /J /K /L /M /N /O +/P /Q /R /S /T /U /V /W /X /Y +/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c +/d /e /f /g /h /i /j /k /l /m +/n /o /p /q /r /s /t /u /v /w +/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright +/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior +/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf +/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla +/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde +/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex +/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring +/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis +/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave +/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def +/cp {closepath} bind def +/c {curveto} bind def +/f {fill} bind def +/a {arc} bind def +/ef {eofill} bind def +/ex {exch} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth pop} bind def +/tr {translate} bind def + +/ellipsedict 8 dict def +ellipsedict /mtrx matrix put +/ellipse +{ ellipsedict begin + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def /savematrix mtrx currentmatrix def + x y tr xrad yrad sc + 0 0 1 startangle endangle arc + savematrix setmatrix + end +} def + +/mergeprocs { +dup length +3 -1 roll +dup +length +dup +5 1 roll +3 -1 roll +add +array cvx +dup +3 -1 roll +0 exch +putinterval +dup +4 2 roll +putinterval +} bind def +/Times-Roman-latin1 + /Times-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-Italic-latin1 + /Times-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-Bold-latin1 + /Times-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-BoldItalic-latin1 + /Times-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-Book-latin1 + /AvantGarde-Book findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-BookOblique-latin1 + /AvantGarde-BookOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-Demi-latin1 + /AvantGarde-Demi findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-DemiOblique-latin1 + /AvantGarde-DemiOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-Light-latin1 + /Bookman-Light findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-LightItalic-latin1 + /Bookman-LightItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-Demi-latin1 + /Bookman-Demi findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-DemiItalic-latin1 + /Bookman-DemiItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-latin1 + /Courier findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-Oblique-latin1 + /Courier-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-Bold-latin1 + /Courier-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-BoldOblique-latin1 + /Courier-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-latin1 + /Helvetica findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Oblique-latin1 + /Helvetica-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Bold-latin1 + /Helvetica-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-BoldOblique-latin1 + /Helvetica-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-latin1 + /Helvetica-Narrow findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-Oblique-latin1 + /Helvetica-Narrow-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-Bold-latin1 + /Helvetica-Narrow-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-BoldOblique-latin1 + /Helvetica-Narrow-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Roman-latin1 + /NewCenturySchoolbook-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Italic-latin1 + /NewCenturySchoolbook-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Bold-latin1 + /NewCenturySchoolbook-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-BoldItalic-latin1 + /NewCenturySchoolbook-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Roman-latin1 + /Palatino-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Italic-latin1 + /Palatino-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Bold-latin1 + /Palatino-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-BoldItalic-latin1 + /Palatino-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Symbol-latin1 + /Symbol findfont +definefont pop +/ZapfChancery-MediumItalic-latin1 + /ZapfChancery-MediumItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/ZapfDingbats-latin1 + /ZapfDingbats findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +28.346000 -28.346000 scale +-0.061670 -17.866043 translate +%%EndProlog + + +0.010000 slw +[] 0 sd +[] 0 sd +0 slj +1.000000 1.000000 1.000000 srgb +n 0.061670 3.016800 m 33.507821 3.016800 l s +n 0.061670 17.866043 m 33.507821 17.866043 l s +n 0.061670 3.016800 0.000000 0.000000 180.000000 270.000000 ellipse s +n 33.507821 3.016800 0.000000 0.000000 270.000000 360.000000 ellipse s +n 0.061670 3.016800 m 0.061670 17.866043 l s +n 33.507821 3.016800 m 33.507821 17.866043 l s +n 0.061670 17.866043 0.000000 0.000000 90.000000 180.000000 ellipse s +n 33.507821 17.866043 0.000000 0.000000 0.000000 90.000000 ellipse s +n 2.176250 4.300000 m 2.176250 9.100000 l 9.400000 9.100000 l 9.400000 4.300000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 2.176250 4.300000 m 2.176250 9.100000 l 9.400000 9.100000 l 9.400000 4.300000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(Program #1) dup sw 2 div 5.788125 ex sub 6.050000 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 3.425000 6.650000 m 3.425000 8.550000 l 7.975000 8.550000 l 7.975000 6.650000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 3.425000 6.650000 m 3.425000 8.550000 l 7.975000 8.550000 l 7.975000 6.650000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(GDS Client) dup sw 2 div 5.700000 ex sub 7.750000 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 2.400000 11.600000 m 2.400000 17.050000 l 9.550000 17.050000 l 9.550000 11.600000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 2.400000 11.600000 m 2.400000 17.050000 l 9.550000 17.050000 l 9.550000 11.600000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(Program #2) dup sw 2 div 5.975000 ex sub 13.275000 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 3.750000 14.250000 m 3.750000 16.150000 l 8.550000 16.150000 l 8.550000 14.250000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 3.750000 14.250000 m 3.750000 16.150000 l 8.550000 16.150000 l 8.550000 14.250000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(GDS Client) dup sw 2 div 6.150000 ex sub 15.350000 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 16.175000 8.575000 m 16.175000 11.275000 l 20.975000 11.275000 l 20.975000 8.575000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 16.175000 8.575000 m 16.175000 11.275000 l 20.975000 11.275000 l 20.975000 8.575000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(GDS Server) dup sw 2 div 18.575000 ex sub 10.075000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +[] 0 sd +0 slc +n 8.550000 15.200000 m 16.175000 9.925000 l s +0.100000 slw +[] 0 sd +[] 0 sd +0 slc +n 7.975000 7.600000 m 16.175000 9.925000 l s +/Helvetica-latin1 ff 0.560000 scf sf +(TCP) 11.350000 12.300000 m gs 1 -1 sc sh gr +/Helvetica-latin1 ff 0.560000 scf sf +(TCP) 11.400000 8.150000 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 22.850100 6.025000 m 22.850100 12.000000 l 30.900100 12.000000 l 30.900100 6.025000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 22.850100 6.025000 m 22.850100 12.000000 l 30.900100 12.000000 l 30.900100 6.025000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(Emacs) dup sw 2 div 26.875100 ex sub 7.162500 m gs 1 -1 sc sh gr +1.000000 1.000000 1.000000 srgb +n 23.935100 8.850000 m 23.935100 10.900000 l 29.500100 10.900000 l 29.500100 8.850000 l f +0.100000 slw +[] 0 sd +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 23.935100 8.850000 m 23.935100 10.900000 l 29.500100 10.900000 l 29.500100 8.850000 l cp s +/Helvetica-latin1 ff 0.560000 scf sf +(GDS Interface) dup sw 2 div 26.717600 ex sub 10.025000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +[] 0 sd +0 slc +n 20.975000 9.925000 m 23.935100 9.875000 l s +showpage diff --git a/doc/ref/gds.pdf b/doc/ref/gds.pdf Binary files differnew file mode 100644 index 000000000..9af4ab2d9 --- /dev/null +++ b/doc/ref/gds.pdf diff --git a/doc/ref/gds.txt b/doc/ref/gds.txt new file mode 100644 index 000000000..4e32ecb0c --- /dev/null +++ b/doc/ref/gds.txt @@ -0,0 +1,17 @@ ++----------------+ +| Program #1 | +| | +| +------------+ | +| | GDS Client |-_ +| +------------+ |-_ +-------------------+ ++----------------+ -_TCP | Emacs | + -_ | | + -_+------------+ | +---------------+ | + _| GDS Server |-----| GDS Interface | | ++----------------+ _- +------------+ | +---------------+ | +| Program #2 | _- +-------------------+ +| | _- TCP +| +------------+ _- +| | GDS Client |-| +| +------------+ | ++----------------+ diff --git a/doc/ref/goops-tutorial.texi b/doc/ref/goops-tutorial.texi new file mode 100644 index 000000000..d2cf6404a --- /dev/null +++ b/doc/ref/goops-tutorial.texi @@ -0,0 +1,31 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008, 2009 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@c Original attribution: + +@c +@c STk Reference manual (Appendix: An Introduction to STklos) +@c +@c Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr> +@c Permission to use, copy, modify, distribute,and license this +@c software and its documentation for any purpose is hereby granted, +@c provided that existing copyright notices are retained in all +@c copies and that this notice is included verbatim in any +@c distributions. No written agreement, license, or royalty fee is +@c required for any of the authorized uses. +@c This software is provided ``AS IS'' without express or implied +@c warranty. +@c + +@c Adapted for use in Guile with the authors permission + +@c @macro goops @c was {\stklos} +@c GOOPS +@c @end macro + +@c @macro guile @c was {\stk} +@c Guile +@c @end macro diff --git a/doc/ref/goops.texi b/doc/ref/goops.texi new file mode 100644 index 000000000..91902e492 --- /dev/null +++ b/doc/ref/goops.texi @@ -0,0 +1,2985 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008, 2009, 2011, 2017 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@macro goops +GOOPS +@end macro + +@macro guile +Guile +@end macro + +@node GOOPS +@chapter GOOPS + +@goops{} is the object oriented extension to @guile{}. Its +implementation is derived from @w{STk-3.99.3} by Erick Gallesio and +version 1.3 of Gregor Kiczales' @cite{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 @code{(oop goops)} +module. You can do this at the Guile REPL by evaluating: + +@lisp +(use-modules (oop goops)) +@end lisp +@findex (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:: +@end menu + +@node Copyright Notice +@section 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. + + +@node Class Definition +@section Class Definition + +A new class is defined with the @code{define-class} syntax: + +@findex define-class +@cindex class +@lisp +(define-class @var{class} (@var{superclass} @dots{}) + @var{slot-description} @dots{} + @var{class-option} @dots{}) +@end lisp + +@var{class} is the class being defined. The list of @var{superclass}es +specifies which existing classes, if any, to inherit slots and +properties from. @dfn{Slots} hold per-instance@footnote{Usually --- but +see also the @code{#:allocation} slot option.} data, for instances of +that class --- like ``fields'' or ``member variables'' in other object +oriented systems. Each @var{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. +@cindex slot + +@deffn syntax define-class name (super @dots{}) @ + slot-definition @dots{} class-option @dots{} +Define a class called @var{name} that inherits from @var{super}s, with +direct slots defined by @var{slot-definition}s and @var{class-option}s. +The newly created class is bound to the variable name @var{name} in the +current environment. + +Each @var{slot-definition} is either a symbol that names the slot or a +list, + +@example +(@var{slot-name-symbol} . @var{slot-options}) +@end example + +where @var{slot-name-symbol} is a symbol and @var{slot-options} is a +list with an even number of elements. The even-numbered elements of +@var{slot-options} (counting from zero) are slot option keywords; the +odd-numbered elements are the corresponding values for those keywords. + +Each @var{class-option} is an option keyword and corresponding value. +@end deffn + +As an example, let us define a type for representing a complex number +in terms of two real numbers.@footnote{Of course Guile already +provides complex numbers, and @code{<complex>} is in fact a predefined +class in GOOPS; but the definition here is still useful as an +example.} This can be done with the following class definition: + +@lisp +(define-class <my-complex> (<number>) + r i) +@end lisp + +This binds the variable @code{<my-complex>} to a new class whose +instances will contain two slots. These slots are called @code{r} and +@code{i} and will hold the real and imaginary parts of a complex +number. Note that this class inherits from @code{<number>}, which is a +predefined class.@footnote{@code{<number>} is the direct superclass of +the predefined class @code{<complex>}; @code{<complex>} is the +superclass of @code{<real>}, and @code{<real>} is the superclass of +@code{<integer>}.} + +Slot options are described in the next section. The possible class +options are as follows. + +@deffn {class option} #:metaclass metaclass +The @code{#:metaclass} class option specifies the metaclass of the class +being defined. @var{metaclass} must be a class that inherits from +@code{<class>}. For the use of metaclasses, see @ref{Metaobjects and +the Metaobject Protocol} and @ref{Metaclasses}. + +If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a +metaclass for the new class by calling @code{ensure-metaclass} +(@pxref{Class Definition Protocol,, ensure-metaclass}). +@end deffn + +@deffn {class option} #:name name +The @code{#: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 @code{#:name} option is absent, GOOPS uses the first argument to +@code{define-class} as the class name. +@end deffn + + +@node Instance Creation +@section Instance Creation and Slot Access + +An instance (or object) of a defined class can be created with +@code{make}. @code{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 + +@findex make +@cindex instance +@lisp +(define c (make <my-complex>)) +@end lisp + +@noindent +creates a new @code{<my-complex>} object and binds it to the Scheme +variable @code{c}. + +@deffn generic make +@deffnx method make (class <class>) initarg @dots{} +Create and return a new instance of class @var{class}, initialized using +@var{initarg} @enddots{}. + +In theory, @var{initarg} @dots{} can have any structure that is +understood by whatever methods get applied when the @code{initialize} +generic function is applied to the newly allocated instance. + +In practice, specialized @code{initialize} methods would normally call +@code{(next-method)}, and so eventually the standard GOOPS +@code{initialize} methods are applied. These methods expect +@var{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 @code{#:init-keyword} option (@pxref{Slot +Options,, init-keyword}). Other keyword value pairs can only be +processed by an @code{initialize} method that is specialized for the new +instance's class. Any unprocessed keyword value pairs are ignored. +@end deffn + +@deffn generic make-instance +@deffnx method make-instance (class <class>) initarg @dots{} +@code{make-instance} is an alias for @code{make}. +@end deffn + +The slots of the new complex number can be accessed using +@code{slot-ref} and @code{slot-set!}. @code{slot-set!} sets the value +of an object slot and @code{slot-ref} retrieves it. + +@findex slot-set! +@findex slot-ref +@lisp +@group +(slot-set! c 'r 10) +(slot-set! c 'i 3) +(slot-ref c 'r) @result{} 10 +(slot-ref c 'i) @result{} 3 +@end group +@end lisp + +The @code{(oop goops describe)} module provides a @code{describe} +function that is useful for seeing all the slots of an object; it prints +the slots and their values to standard output. + +@lisp +(describe c) +@print{} +#<<my-complex> 401d8638> is an instance of class <my-complex> +Slots are: + r = 10 + i = 3 +@end lisp + + +@node Slot Options +@section Slot Options + +When specifying a slot (in a @code{(define-class @dots{})} 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. + +@deffn {slot option} #:init-value init-value +@deffnx {slot option} #:init-form init-form +@deffnx {slot option} #:init-thunk init-thunk +@deffnx {slot option} #:init-keyword init-keyword +These options provide various ways to specify how to initialize the +slot's value at instance creation time. +@cindex default slot value + +@var{init-value} specifies a fixed initial slot value (shared across all +new instances of the class). + +@var{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. + +@var{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 @code{define-class} expression. + +@var{init-keyword} specifies a keyword that can be used to pass an +initial slot value to @code{make} when creating a new instance. + +Note that, since an @code{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 +@code{init-thunk} or @code{init-form} instead. Consider the following +example. + +@example +(define-class <chbouib> () + (hashtab #:init-value (make-hash-table))) +@end example + +@noindent +Here only one hash table is created and all instances of +@code{<chbouib>} have their @code{hashtab} slot refer to it. In order +to have each instance of @code{<chbouib>} refer to a new hash table, you +should instead write: + +@example +(define-class <chbouib> () + (hashtab #:init-thunk make-hash-table)) +@end example + +@noindent +or: + +@example +(define-class <chbouib> () + (hashtab #:init-form (make-hash-table))) +@end example + +If more than one of these options is specified for the same slot, the +order of precedence, highest first is + +@itemize @bullet +@item +@code{#:init-keyword}, if @var{init-keyword} is present in the options +passed to @code{make} + +@item +@code{#:init-thunk}, @code{#:init-form} or @code{#:init-value}. +@end itemize + +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 @code{initialize}, whose +signature is + +@example +(define-method (initialize (object <object>) initargs) ...) +@end example + +The initialization of instances of any given class can be customized by +defining a @code{initialize} method that is specialized for that class, +and the author of the specialized method may decide to call +@code{next-method} - which will result in a call to the next less +specialized @code{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. +@end deffn + +@deffn {slot option} #:getter getter +@deffnx {slot option} #:setter setter +@deffnx {slot option} #:accessor accessor +Given an object @var{obj} with slots named @code{foo} and @code{bar}, it +is always possible to read and write those slots by calling +@code{slot-ref} and @code{slot-set!} with the relevant slot name; for +example: + +@example +(slot-ref @var{obj} 'foo) +(slot-set! @var{obj} 'bar 25) +@end example + +The @code{#:getter}, @code{#:setter} and @code{#: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. +@var{getter} specifies a generic function to which GOOPS will add a +method for getting the slot value. @var{setter} specifies a generic +function to which GOOPS will add a method for setting the slot value. +@var{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: + +@example +(c #:getter get-count #:setter set-count #:accessor count) +@end example + +GOOPS defines generic function methods such that the slot value can be +referenced using either the getter or the accessor - + +@example +(let ((current-count (get-count obj))) @dots{}) +(let ((current-count (count obj))) @dots{}) +@end example + +- and set using either the setter or the accessor - + +@example +(set-count obj (+ 1 current-count)) +(set! (count obj) (+ 1 current-count)) +@end example + +Note that + +@itemize @bullet +@item +with an accessor, the slot value is set using the generalized +@code{set!} syntax + +@item +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 +@code{#:getter}, @code{#:setter} and @code{#:accessor} options +respectively. +@end itemize + +The binding of the specified names is done in the environment of the +@code{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 @code{define-class} expression is +evaluated. For more detail, see @ref{Generic Function Internals,, +ensure-generic}. +@end deffn + +@deffn {slot option} #:allocation allocation +The @code{#:allocation} option tells GOOPS how to allocate storage for +the slot. Possible values for @var{allocation} are + +@itemize @bullet +@item @code{#:instance} + +@findex #: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. + +@item @code{#:class} + +@findex #: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 @var{C} with allocation @code{#:class} is shared +by all @var{instance}s for which @code{(is-a? @var{instance} @var{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. + +@item @code{#:each-subclass} + +@findex #:each-subclass +Indicates that GOOPS should create storage for this slot that is shared +by all @emph{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 @emph{direct} +instances of the subclass. In other words, a slot with allocation +@code{#:each-subclass} is shared by all instances with the same +@code{class-of}. + +@item @code{#:virtual} + +@findex #:slot-set! +@findex #:slot-ref +@findex #:virtual +Indicates that GOOPS should not allocate storage for this slot. The +slot definition must also include the @code{#:slot-ref} and +@code{#:slot-set!} options to specify how to reference and set the value +for this slot. See the example below. +@end itemize + +Slot allocation options are processed when defining a new class by the +generic function @code{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 +@code{compute-get-n-set} that is specialized for the new metaclass. For +an example of how to do this, see @ref{Customizing Class Definition}. +@end deffn + +@deffn {slot option} #:slot-ref getter +@deffnx {slot option} #:slot-set! setter +The @code{#:slot-ref} and @code{#:slot-set!} options must be specified +if the slot allocation is @code{#:virtual}, and are ignored otherwise. + +@var{getter} should be a closure taking a single @var{instance} parameter +that returns the current slot value. @var{setter} should be a closure +taking two parameters - @var{instance} and @var{new-val} - that sets the +slot value to @var{new-val}. +@end deffn + +@node Slot Description Example +@section Illustrating Slot Description + +To illustrate slot description, we can redefine the @code{<my-complex>} +class seen before. A definition could be: + +@lisp +(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)) +@end lisp + +@noindent +With this definition, the @code{r} and @code{i} slots are set to 0 by +default, and can be initialised to other values by calling @code{make} +with the @code{#:r} and @code{#:i} keywords. Also the generic functions +@code{get-r}, @code{set-r!}, @code{get-i} and @code{set-i!} are +automatically defined to read and write the slots. + +@lisp +(define c1 (make <my-complex> #:r 1 #:i 2)) +(get-r c1) @result{} 1 +(set-r! c1 12) +(get-r c1) @result{} 12 +(define c2 (make <my-complex> #:r 2)) +(get-r c2) @result{} 2 +(get-i c2) @result{} 0 +@end lisp + +Accessors can both read and write a slot. So, another definition of the +@code{<my-complex>} class, using the @code{#:accessor} option, could be: + +@findex set! +@lisp +(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)) +@end lisp + +@noindent +With this definition, the @code{r} slot can be read with: +@lisp +(real-part c) +@end lisp +@noindent +and set with: +@lisp +(set! (real-part c) new-value) +@end lisp + +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: + +@lisp +(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))))))) + +@end lisp + +In this class definition, the magnitude @code{m} and angle @code{a} +slots are virtual, and are calculated, when referenced, from the normal +(i.e.@: @code{#:allocation #:instance}) slots @code{r} and @code{i}, by +calling the function defined in the relevant @code{#:slot-ref} option. +Correspondingly, writing @code{m} or @code{a} leads to calling the +function defined in the @code{#:slot-set!} option. Thus the +following expression + +@findex #:slot-set! +@findex #:slot-ref +@lisp +(slot-set! c 'a 3) +@end lisp + +@noindent +permits to set the angle of the @code{c} complex number. + +@lisp +(define c (make <my-complex> #:r 12 #:i 20)) +(real-part c) @result{} 12 +(angle c) @result{} 1.03037682652431 +(slot-set! c 'i 10) +(set! (real-part c) 1) +(describe c) +@print{} +#<<my-complex> 401e9b58> is an instance of class <my-complex> +Slots are: + r = 1 + i = 10 + m = 10.0498756211209 + a = 1.47112767430373 +@end lisp + +Since initialization keywords have been defined for the four slots, we +can now define the standard Scheme primitives @code{make-rectangular} +and @code{make-polar}. + +@lisp +(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))) +@end lisp + + +@node Methods and Generic Functions +@section 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. + +@lisp +(define-method (+ (x <string>) (y <string>)) + (string-append x y)) + +(+ "abc" "de") @result{} "abcde" +@end lisp + +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 + +@lisp +(define-method (stretch (im <image>) (sf <surface>)) + ...) +@end lisp + +@noindent +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: + +@lisp +(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>)) ...) +@end lisp + +@noindent +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 @code{(+ 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 @code{+}). 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 +@code{define-generic} macro. Definition of a new method is done with +the @code{define-method} macro. Note that @code{define-method} +automatically does a @code{define-generic} if the identifier concerned +is not already a generic function, so often an explicit +@code{define-generic} call is not needed. +@findex define-generic +@findex define-method + +@deffn syntax define-generic symbol +Create a generic function with name @var{symbol} and bind it to the +variable @var{symbol}. If @var{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. +@end deffn + +@deffn syntax define-method (generic parameter @dots{}) body @dots{} +Define a method for the generic function or accessor @var{generic} with +parameters @var{parameter}s and body @var{body} @enddots{}. + +@var{generic} is a generic function. If @var{generic} is a variable +which is not yet bound to a generic function object, the expansion of +@code{define-method} will include a call to @code{define-generic}. If +@var{generic} is @code{(setter @var{generic-with-setter})}, where +@var{generic-with-setter} is a variable which is not yet bound to a +generic-with-setter object, the expansion will include a call to +@code{define-accessor}. + +Each @var{parameter} must be either a symbol or a two-element list +@code{(@var{symbol} @var{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 @var{class}es, if present, +specify the possible combinations of parameters to which this method +can be applied. + +@var{body} @dots{} are the bodies of the method definition. +@end deffn + +@code{define-method} expressions look a little like Scheme procedure +definitions of the form + +@example +(define (name formals @dots{}) . body) +@end example + +The important difference is that each formal parameter, apart from the +possible ``rest'' argument, can be qualified by a class name: +@code{@var{formal}} becomes @code{(@var{formal} @var{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 @code{@var{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 @code{<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 +@var{parameter}s @code{(s1 <square>)} and @code{(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 +@code{<square>} class and the second parameter is a number. + +@menu +* Accessors:: +* Extending Primitives:: +* Merging Generics:: +* Next-method:: +* Generic Function and Method Examples:: +* Handling Invocation Errors:: +@end menu + + +@node Accessors +@subsection Accessors + +An accessor is a generic function that can also be used with the +generalized @code{set!} syntax (@pxref{Procedures with Setters}). Guile +will handle a call like + +@example +(set! (@code{accessor} @code{args}@dots{}) @code{value}) +@end example + +@noindent +by calling the most specialized method of @code{accessor} that matches +the classes of @code{args} and @code{value}. @code{define-accessor} is +used to bind an identifier to an accessor. + +@deffn syntax define-accessor symbol +Create an accessor with name @var{symbol} and bind it to the variable +@var{symbol}. If @var{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. +@end deffn + + +@node Extending Primitives +@subsection 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 +@code{define-method} call) for a variable whose current value is a +primitive. But it can also be forced by calling +@code{enable-primitive-generic!}. + +@deffn {primitive procedure} enable-primitive-generic! primitive +Force the creation of a generic function definition for +@var{primitive}. +@end deffn + +Once the generic function definition for a primitive has been created, +it can be retrieved using @code{primitive-generic-generic}. + +@deffn {primitive procedure} primitive-generic-generic primitive +Return the generic function definition of @var{primitive}. + +@code{primitive-generic-generic} raises an error if @var{primitive} +is not a primitive with generic capability. +@end deffn + +@node Merging Generics +@subsection 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 @code{x}. It +doesn't need to be called, for example, @code{vector:x}, because +GOOPS will work out, when it sees code like @code{(x @var{obj})}, that +the vector-specific method of @code{x} should be called if @var{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 +@code{x}, what does the code using those packages end up with? + +@ref{Creating Guile Modules,,duplicate binding handlers} explains how +this is resolved for conflicting bindings in general. For generics, +there is a special duplicates handler, @code{merge-generics}, which +tells the module system to merge generic functions with the same name. +Here is an example: + +@lisp +(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)) +@end lisp + +The generic function @code{x} in @code{(my-module)} will now incorporate +all of the methods of @code{x} from both imported modules. + +To be precise, there will now be three distinct generic functions named +@code{x}: @code{x} in @code{(math 2D-vectors)}, @code{x} in @code{(math +3D-vectors)}, and @code{x} in @code{(my-module)}; and these functions +share their methods in an interesting and dynamic way. + +To explain, let's call the imported generic functions (in @code{(math +2D-vectors)} and @code{(math 3D-vectors)}) the @dfn{ancestors}, and the +merged generic function (in @code{(my-module)}), the @dfn{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, @code{x} in +@code{(math 2D-vectors)} will share the methods of @code{x} in +@code{(my-module)} and vice versa.@footnote{But note that @code{x} in +@code{(math 2D-vectors)} doesn't share methods with @code{x} in +@code{(math 3D-vectors)}, so modularity is still preserved.} Sharing is +dynamic, so adding another new method to a descendant implies adding it +to that descendant's ancestors too. + +@node Next-method +@subsection 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 @code{next-method}. + +@lisp +(define-method (Test (a <integer>)) (cons 'integer (next-method))) +(define-method (Test (a <number>)) (cons 'number (next-method))) +(define-method (Test a) (list 'top)) +@end lisp + +With these definitions, + +@lisp +(Test 1) @result{} (integer number top) +(Test 1.0) @result{} (number top) +(Test #t) @result{} (top) +@end lisp + +@code{next-method} is always called as just @code{(next-method)}. The +arguments for the next method call are always implicit, and always 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 do not use @code{next-method}, but instead simply +write the new call as usual: + +@lisp +(define-method (Test (a <number>) min max) + (if (and (>= a min) (<= a max)) + (display "Number is in range\n")) + (Test a)) + +(Test 2 1 10) +@print{} +Number is in range +@result{} +(integer number top) +@end lisp + +(You should be careful in this case that the @code{Test} calls do not +lead to an infinite recursion, but this consideration is just the same +as in Scheme code in general.) + +@node Generic Function and Method Examples +@subsection Generic Function and Method Examples + +Consider the following definitions: + +@lisp +(define-generic G) +(define-method (G (a <integer>) b) 'integer) +(define-method (G (a <real>) b) 'real) +(define-method (G a b) 'top) +@end lisp + +The @code{define-generic} call defines @var{G} as a generic function. +The three next lines define methods for @var{G}. Each method uses a +sequence of @dfn{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 @code{<top>}. Thus, +the first method definition is equivalent to + +@cindex parameter specializers +@lisp +(define-method (G (a <integer>) (b <top>)) 'integer) +@end lisp + +Now, let's look at some possible calls to the generic function @var{G}: + +@lisp +(G 2 3) @result{} integer +(G 2 #t) @result{} integer +(G 1.2 'a) @result{} real +@c (G #3 'a) @result{} real @c was {\sharpsign} +(G #t #f) @result{} top +(G 1 2 3) @result{} error (since no method exists for 3 parameters) +@end lisp + +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: + +@lisp +(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) +@end lisp + +@noindent With these definitions: + +@lisp +(G 1 2) @result{} integer-integer +(G 1 1.0) @result{} integer-real +(G 1 #t) @result{} integer +(G 'a 1) @result{} top-number +@end lisp + +As a further example we shall continue to define operations on the +@code{<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 + +@lisp +(define-method (new-+ (a <my-complex>) (b <my-complex>)) + (make-rectangular (+ (real-part a) (real-part b)) + (+ (imag-part a) (imag-part b)))) +@end lisp + +To be sure that the @code{+} used in the method @code{new-+} is the +standard addition we can do: + +@lisp +(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))))) +@end lisp + +The @code{define-generic} ensures here that @code{new-+} will be defined +in the global environment. Once this is done, we can add methods to the +generic function @code{new-+} which make a closure on the @code{+} +symbol. A complete writing of the @code{new-+} methods is shown in +@ref{fig:newplus}. + +@float Figure,fig:newplus +@lisp +(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-+) +@end lisp + +@caption{Extending @code{+} to handle complex numbers} +@end float + +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 @code{+}). The last method takes an arbitrary number of +parameters@footnote{The parameter list for a @code{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}. This method acts as a kind of @code{reduce}: it calls the +dyadic addition on the @emph{car} of the list and on the result of +applying it on its rest. To finish, the @code{set!} permits to redefine +the @code{+} symbol to our extended addition. + +To conclude our implementation (integration?) of complex numbers, we +could redefine standard Scheme predicates in the following manner: + +@lisp +(define-method (complex? c <my-complex>) #t) +(define-method (complex? c) #f) + +(define-method (number? n <number>) #t) +(define-method (number? n) #f) +@dots{} +@end lisp + +Standard primitives in which complex numbers are involved could also be +redefined in the same manner. + + +@node Handling Invocation Errors +@subsection 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. + +@deffn generic no-method +@deffnx 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 +@code{no-method} generic function. The default method calls +@code{goops-error} with an appropriate message. +@end deffn + +@deffn generic no-applicable-method +@deffnx 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 @code{no-applicable-method} generic function. The default method +calls @code{goops-error} with an appropriate message. +@end deffn + +@deffn generic no-next-method +@deffnx method no-next-method (gf <generic>) args +When a generic function method calls @code{(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 @code{no-next-method} generic function. The +default method calls @code{goops-error} with an appropriate message. +@end deffn + + +@node Inheritance +@section Inheritance + +Here are some class definitions to help illustrate inheritance: + +@lisp +(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) +@end lisp + +@code{A}, @code{B}, @code{C} have a null list of superclasses. In this +case, the system will replace the null list by a list which only +contains @code{<object>}, the root of all the classes defined by +@code{define-class}. @code{D}, @code{E}, @code{F} use multiple +inheritance: each class inherits from two previously defined classes. +Those class definitions define a hierarchy which is shown in +@ref{fig:hier}. In this figure, the class @code{<top>} is also shown; +this class is the superclass of all Scheme objects. In particular, +@code{<top>} is the superclass of all standard Scheme +types. + +@float Figure,fig:hier +@iftex +@center @image{hierarchy,5in} +@end iftex +@ifnottex +@verbatiminclude hierarchy.txt +@end ifnottex + +@caption{A class hierarchy.} +@end float + +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, @code{a}, @code{b} and +@code{d}). The slots of a class can be discovered using the +@code{class-slots} primitive. For instance, + +@lisp +(class-slots A) @result{} ((a)) +(class-slots E) @result{} ((a) (e) (c)) +(class-slots F) @result{} ((e) (c) (b) (d) (a) (f)) +@end lisp + +@noindent +The ordering of the returned slots is not significant. + +@menu +* Class Precedence List:: +* Sorting Methods:: +@end menu + + +@node Class Precedence List +@subsection 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 @dfn{Class Precedence +List}.@footnote{This section is an adaptation of material from Jeff +Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief introduction to CLOS}} + +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 +@code{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 @dfn{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 + +@lisp +(define-class X () + (x #:init-value 1)) + +(define-class Y () + (x #:init-value 2)) + +(define-class Z (X Y) + (@dots{})) +@end lisp + +@noindent +Clearly the @code{Z} class is more specific than @code{X} or @code{Y}, +for instances of @code{Z}. But which is more specific out of @code{X} +and @code{Y} --- and hence, for the definitions above, which +@code{#:init-value} will take effect when creating an instance of +@code{Z}? The rule in @goops{} is that the superclasses listed earlier +are more specific than those listed later. Hence @code{X} is more +specific than @code{Y}, and the @code{#:init-value} for slot @code{x} in +instances of @code{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 @code{F} class shown in @ref{fig:hier}, the class precedence +list is + +@example +(f d e a c b <object> <top>) +@end example + +@noindent +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 +@code{class-precedence-list}. This function returns a ordered list +whose first element is the most specific class. For instance: + +@lisp +(class-precedence-list B) @result{} (#<<class> B 401b97c8> + #<<class> <object> 401e4a10> + #<<class> <top> 4026a9d8>) +@end lisp + +@noindent +Or for a more immediately readable result: + +@lisp +(map class-name (class-precedence-list B)) @result{} (B <object> <top>) +@end lisp + + +@node Sorting Methods +@subsection 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 +@itemize +@item +the applicable methods are sorted in order of specificity, and the most +specific method is used first, then the next if that method calls +@code{next-method}, and so on + +@item +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 + +@item +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. +@end itemize + + +@node Introspection +@section Introspection + +@dfn{Introspection}, or @dfn{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: + +@itemize @bullet +@item +What are the data members of this object or class? + +@item +What classes does this class inherit from? + +@item +Is this method call virtual or non-virtual? + +@item +If I invoke @code{Employee::adjustHoliday()}, what class contains the +@code{adjustHoliday()} method that will be applied? +@end itemize + +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:: +@end menu + +@node Classes +@subsection Classes + +A GOOPS class is itself an instance of the @code{<class>} class, or of a +subclass of @code{<class>}. The definition of the @code{<class>} class +has slots that are used to describe the properties of a class, including +the following. + +@deffn {primitive procedure} class-name class +Return the name of class @var{class}. This is the value of +@var{class}'s @code{name} slot. +@end deffn + +@deffn {primitive procedure} class-direct-supers class +Return a list containing the direct superclasses of @var{class}. This +is the value of @var{class}'s @code{direct-supers} slot. +@end deffn + +@deffn {primitive procedure} class-direct-slots class +Return a list containing the slot definitions of the direct slots of +@var{class}. This is the value of @var{class}'s @code{direct-slots} +slot. +@end deffn + +@deffn {primitive procedure} class-direct-subclasses class +Return a list containing the direct subclasses of @var{class}. This is +the value of @var{class}'s @code{direct-subclasses} slot. +@end deffn + +@deffn {primitive procedure} class-direct-methods class +Return a list of all the generic function methods that use @var{class} +as a formal parameter specializer. This is the value of @var{class}'s +@code{direct-methods} slot. +@end deffn + +@deffn {primitive procedure} class-precedence-list class +Return the class precedence list for class @var{class} (@pxref{Class +Precedence List}). This is the value of @var{class}'s @code{cpl} slot. +@end deffn + +@deffn {primitive procedure} class-slots class +Return a list containing the slot definitions for all @var{class}'s +slots, including any slots that are inherited from superclasses. This +is the value of @var{class}'s @code{slots} slot. +@end deffn + +@deffn procedure class-subclasses class +Return a list of all subclasses of @var{class}. +@end deffn + +@deffn procedure class-methods class +Return a list of all methods that use @var{class} or a subclass of +@var{class} as one of its formal parameter specializers. +@end deffn + + +@node Instances +@subsection Instances + +@deffn {primitive procedure} class-of value +Return the GOOPS class of any Scheme @var{value}. +@end deffn + +@deffn {primitive procedure} instance? object +Return @code{#t} if @var{object} is any GOOPS instance, otherwise +@code{#f}. +@end deffn + +@deffn procedure is-a? object class +Return @code{#t} if @var{object} is an instance of @var{class} or one of +its subclasses. +@end deffn + +You can use the @code{is-a?} predicate to ask whether any given value +belongs to a given class, or @code{class-of} to discover the class of a +given value. Note that when GOOPS is loaded (by code using the +@code{(oop goops)} module) built-in classes like @code{<string>}, +@code{<list>} and @code{<number>} are automatically set up, +corresponding to all Guile Scheme types. + +@lisp +(is-a? 2.3 <number>) @result{} #t +(is-a? 2.3 <real>) @result{} #t +(is-a? 2.3 <string>) @result{} #f +(is-a? '("a" "b") <string>) @result{} #f +(is-a? '("a" "b") <list>) @result{} #t +(is-a? (car '("a" "b")) <string>) @result{} #t +(is-a? <string> <class>) @result{} #t +(is-a? <class> <string>) @result{} #f + +(class-of 2.3) @result{} #<<class> <real> 908c708> +(class-of #(1 2 3)) @result{} #<<class> <vector> 908cd20> +(class-of <string>) @result{} #<<class> <class> 8bd3e10> +(class-of <class>) @result{} #<<class> <class> 8bd3e10> +@end lisp + + +@node Slots +@subsection Slots + +@deffn procedure class-slot-definition class slot-name +Return the slot definition for the slot named @var{slot-name} in class +@var{class}. @var{slot-name} should be a symbol. +@end deffn + +@deffn procedure slot-definition-name slot-def +Extract and return the slot name from @var{slot-def}. +@end deffn + +@deffn procedure slot-definition-options slot-def +Extract and return the slot options from @var{slot-def}. +@end deffn + +@deffn procedure slot-definition-allocation slot-def +Extract and return the slot allocation option from @var{slot-def}. This +is the value of the @code{#:allocation} keyword (@pxref{Slot Options,, +allocation}), or @code{#:instance} if the @code{#:allocation} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-getter slot-def +Extract and return the slot getter option from @var{slot-def}. This is +the value of the @code{#:getter} keyword (@pxref{Slot Options,, +getter}), or @code{#f} if the @code{#:getter} keyword is absent. +@end deffn + +@deffn procedure slot-definition-setter slot-def +Extract and return the slot setter option from @var{slot-def}. This is +the value of the @code{#:setter} keyword (@pxref{Slot Options,, +setter}), or @code{#f} if the @code{#:setter} keyword is absent. +@end deffn + +@deffn procedure slot-definition-accessor slot-def +Extract and return the slot accessor option from @var{slot-def}. This +is the value of the @code{#:accessor} keyword (@pxref{Slot Options,, +accessor}), or @code{#f} if the @code{#:accessor} keyword is absent. +@end deffn + +@deffn procedure slot-definition-init-value slot-def +Extract and return the slot init-value option from @var{slot-def}. This +is the value of the @code{#:init-value} keyword (@pxref{Slot Options,, +init-value}), or the unbound value if the @code{#:init-value} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-init-form slot-def +Extract and return the slot init-form option from @var{slot-def}. This +is the value of the @code{#:init-form} keyword (@pxref{Slot Options,, +init-form}), or the unbound value if the @code{#:init-form} keyword is +absent. +@end deffn + +@deffn procedure slot-definition-init-thunk slot-def +Extract and return the slot init-thunk option from @var{slot-def}. This +is the value of the @code{#:init-thunk} keyword (@pxref{Slot Options,, +init-thunk}), or @code{#f} if the @code{#:init-thunk} keyword is absent. +@end deffn + +@deffn procedure slot-definition-init-keyword slot-def +Extract and return the slot init-keyword option from @var{slot-def}. +This is the value of the @code{#:init-keyword} keyword (@pxref{Slot +Options,, init-keyword}), or @code{#f} if the @code{#:init-keyword} +keyword is absent. +@end deffn + +@deffn procedure slot-init-function class slot-name +Return the initialization function for the slot named @var{slot-name} in +class @var{class}. @var{slot-name} should be a symbol. + +The returned initialization function incorporates the effects of the +standard @code{#:init-thunk}, @code{#:init-form} and @code{#:init-value} +slot options. These initializations can be overridden by the +@code{#:init-keyword} slot option or by a specialized @code{initialize} +method, so, in general, the function returned by +@code{slot-init-function} may be irrelevant. For a fuller discussion, +see @ref{Slot Options,, init-value}. +@end deffn + + +@node Generic Functions +@subsection Generic Functions + +A generic function is an instance of the @code{<generic>} class, or of a +subclass of @code{<generic>}. The definition of the @code{<generic>} +class has slots that are used to describe the properties of a generic +function. + +@deffn {primitive procedure} generic-function-name gf +Return the name of generic function @var{gf}. +@end deffn + +@deffn {primitive procedure} generic-function-methods gf +Return a list of the methods of generic function @var{gf}. This is the +value of @var{gf}'s @code{methods} slot. +@end deffn + +Similarly, a method is an instance of the @code{<method>} class, or of a +subclass of @code{<method>}; and the definition of the @code{<method>} +class has slots that are used to describe the properties of a method. + +@deffn {primitive procedure} method-generic-function method +Return the generic function that @var{method} belongs to. This is the +value of @var{method}'s @code{generic-function} slot. +@end deffn + +@deffn {primitive procedure} method-specializers method +Return a list of @var{method}'s formal parameter specializers . This is +the value of @var{method}'s @code{specializers} slot. +@end deffn + +@deffn {primitive procedure} method-procedure method +Return the procedure that implements @var{method}. This is the value of +@var{method}'s @code{procedure} slot. +@end deffn + +@deffn generic method-source +@deffnx method method-source (m <method>) +Return an expression that prints to show the definition of method +@var{m}. + +@example +(define-generic cube) + +(define-method (cube (n <number>)) + (* n n n)) + +(map method-source (generic-function-methods cube)) +@result{} +((method ((n <number>)) (* n n n))) +@end example +@end deffn + + +@node Accessing Slots +@subsection Accessing Slots + +Any slot, regardless of its allocation, can be queried, referenced and +set using the following four primitive procedures. + +@deffn {primitive procedure} slot-exists? obj slot-name +Return @code{#t} if @var{obj} has a slot with name @var{slot-name}, +otherwise @code{#f}. +@end deffn + +@deffn {primitive procedure} slot-bound? obj slot-name +Return @code{#t} if the slot named @var{slot-name} in @var{obj} has a +value, otherwise @code{#f}. + +@code{slot-bound?} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing +Slots, slot-missing}). +@end deffn + +@deffn {primitive procedure} slot-ref obj slot-name +Return the value of the slot named @var{slot-name} in @var{obj}. + +@code{slot-ref} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing +Slots, slot-missing}). + +@code{slot-ref} calls the generic function @code{slot-unbound} if the +named slot in @var{obj} does not have a value (@pxref{Accessing Slots, +slot-unbound}). +@end deffn + +@deffn {primitive procedure} slot-set! obj slot-name value +Set the value of the slot named @var{slot-name} in @var{obj} to @var{value}. + +@code{slot-set!} calls the generic function @code{slot-missing} if +@var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing +Slots, slot-missing}). +@end deffn + +GOOPS stores information about slots in classes. Internally, +all of these procedures work by looking up the slot definition for the +slot named @var{slot-name} in the class @code{(class-of +@var{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 +@code{(class-of @var{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. + +@deffn {primitive procedure} slot-exists-using-class? class obj slot-name +Return @code{#t} if @var{class} has a slot definition for a slot with +name @var{slot-name}, otherwise @code{#f}. +@end deffn + +@deffn {primitive procedure} slot-bound-using-class? class obj slot-name +Return @code{#t} if applying @code{slot-ref-using-class} to the same +arguments would call the generic function @code{slot-unbound}, otherwise +@code{#f}. + +@code{slot-bound-using-class?} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Accessing Slots, +slot-missing}). +@end deffn + +@deffn {primitive procedure} slot-ref-using-class class obj slot-name +Apply the ``getter'' closure for the slot named @var{slot-name} in +@var{class} to @var{obj}, and return its result. + +@code{slot-ref-using-class} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Accessing Slots, +slot-missing}). + +@code{slot-ref-using-class} calls the generic function +@code{slot-unbound} if the application of the ``getter'' closure to +@var{obj} returns an unbound value (@pxref{Accessing Slots, +slot-unbound}). +@end deffn + +@deffn {primitive procedure} slot-set-using-class! class obj slot-name value +Apply the ``setter'' closure for the slot named @var{slot-name} in +@var{class} to @var{obj} and @var{value}. + +@code{slot-set-using-class!} calls the generic function +@code{slot-missing} if @var{class} does not have a slot definition for a +slot called @var{slot-name} (@pxref{Accessing Slots, slot-missing}). +@end deffn + +Slots whose allocation is per-class rather than per-instance can be +referenced and set without needing to specify any particular instance. + +@deffn procedure class-slot-ref class slot-name +Return the value of the slot named @var{slot-name} in class @var{class}. +The named slot must have @code{#:class} or @code{#:each-subclass} +allocation (@pxref{Slot Options,, allocation}). + +If there is no such slot with @code{#:class} or @code{#:each-subclass} +allocation, @code{class-slot-ref} calls the @code{slot-missing} generic +function with arguments @var{class} and @var{slot-name}. Otherwise, if +the slot value is unbound, @code{class-slot-ref} calls the +@code{slot-unbound} generic function, with the same arguments. +@end deffn + +@deffn procedure class-slot-set! class slot-name value +Set the value of the slot named @var{slot-name} in class @var{class} to +@var{value}. The named slot must have @code{#:class} or +@code{#:each-subclass} allocation (@pxref{Slot Options,, allocation}). + +If there is no such slot with @code{#:class} or @code{#:each-subclass} +allocation, @code{class-slot-ref} calls the @code{slot-missing} generic +function with arguments @var{class} and @var{slot-name}. +@end deffn + +When a @code{slot-ref} or @code{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. + +@deffn generic slot-missing +@deffnx method slot-missing (class <class>) slot-name +@deffnx method slot-missing (class <class>) (object <object>) slot-name +@deffnx 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 @var{class} +or @var{object}, GOOPS calls the @code{slot-missing} generic function. + +The default methods all call @code{goops-error} with an appropriate +message. +@end deffn + +@deffn generic slot-unbound +@deffnx method slot-unbound (object <object>) +@deffnx method slot-unbound (class <class>) slot-name +@deffnx 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 @code{slot-unbound} generic +function. + +The default methods all call @code{goops-error} with an appropriate +message. +@end deffn + + +@node GOOPS Error Handling +@section Error Handling + +The procedure @code{goops-error} is called to raise an appropriate error +by the default methods of the following generic functions: + +@itemize @bullet +@item +@code{slot-missing} (@pxref{Accessing Slots,, slot-missing}) + +@item +@code{slot-unbound} (@pxref{Accessing Slots,, slot-unbound}) + +@item +@code{no-method} (@pxref{Handling Invocation Errors,, no-method}) + +@item +@code{no-applicable-method} (@pxref{Handling Invocation Errors,, +no-applicable-method}) + +@item +@code{no-next-method} (@pxref{Handling Invocation Errors,, +no-next-method}) +@end itemize + +If you customize these functions for particular classes or metaclasses, +you may still want to use @code{goops-error} to signal any error +conditions that you detect. + +@deffn procedure goops-error format-string arg @dots{} +Raise an error with key @code{goops-error} and error message constructed +from @var{format-string} and @var{arg} @enddots{}. Error message +formatting is as done by @code{scm-error}. +@end deffn + + +@node GOOPS Object Miscellany +@section GOOPS Object Miscellany + +Here we cover some points about GOOPS objects that aren't substantial +enough to merit sections on their own. + +@subheading Object Equality + +When GOOPS is loaded, @code{eqv?}, @code{equal?} and @code{=} 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 @code{assoc} procedure, for looking up an entry in an +alist, is specified as using @code{equal?} to determine when the car of +an entry in the alist is the same as the key parameter that @code{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 @code{equal?}, for your class, to control @code{assoc}'s +lookup precisely. + +@subheading Cloning Objects + +@deffn generic shallow-clone +@deffnx method shallow-clone (self <object>) +Return a ``shallow'' clone of @var{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. +@end deffn + +@deffn generic deep-clone +@deffnx method deep-clone (self <object>) +Return a ``deep'' clone of @var{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 @code{instance?}), it is cloned by calling @code{deep-clone} +on that value. Other slot values are copied either as immediate values +or by reference. +@end deffn + +@subheading Write and Display + +@deffn {primitive generic} write object port +@deffnx {primitive generic} display object port +When GOOPS is loaded, @code{write} and @code{display} become generic +functions with special methods for printing + +@itemize @bullet +@item +objects - instances of the class @code{<object>} + +@item +foreign objects - instances of the class @code{<foreign-object>} + +@item +classes - instances of the class @code{<class>} + +@item +generic functions - instances of the class @code{<generic>} + +@item +methods - instances of the class @code{<method>}. +@end itemize + +@code{write} and @code{display} print non-GOOPS values in the same way +as the Guile primitive @code{write} and @code{display} functions. +@end deffn + +In addition to the cases mentioned, you can of course define +@code{write} and @code{display} methods for your own classes, to +customize how instances of those classes are printed. + + +@node The Metaobject Protocol +@section 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 @code{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 behaviour 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:: +@end menu + +@node Metaobjects and the Metaobject Protocol +@subsection 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 behaviour, 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 behaviour 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 behaviour 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 +@code{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 +@code{define-class} itself does not perform this calculation. Instead, +there is a method of the @code{initialize} generic function that is +specialized for instances of type @code{<class>}, and it is this method +that performs the slot calculation. + +@code{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. + +@itemize @bullet +@item +@code{define-class} uses @code{make} to make a new instance of the +@code{<class>} class, passing as initialization arguments the +superclasses, slot definitions and class options that were specified in +the @code{define-class} form. + +@item +@code{make} allocates memory for the new instance, and invokes the +@code{initialize} generic function to initialize the new instance's +slots. + +@item +The @code{initialize} generic function applies the method that is +specialized for instances of type @code{<class>}, and this method +performs the slot calculation. +@end itemize + +In other words, rather than being hardcoded in @code{define-class}, the +default behaviour of class definition is encapsulated by generic +function methods that are specialized for the class @code{<class>}. + +It is possible to create a new class that inherits from @code{<class>}, +which is called a ``metaclass'', and to write a new @code{initialize} +method that is specialized for instances of the new metaclass. Then, if +the @code{define-class} form includes a @code{#:metaclass} class option +whose value is the new metaclass, the class that is defined by the +@code{define-class} form will be an instance of the new metaclass rather +than of the default @code{<class>}, and will be defined in accordance +with the new @code{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 behaviour of generic functions can be modified or +overridden by creating a new class that inherits from the standard +generic function class @code{<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 @code{initialize} method +that is specialized to their application class, to initialize instances +of that class. + +Such is the power of the MOP. Note that @code{initialize} is just one +of a large number of generic functions that can be customized to modify +the behaviour 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. + +@node Metaclasses +@subsection Metaclasses + +A @dfn{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 @code{<class>} and, by default, +any new class that is created using @code{define-class} has the +metaclass @code{<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 @code{define-class}: + +@example +(define-class <my-class> (<object>) . slots) +@end example + +@noindent +Guile expands this to something like: + +@example +(define <my-class> (class (<object>) . slots)) +@end example + +@noindent +which in turn expands to: + +@example +(define <my-class> + (make <class> #:dsupers (list <object>) #:slots slots)) +@end example + +As this expansion makes clear, the resulting value of @code{<my-class>} +is an instance of the class @code{<class>} with slot values specifying +the superclasses and slot definitions for the class @code{<my-class>}. +(@code{#:dsupers} and @code{#:slots} are initialization keywords for the +@code{dsupers} and @code{dslots} slots of the @code{<class>} class.) + +Now suppose that you want to define a new class with a metaclass other +than the default @code{<class>}. This is done by writing: + +@example +(define-class <my-class2> (<object>) + slot @dots{} + #:metaclass <my-metaclass>) +@end example + +@noindent +and Guile expands @emph{this} to something like: + +@example +(define <my-class2> + (make <my-metaclass> #:dsupers (list <object>) #:slots slots)) +@end example + +In this case, the value of @code{<my-class2>} is an instance of the more +specialized class @code{<my-metaclass>}. Note that +@code{<my-metaclass>} itself must previously have been defined as a +subclass of @code{<class>}. For a full discussion of when and how it is +useful to define new metaclasses, see @ref{MOP Specification}. + +Now let's make an instance of @code{<my-class2>}: + +@example +(define my-object (make <my-class2> ...)) +@end example + +All of the following statements are correct expressions of the +relationships between @code{my-object}, @code{<my-class2>}, +@code{<my-metaclass>} and @code{<class>}. + +@itemize @bullet +@item +@code{my-object} is an instance of the class @code{<my-class2>}. + +@item +@code{<my-class2>} is an instance of the class @code{<my-metaclass>}. + +@item +@code{<my-metaclass>} is an instance of the class @code{<class>}. + +@item +The class of @code{my-object} is @code{<my-class2>}. + +@item +The class of @code{<my-class2>} is @code{<my-metaclass>}. + +@item +The class of @code{<my-metaclass>} is @code{<class>}. +@end itemize + + +@node MOP Specification +@subsection 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 +@code{(initialize @var{instance} @var{initargs})} invocation in the +default @code{make-instance} method is customizable, because the type of +the @code{@var{instance}} argument is determined by the class that was +passed to @code{make-instance}. + +(Whereas --- to give a counter-example --- the @code{(make <generic> +#:name ',name)} invocation in @code{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 @dfn{invocation +protocol} is explained by specifying + +@itemize @bullet +@item +what, conceptually, the applied method is intended to do + +@item +what assumptions, if any, the caller makes about the applied method's side +effects + +@item +what the caller expects to get as the applied method's return value. +@end itemize + + +@node Instance Creation Protocol +@subsection Instance Creation Protocol + +@code{make <class> . @var{initargs}} (method) + +@itemize @bullet +@item +@code{allocate-instance @var{class} @var{initargs}} (generic) + +The applied @code{allocate-instance} method should allocate storage for +a new instance of class @var{class} and return the uninitialized instance. + +@item +@code{initialize @var{instance} @var{initargs}} (generic) + +@var{instance} is the uninitialized instance returned by +@code{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. +@end itemize + +@code{make} itself is a generic function. Hence the @code{make} +invocation itself can be customized in the case where the new instance's +metaclass is more specialized than the default @code{<class>}, by +defining a @code{make} method that is specialized to that metaclass. + +Normally, however, the method for classes with metaclass @code{<class>} +will be applied. This method calls two generic functions: + +@itemize @bullet +@item +(allocate-instance @var{class} . @var{initargs}) + +@item +(initialize @var{instance} . @var{initargs}) +@end itemize + +@code{allocate-instance} allocates storage for and returns the new +instance, uninitialized. You might customize @code{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 @code{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 @code{make} and +@code{initialize}, so that GOOPS knows how to make classes from the +other system, access instance slots, and so on. + +@code{initialize} initializes the instance that is returned by +@code{allocate-instance}. The standard GOOPS methods perform +initializations appropriate to the instance class. + +@itemize @bullet +@item +At the least specialized level, the method for instances of type +@code{<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 @var{initargs}. + +@item +The method for instances of type @code{<class>} calls +@code{(next-method)}, then performs the class initializations described +in @ref{Class Definition Protocol}. + +@item +and so on for generic functions, methods, operator classes @dots{} +@end itemize + +Similarly, you can customize the initialization of instances of any +application-defined class by defining an @code{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 @code{#:init-thunk} keywords +and closures in the slot definitions, it may be neater to write an +@code{initialize} method for the class that queries the database once +and initializes all the dependent slot values according to the results. + + +@node Class Definition Protocol +@subsection Class Definition Protocol + +Here is a summary diagram of the syntax, procedures and generic +functions that may be involved in class definition. + +@noindent +@code{define-class} (syntax) + +@itemize @bullet +@item +@code{class} (syntax) + +@itemize @bullet +@item +@code{make-class} (procedure) + +@itemize @bullet +@item +@code{ensure-metaclass} (procedure) + +@item +@code{make @var{metaclass} @dots{}} (generic) + +@itemize @bullet +@item +@code{allocate-instance} (generic) + +@item +@code{initialize} (generic) + +@itemize @bullet +@item +@code{compute-cpl} (generic) + +@itemize @bullet +@item +@code{compute-std-cpl} (procedure) +@end itemize + +@item +@code{compute-slots} (generic) + +@item +@code{compute-get-n-set} (generic) + +@item +@code{compute-getter-method} (generic) + +@item +@code{compute-setter-method} (generic) +@end itemize +@end itemize +@end itemize +@end itemize + +@item +@code{class-redefinition} (generic) + +@itemize @bullet +@item +@code{remove-class-accessors} (generic) + +@item +@code{update-direct-method!} (generic) + +@item +@code{update-direct-subclass!} (generic) +@end itemize +@end itemize + +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 @code{initialize} method, for some metaclass, +that does not call @code{next-method} and does not call +@code{compute-cpl}, then @code{compute-cpl} will not be called when a +class is defined with that metaclass. + +A @code{(define-class ...)} form (@pxref{Class Definition}) expands to +an expression which + +@itemize @bullet +@item +checks that it is being evaluated only at top level + +@item +defines any accessors that are implied by the @var{slot-definition}s + +@item +uses @code{class} to create the new class + +@item +checks for a previous class definition for @var{name} and, if found, +handles the redefinition by invoking @code{class-redefinition} +(@pxref{Redefining a Class}). +@end itemize + +@deffn syntax class name (super @dots{}) @ + slot-definition @dots{} class-option @dots{} +Return a newly created class that inherits from @var{super}s, with +direct slots defined by @var{slot-definition}s and @var{class-option}s. +For the format of @var{slot-definition}s and @var{class-option}s, see +@ref{Class Definition,, define-class}. +@end deffn + +@noindent @code{class} expands to an expression which + +@itemize @bullet +@item +processes the class and slot definition options to check that they are +well-formed, to convert the @code{#:init-form} option to an +@code{#: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 + +@item +calls @code{make-class} to create the class with the processed and +evaluated parameters. +@end itemize + +@deffn procedure make-class supers slots class-option @dots{} +Return a newly created class that inherits from @var{supers}, with +direct slots defined by @var{slots} and @var{class-option}s. For the +format of @var{slots} and @var{class-option}s, see @ref{Class +Definition,, define-class}, except note that for @code{make-class}, +@var{slots} is a separate list of slot definitions. +@end deffn + +@noindent @code{make-class} + +@itemize @bullet +@item +adds @code{<object>} to the @var{supers} list if @var{supers} is empty +or if none of the classes in @var{supers} have @code{<object>} in their +class precedence list + +@item +defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass} +options, if they are not specified by @var{options}, to the current +top-level environment, the unbound value, and @code{(ensure-metaclass +@var{supers})} respectively + +@item +checks for duplicate classes in @var{supers} and duplicate slot names in +@var{slots}, and signals an error if there are any duplicates + +@item +calls @code{make}, passing the metaclass as the first parameter and all +other parameters as option keywords with values. +@end itemize + +@deffn procedure ensure-metaclass supers env +Return a metaclass suitable for a class that inherits from the list of +classes in @var{supers}. The returned metaclass is the union by +inheritance of the metaclasses of the classes in @var{supers}. + +In the simplest case, where all the @var{supers} are straightforward +classes with metaclass @code{<class>}, the returned metaclass is just +@code{<class>}. + +For a more complex example, suppose that @var{supers} contained one +class with metaclass @code{<operator-class>} and one with metaclass +@code{<foreign-object-class>}. Then the returned metaclass would be a +class that inherits from both @code{<operator-class>} and +@code{<foreign-object-class>}. + +If @var{supers} is the empty list, @code{ensure-metaclass} returns the +default GOOPS metaclass @code{<class>}. + +GOOPS keeps a list of the metaclasses created by +@code{ensure-metaclass}, so that each required type of metaclass only +has to be created once. + +The @code{env} parameter is ignored. +@end deffn + +@deffn generic make metaclass initarg @dots{} +@var{metaclass} is the metaclass of the class being defined, either +taken from the @code{#:metaclass} class option or computed by +@code{ensure-metaclass}. The applied method must create and return the +fully initialized class metaobject for the new class definition. +@end deffn + +The @code{(make @var{metaclass} @var{initarg} @dots{})} invocation is a +particular case of the instance creation protocol covered in the +previous section. It will create an class metaobject with metaclass +@var{metaclass}. By default, this metaobject will be initialized by the +@code{initialize} method that is specialized for instances of type +@code{<class>}. + +The @code{initialize} method for classes (signature @code{(initialize +<class> initargs)}) calls the following generic functions. + +@itemize @bullet +@item +@code{compute-cpl @var{class}} (generic) + +The applied method should compute and return the class precedence list +for @var{class} as a list of class metaobjects. When @code{compute-cpl} +is called, the following @var{class} metaobject slots have all been +initialized: @code{name}, @code{direct-supers}, @code{direct-slots}, +@code{direct-subclasses} (empty), @code{direct-methods}. The value +returned by @code{compute-cpl} will be stored in the @code{cpl} slot. + +@item +@code{compute-slots @var{class}} (generic) + +The applied method should compute and return the slots (union of direct +and inherited) for @var{class} as a list of slot definitions. When +@code{compute-slots} is called, all the @var{class} metaobject slots +mentioned for @code{compute-cpl} have been initialized, plus the +following: @code{cpl}, @code{redefined} (@code{#f}), @code{environment}. +The value returned by @code{compute-slots} will be stored in the +@code{slots} slot. + +@item +@code{compute-get-n-set @var{class} @var{slot-def}} (generic) + +@code{initialize} calls @code{compute-get-n-set} for each slot computed +by @code{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: @code{(list @var{get} @var{set})}. + +The closures returned by @code{compute-get-n-set} are stored as part of +the value of the @var{class} metaobject's @code{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 + +@example +@code{(@var{slot-name-symbol} @var{init-function} . @var{index})} +@end example + +or like + +@example +@code{(@var{slot-name-symbol} @var{init-function} @var{get} @var{set})} +@end example + +Where the get and set closures are replaced by @var{index}, the slot is +an instance slot and @var{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, +@var{get} and @var{set} are the closures returned by @code{compute-get-n-set}. + +The structure of the @code{getters-n-setters} slot value is important when +understanding the next customizable generic functions that @code{initialize} +calls@dots{} + +@item +@code{compute-getter-method @var{class} @var{gns}} (generic) + +@code{initialize} calls @code{compute-getter-method} for each of the +class's slots (as determined by @code{compute-slots}) that includes a +@code{#:getter} or @code{#:accessor} slot option. @var{gns} is the +element of the @var{class} metaobject's @code{getters-n-setters} slot +that specifies how the slot in question is referenced and set, as +described above under @code{compute-get-n-set}. The applied method +should create and return a method that is specialized for instances of +type @var{class} and uses the get closure to retrieve the slot's value. +@code{initialize} uses @code{add-method!} to add the returned method to +the generic function named by the slot definition's @code{#:getter} or +@code{#:accessor} option. + +@item +@code{compute-setter-method @var{class} @var{gns}} (generic) + +@code{compute-setter-method} is invoked with the same arguments as +@code{compute-getter-method}, for each of the class's slots that includes +a @code{#:setter} or @code{#:accessor} slot option. The applied method +should create and return a method that is specialized for instances of +type @var{class} and uses the set closure to set the slot's value. +@code{initialize} then uses @code{add-method!} to add the returned method +to the generic function named by the slot definition's @code{#:setter} +or @code{#:accessor} option. +@end itemize + +@node Customizing Class Definition +@subsection Customizing Class Definition + +If the metaclass of the new class is something more specialized than the +default @code{<class>}, then the type of @var{class} in the calls above +is more specialized than @code{<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 behaviour of +@code{initialize}, @code{compute-cpl} or @code{compute-get-n-set}. + +@code{compute-cpl} computes the class precedence list (``CPL'') for the +new class (@pxref{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 @code{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 @code{compute-std-cpl} +procedure, which is called by the default @code{compute-cpl} method. + +@deffn procedure compute-std-cpl class +Compute and return the class precedence list for @var{class} according +to the algorithm described in @ref{Class Precedence List}. +@end deffn + +@code{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 @code{define-class} form, plus the slot definitions +that are inherited from the new class's superclasses. The default +@code{compute-slots} method uses the CPL computed by @code{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 @code{compute-slots} would be +to implement an alternative resolution strategy for slot name conflicts. + +@code{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 @code{compute-get-n-set} method, specialized for classes of +type @code{<class>}, handles the standard GOOPS values for the +@code{#:allocation} slot option (@pxref{Slot Options,, allocation}). By +defining a new @code{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. + +@example +(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>) +@end example + +The usage of @code{compute-getter-method} and @code{compute-setter-method} +is described in @ref{Class Definition Protocol}. + +@code{compute-cpl} and @code{compute-get-n-set} are called by the +standard @code{initialize} method for classes whose metaclass is +@code{<class>}. But @code{initialize} itself can also be modified, by +defining an @code{initialize} method specialized to the new class's +metaclass. Such a method could complete override the standard +behaviour, by not calling @code{(next-method)} at all, but more +typically it would perform additional class initialization steps before +and/or after calling @code{(next-method)} for the standard behaviour. + + +@node Method Definition +@subsection Method Definition + +@code{define-method} (syntax) + +@itemize @bullet +@item +@code{add-method! @var{target} @var{method}} (generic) +@end itemize + +@noindent +@code{define-method} invokes the @code{add-method!} generic function to +handle adding the new method to a variety of possible targets. GOOPS +includes methods to handle @var{target} as + +@itemize @bullet +@item +a generic function (the most common case) + +@item +a procedure + +@item +a primitive generic (@pxref{Extending Primitives}) +@end itemize + +By defining further methods for @code{add-method!}, you can +theoretically handle adding methods to further types of target. + + +@node Method Definition Internals +@subsection Method Definition Internals + +@code{define-method}: + +@itemize @bullet +@item +checks the form of the first parameter, and applies the following steps +to the accessor's setter if it has the @code{(setter @dots{})} form + +@item +interpolates a call to @code{define-generic} or @code{define-accessor} +if a generic function is not already defined with the supplied name + +@item +calls @code{method} with the @var{parameter}s and @var{body}, to make a +new method instance + +@item +calls @code{add-method!} to add this method to the relevant generic +function. +@end itemize + +@deffn syntax method (parameter @dots{}) body @dots{} +Make a method whose specializers are defined by the classes in +@var{parameter}s and whose procedure definition is constructed from the +@var{parameter} symbols and @var{body} forms. + +The @var{parameter} and @var{body} parameters should be as for +@code{define-method} (@pxref{Methods and Generic Functions,, +define-method}). +@end deffn + +@noindent +@code{method}: + +@itemize @bullet +@item +extracts formals and specializing classes from the @var{parameter}s, +defaulting the class for unspecialized parameters to @code{<top>} + +@item +creates a closure using the formals and the @var{body} forms + +@item +calls @code{make} with metaclass @code{<method>} and the specializers +and closure using the @code{#:specializers} and @code{#:procedure} +keywords. +@end itemize + +@deffn procedure make-method specializers procedure +Make a method using @var{specializers} and @var{procedure}. + +@var{specializers} should be a list of classes that specifies the +parameter combinations to which this method will be applicable. + +@var{procedure} should be the closure that will applied to the generic +function parameters when this method is invoked. +@end deffn + +@noindent +@code{make-method} is a simple wrapper around @code{make} with metaclass +@code{<method>}. + +@deffn generic add-method! target method +Generic function for adding method @var{method} to @var{target}. +@end deffn + +@deffn method add-method! (generic <generic>) (method <method>) +Add method @var{method} to the generic function @var{generic}. +@end deffn + +@deffn method add-method! (proc <procedure>) (method <method>) +If @var{proc} is a procedure with generic capability (@pxref{Extending +Primitives,, generic-capability?}), upgrade it to a primitive generic +and add @var{method} to its generic function definition. +@end deffn + +@deffn method add-method! (pg <primitive-generic>) (method <method>) +Add method @var{method} to the generic function definition of @var{pg}. + +Implementation: @code{(add-method! (primitive-generic-generic pg) method)}. +@end deffn + +@deffn method add-method! (whatever <top>) (method <method>) +Raise an error indicating that @var{whatever} is not a valid generic +function. +@end deffn + +@node Generic Function Internals +@subsection Generic Function Internals + +@code{define-generic} calls @code{ensure-generic} to upgrade a +pre-existing procedure value, or @code{make} with metaclass +@code{<generic>} to create a new generic function. + +@code{define-accessor} calls @code{ensure-accessor} to upgrade a +pre-existing procedure value, or @code{make-accessor} to create a new +accessor. + +@deffn procedure ensure-generic old-definition [name] +Return a generic function with name @var{name}, if possible by using or +upgrading @var{old-definition}. If unspecified, @var{name} defaults to +@code{#f}. + +If @var{old-definition} is already a generic function, it is returned +unchanged. + +If @var{old-definition} is a Scheme procedure or procedure-with-setter, +@code{ensure-generic} returns a new generic function that uses +@var{old-definition} for its default procedure and setter. + +Otherwise @code{ensure-generic} returns a new generic function with no +defaults and no methods. +@end deffn + +@deffn procedure make-generic [name] +Return a new generic function with name @code{(car @var{name})}. If +unspecified, @var{name} defaults to @code{#f}. +@end deffn + +@code{ensure-generic} calls @code{make} with metaclasses +@code{<generic>} and @code{<generic-with-setter>}, depending on the +previous value of the variable that it is trying to upgrade. + +@code{make-generic} is a simple wrapper for @code{make} with metaclass +@code{<generic>}. + +@deffn procedure ensure-accessor proc [name] +Return an accessor with name @var{name}, if possible by using or +upgrading @var{proc}. If unspecified, @var{name} defaults to @code{#f}. + +If @var{proc} is already an accessor, it is returned unchanged. + +If @var{proc} is a Scheme procedure, procedure-with-setter or generic +function, @code{ensure-accessor} returns an accessor that reuses the +reusable elements of @var{proc}. + +Otherwise @code{ensure-accessor} returns a new accessor with no defaults +and no methods. +@end deffn + +@deffn procedure make-accessor [name] +Return a new accessor with name @code{(car @var{name})}. If +unspecified, @var{name} defaults to @code{#f}. +@end deffn + +@code{ensure-accessor} calls @code{make} with +metaclass @code{<generic-with-setter>}, as well as calls to +@code{ensure-generic}, @code{make-accessor} and (tail recursively) +@code{ensure-accessor}. + +@code{make-accessor} calls @code{make} twice, first +with metaclass @code{<generic>} to create a generic function for the +setter, then with metaclass @code{<generic-with-setter>} to create the +accessor, passing the setter generic function as the value of the +@code{#:setter} keyword. + +@node Generic Function Invocation +@subsection 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. + +@noindent +@code{apply-generic} (generic) + +@itemize @bullet +@item +@code{no-method} (generic) + +@item +@code{compute-applicable-methods} (generic) + +@item +@code{sort-applicable-methods} (generic) + +@itemize @bullet +@item +@code{method-more-specific?} (generic) +@end itemize + +@item +@code{apply-methods} (generic) + +@itemize @bullet +@item +@code{apply-method} (generic) + +@item +@code{no-next-method} (generic) +@end itemize + +@item +@code{no-applicable-method} +@end itemize + +We do not yet have full documentation for these. Please refer to the +code (@file{oop/goops.scm}) for details. + + +@node Redefining a Class +@section Redefining a Class + +Suppose that a class @code{<my-class>} is defined using @code{define-class} +(@pxref{Class Definition,, define-class}), with slots that have +accessor functions, and that an application has created several instances +of @code{<my-class>} using @code{make} (@pxref{Instance Creation,, +make}). What then happens if @code{<my-class>} is redefined by calling +@code{define-class} again? + +@menu +* Redefinable Classes:: +* Default Class Redefinition Behaviour:: +* Customizing Class Redefinition:: +@end menu + +@node Redefinable Classes +@subsection 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 @emph{not} redefinable. A +redefinable class is an instance of @code{<redefinable-class>}; that is +to say, a class with @code{<redefinable-class>} as its metaclass. +Accordingly, to define a redefinable class, add @code{#:metaclass +<redefinable-class>} to its class definition: + +@example +(define-class <foo> () + #:metaclass <redefinable-class>) +@end example + +Note that any subclass of @code{<foo>} is also redefinable, without the +need to explicitly pass the @code{#:metaclass} argument, so you only +need to specify @code{#:metaclass} for the roots of your application's +class hierarchy. + +@example +(define-class <bar> (<foo>)) +(class-of <bar>) @result{} <redefinable-class> +@end example + +Note that prior to Guile 3.0, all GOOPS classes were redefinable in +theory. In practice, attempting to, for example, redefine +@code{<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. + +@node Default Class Redefinition Behaviour +@subsection Default Class Redefinition Behaviour + +When a class is defined using @code{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 @code{define}. However if +both the old and new bindings are redefinable classes (instances of +@code{<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. + +@itemize @bullet +@item +All existing direct instances of @code{<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 (@pxref{Instance +Creation,, make}). + +@item +All existing subclasses of @code{<my-class>} are redefined, as though +the @code{define-class} expressions that defined them were re-evaluated +following the redefinition of @code{<my-class>}, and the class +redefinition process described here is applied recursively to the +redefined subclasses. + +@item +Once all of its instances and subclasses have been updated, the class +metaobject previously bound to the variable @code{<my-class>} is no +longer needed and so can be allowed to be garbage collected. +@end itemize + +To keep things tidy, GOOPS also needs to do a little housekeeping on +methods that are associated with the redefined class. + +@itemize @bullet +@item +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. + +@item +Any generic function method that uses the old @code{<my-class>} metaobject +as one of its formal parameter specializers must be updated to refer to +the new @code{<my-class>} metaobject. (Whenever a new generic function +method is defined, @code{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.) +@end itemize + +If this class redefinition strategy strikes you as rather counter-intuitive, +bear in mind that it is derived from similar behaviour 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 behaviour, it can +be customized@dots{} + +@node Customizing Class Redefinition +@subsection Customizing Class Redefinition + +When @code{define-class} notices that a class is being redefined, it +constructs the new class metaobject as usual, then invokes the +@code{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 @code{<redefinable-class>}, class redefinition +behaviour can be customized by defining a @code{class-redefinition} +method that is specialized for the relevant metaclasses. + +@deffn generic class-redefinition +Handle the class redefinition from @var{old} to @var{new}, and return +the new class metaobject that should be bound to the variable specified +by @code{define-class}'s first argument. +@end deffn + +@deffn method class-redefinition (old <top>) (new <class>) +Not all classes are redefinable, and not all previous bindings are +classes. @xref{Redefinable Classes}. This default method just returns +@var{new}. +@end deffn + +@deffn method class-redefinition (old <redefinable-class>) (new <redefinable-class>) +This method implements GOOPS' default class redefinition behaviour, as +described in @ref{Default Class Redefinition Behaviour}. Returns the +metaobject for the new class definition. +@end deffn + +The @code{class-redefinition} method for classes with metaclass +@code{<redefinable-class>} calls the following generic functions, which +could of course be individually customized. + +@deffn generic remove-class-accessors! old +The default @code{remove-class-accessors!} method removes the accessor +methods of the old class from all classes which they specialize. +@end deffn + +@deffn generic update-direct-method! method old new +The default @code{update-direct-method!} method substitutes the new +class for the old in all methods specialized to the old class. +@end deffn + +@deffn generic update-direct-subclass! subclass old new +The default @code{update-direct-subclass!} method invokes +@code{class-redefinition} recursively to handle the redefinition of +subclasses. +@end deffn + +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 @code{class-redefinition} method that +is specialized for this metaclass: + +@example +(define-class <can-be-nameless> (<redefinable-class>)) + +(define-method (class-redefinition (old <can-be-nameless>) + (new <class>)) + new) +@end example + +When customization can be as easy as this, aren't you glad that GOOPS +implements the far more difficult strategy as its default! + + +@node Changing the Class of an Instance +@section 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 +@code{change-class}. + +More generally, you can change the class of an existing instance at any +time by invoking the generic function @code{change-class} with two +arguments: the instance and the new class. + +The default method for @code{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 (@pxref{Classes,, +slot-init-function}). + +@deffn generic change-class instance new-class +@end deffn + +@deffn {method} change-class (obj <object>) (new <redefinable-class>) +Modify instance @var{obj} to make it an instance of class @var{new}. +@var{obj} itself must already be an instance of a redefinable class. + +The value of each of @var{obj}'s slots is preserved only if a similarly named +slot exists in @var{new}; any other slot values are discarded. + +The slots in @var{new} that do not correspond to any of @var{obj}'s +pre-existing slots are initialized according to @var{new}'s slot definitions' +init functions. +@end deffn + +The default @code{change-class} method also invokes another generic +function, @code{update-instance-for-different-class}, as the last thing +that it does before returning. The applied +@code{update-instance-for-different-class} method can make any further +adjustments to @var{new-instance} that are required to complete or +modify the change of class. The return value from the applied method is +ignored. + +@deffn 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 +@code{update-instance-for-different-class} method does nothing. +@end deffn + +Customized change of class behaviour can be implemented by defining +@code{change-class} methods that are specialized either by the class +of the instances to be modified or by the metaclass of the new class. diff --git a/doc/ref/guile-invoke.texi b/doc/ref/guile-invoke.texi new file mode 100644 index 000000000..171a30ada --- /dev/null +++ b/doc/ref/guile-invoke.texi @@ -0,0 +1,426 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2005, 2010, 2011, 2013, 2014, +@c 2016 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Invoking Guile +@section Invoking Guile +@cindex invocation + +Many features of Guile depend on and can be changed by information that +the user provides either before or when Guile is started. Below is a +description of what information to provide and how to provide it. + +@menu +* Command-line Options:: Command-line options understood by Guile. +* Environment Variables:: Variables that affect Guile's behavior. +@end menu + +@node Command-line Options +@subsection Command-line Options +@cindex Command-line Options +@cindex command-line arguments +@cindex arguments (command line) +@cindex options (command line) +@cindex switches (command line) +@cindex startup (command-line arguments) +@cindex invocation (command-line arguments) + +Here we describe Guile's command-line processing in detail. Guile +processes its arguments from left to right, recognizing the switches +described below. For examples, see @ref{Scripting Examples}. + +@table @code + +@item @var{script} @var{arg...} +@itemx -s @var{script} @var{arg...} +@cindex script mode +By default, Guile will read a file named on the command line as a +script. Any command-line arguments @var{arg...} following @var{script} +become the script's arguments; the @code{command-line} function returns +a list of strings of the form @code{(@var{script} @var{arg...})}. + +It is possible to name a file using a leading hyphen, for example, +@file{-myfile.scm}. In this case, the file name must be preceded by +@option{-s} to tell Guile that a (script) file is being named. + +Scripts are read and evaluated as Scheme source code just as the +@code{load} function would. After loading @var{script}, Guile exits. + +@item -c @var{expr} @var{arg...} +@cindex evaluate expression, command-line argument +Evaluate @var{expr} as Scheme code, and then exit. Any command-line +arguments @var{arg...} following @var{expr} become command-line +arguments; the @code{command-line} function returns a list of strings of +the form @code{(@var{guile} @var{arg...})}, where @var{guile} is the +path of the Guile executable. + +@item -- @var{arg...} +Run interactively, prompting the user for expressions and evaluating +them. Any command-line arguments @var{arg...} following the @option{--} +become command-line arguments for the interactive session; the +@code{command-line} function returns a list of strings of the form +@code{(@var{guile} @var{arg...})}, where @var{guile} is the path of the +Guile executable. + +@item -L @var{directory} +Add @var{directory} to the front of Guile's module load path. The given +directories are searched in the order given on the command line and +before any directories in the @env{GUILE_LOAD_PATH} environment +variable. Paths added here are @emph{not} in effect during execution of +the user's @file{.guile} file. + +@item -C @var{directory} +Like @option{-L}, but adjusts the load path for @emph{compiled} files. + +@item -x @var{extension} +Add @var{extension} to the front of Guile's load extension list +(@pxref{Load Paths, @code{%load-extensions}}). The specified extensions +are tried in the order given on the command line, and before the default +load extensions. Extensions added here are @emph{not} in effect during +execution of the user's @file{.guile} file. + +@item -l @var{file} +Load Scheme source code from @var{file}, and continue processing the +command line. + +@item -e @var{function} +Make @var{function} the @dfn{entry point} of the script. After loading +the script file (with @option{-s}) or evaluating the expression (with +@option{-c}), apply @var{function} to a list containing the program name +and the command-line arguments---the list provided by the +@code{command-line} function. + +A @option{-e} switch can appear anywhere in the argument list, but Guile +always invokes the @var{function} as the @emph{last} action it performs. +This is weird, but because of the way script invocation works under +POSIX, the @option{-s} option must always come last in the list. + +The @var{function} is most often a simple symbol that names a function +that is defined in the script. It can also be of the form @code{(@@ +@var{module-name} @var{symbol})}, and in that case, the symbol is +looked up in the module named @var{module-name}. + +As a shorthand you can use the form @code{(symbol ...)}, that is, a list +of only symbols that doesn't start with @code{@@}. It is equivalent to +@code{(@@ @var{module-name} main)}, where @var{module-name} is +@code{(symbol ...)} form. @xref{Using Guile Modules} and @ref{Scripting +Examples}. + +@item -ds +Treat a final @option{-s} option as if it occurred at this point in the +command line; load the script here. + +This switch is necessary because, although the POSIX script invocation +mechanism effectively requires the @option{-s} option to appear last, the +programmer may well want to run the script before other actions +requested on the command line. For examples, see @ref{Scripting +Examples}. + +@item \ +Read more command-line arguments, starting from the second line of the +script file. @xref{The Meta Switch}. + +@item --use-srfi=@var{list} +@cindex loading srfi modules (command line) +The option @option{--use-srfi} expects a comma-separated list of numbers, +each representing a SRFI module to be loaded into the interpreter +before evaluating a script file or starting the REPL. Additionally, +the feature identifier for the loaded SRFIs is recognized by +the procedure @code{cond-expand} when this option is used. + +Here is an example that loads the modules SRFI-8 ('receive') and SRFI-13 +('string library') before the GUILE interpreter is started: + +@example +guile --use-srfi=8,13 +@end example + +@item --debug +@cindex debugging virtual machine (command line) +Start with the debugging virtual machine (VM) engine. Using the +debugging VM will enable support for VM hooks, which are needed for +tracing, breakpoints, and accurate call counts when profiling. The +debugging VM is slower than the regular VM, though, by about ten +percent. @xref{VM Hooks}, for more information. + +By default, the debugging VM engine is only used when entering an +interactive session. When executing a script with @option{-s} or +@option{-c}, the normal, faster VM is used by default. + +@vnew{1.8} +@item --no-debug +@cindex debugging virtual machine (command line) +Do not use the debugging VM engine, even when entering an interactive +session. + +Note that, despite the name, Guile running with @option{--no-debug} +@emph{does} support the usual debugging facilities, such as printing a +detailed backtrace upon error. The only difference with +@option{--debug} is lack of support for VM hooks and the facilities that +build upon it (see above). + +@item -q +@cindex init file, not loading +@cindex @file{.guile} file, not loading +Do not load the initialization file, @file{.guile}. This option only +has an effect when running interactively; running scripts does not load +the @file{.guile} file. @xref{Init File}. + +@item --listen[=@var{p}] +While this program runs, listen on a local port or a path for REPL +clients. If @var{p} starts with a number, it is assumed to be a local +port on which to listen. If it starts with a forward slash, it is +assumed to be the file name of a UNIX domain socket on which to listen. + +If @var{p} is not given, the default is local port 37146. If you look +at it upside down, it almost spells ``Guile''. If you have netcat +installed, you should be able to @kbd{nc localhost 37146} and get a +Guile prompt. Alternately you can fire up Emacs and connect to the +process; see @ref{Using Guile in Emacs} for more details. + +@quotation Note +Opening a port allows anyone who can connect to that port to do anything +Guile can do, as the user +that the Guile process is running as. Do not use @option{--listen} on +multi-user machines. Of course, if you do not pass @option{--listen} to +Guile, no port will be opened. + +Guile protects against the +@uref{https://en.wikipedia.org/wiki/Inter-protocol_exploitation, +@dfn{HTTP inter-protocol exploitation attack}}, a scenario whereby an +attacker can, @i{via} an HTML page, cause a web browser to send data to +TCP servers listening on a loopback interface or private network. +Nevertheless, you are advised to use UNIX domain sockets, as in +@code{--listen=/some/local/file}, whenever possible. +@end quotation + +That said, @option{--listen} is great for interactive debugging and +development. + +@vnew{2.0} + +@item --auto-compile +Compile source files automatically (default behavior). + +@vnew{2.0.1} + +@item --fresh-auto-compile +Treat the auto-compilation cache as invalid, forcing recompilation. + +@vnew{2.0} + +@item --no-auto-compile +Disable automatic source file compilation. + +@vnew{2.0.8} + +@item --language=@var{lang} +For the remainder of the command line arguments, assume that files +mentioned with @code{-l} and expressions passed with @code{-c} are +written in @var{lang}. @var{lang} must be the name of one of the +languages supported by the compiler (@pxref{Compiler Tower}). When run +interactively, set the REPL's language to @var{lang} (@pxref{Using Guile +Interactively}). + +The default language is @code{scheme}; other interesting values include +@code{elisp} (for Emacs Lisp), and @code{ecmascript}. + +The example below shows the evaluation of expressions in Scheme, Emacs +Lisp, and ECMAScript: + +@example +guile -c "(apply + '(1 2))" +guile --language=elisp -c "(= (funcall (symbol-function '+) 1 2) 3)" +guile --language=ecmascript -c '(function (x) @{ return x * x; @})(2);' +@end example + +To load a file written in Scheme and one written in Emacs Lisp, and then +start a Scheme REPL, type: + +@example +guile -l foo.scm --language=elisp -l foo.el --language=scheme +@end example + +@vnew{2.0} + +@item -h@r{, }--help +Display help on invoking Guile, and then exit. + +@item -v@r{, }--version +Display the current version of Guile, and then exit. + +@end table + +@node Environment Variables +@subsection Environment Variables +@cindex environment variables +@cindex shell +@cindex initialization +The @dfn{environment} is a feature of the operating system; it consists +of a collection of variables with names and values. Each variable is +called an @dfn{environment variable} (or, sometimes, a ``shell +variable''); environment variable names are case-sensitive, and it is +conventional to use upper-case letters only. The values are all text +strings, even those that are written as numerals. (Note that here we +are referring to names and values that are defined in the operating +system shell from which Guile is invoked. This is not the same as a +Scheme environment that is defined within a running instance of Guile. +For a description of Scheme environments, @pxref{About Environments}.) + +How to set environment variables before starting Guile depends on the +operating system and, especially, the shell that you are using. For +example, here is how to tell Guile to provide detailed warning messages +about deprecated features by setting @env{GUILE_WARN_DEPRECATED} using +Bash: + +@example +$ export GUILE_WARN_DEPRECATED="detailed" +$ guile +@end example + +@noindent +Or, detailed warnings can be turned on for a single invocation using: + +@example +$ env GUILE_WARN_DEPRECATED="detailed" guile +@end example + +If you wish to retrieve or change the value of the shell environment +variables that affect the run-time behavior of Guile from within a +running instance of Guile, see @ref{Runtime Environment}. + +Here are the environment variables that affect the run-time behavior of +Guile: + +@table @env +@item GUILE_AUTO_COMPILE +@vindex GUILE_AUTO_COMPILE +This is a flag that can be used to tell Guile whether or not to compile +Scheme source files automatically. Starting with Guile 2.0, Scheme +source files will be compiled automatically, by default. + +If a compiled (@file{.go}) file corresponding to a @file{.scm} file is +not found or is not newer than the @file{.scm} file, the @file{.scm} +file will be compiled on the fly, and the resulting @file{.go} file +stored away. An advisory note will be printed on the console. + +Compiled files will be stored in the directory +@file{$XDG_CACHE_HOME/@/guile/@/ccache}, where @env{XDG_CACHE_HOME} +defaults to the directory @file{$HOME/.cache}. This directory will be +created if it does not already exist. + +Note that this mechanism depends on the timestamp of the @file{.go} file +being newer than that of the @file{.scm} file; if the @file{.scm} or +@file{.go} files are moved after installation, care should be taken to +preserve their original timestamps. + +Set @env{GUILE_AUTO_COMPILE} to zero (0), to prevent Scheme files from +being compiled automatically. Set this variable to ``fresh'' to tell +Guile to compile Scheme files whether they are newer than the compiled +files or not. + +@xref{Compilation}. + +@item GUILE_HISTORY +@vindex GUILE_HISTORY +This variable names the file that holds the Guile REPL command history. +You can specify a different history file by setting this environment +variable. By default, the history file is @file{$HOME/.guile_history}. + +@item GUILE_INSTALL_LOCALE +@vindex GUILE_INSTALL_LOCALE +This is a flag that can be used to tell Guile whether or not to install +the current locale at startup, via a call to @code{(setlocale LC_ALL +"")}@footnote{The @code{GUILE_INSTALL_LOCALE} environment variable was +ignored in Guile versions prior to 2.0.9.}. @xref{Locales}, for more +information on locales. + +You may explicitly indicate that you do not want to install +the locale by setting @env{GUILE_INSTALL_LOCALE} to @code{0}, or +explicitly enable it by setting the variable to @code{1}. + +Usually, installing the current locale is the right thing to do. It +allows Guile to correctly parse and print strings with non-ASCII +characters. Therefore, this option is on by default. + +@item GUILE_STACK_SIZE +@vindex GUILE_STACK_SIZE +Guile currently has a limited stack size for Scheme computations. +Attempting to call too many nested functions will signal an error. This +is good to detect infinite recursion, but sometimes the limit is reached +for normal computations. This environment variable, if set to a +positive integer, specifies the number of Scheme value slots to allocate +for the stack. + +In the future we will implement stacks that can grow and shrink, but for +now this hack will have to do. + +@item GUILE_LOAD_COMPILED_PATH +@vindex GUILE_LOAD_COMPILED_PATH +This variable may be used to augment the path that is searched for +compiled Scheme files (@file{.go} files) when loading. Its value should +be a colon-separated list of directories. If it contains the special +path component @code{...} (ellipsis), then the default path is put in +place of the ellipsis, otherwise the default path is placed at the end. +The result is stored in @code{%load-compiled-path} (@pxref{Load Paths}). + +Here is an example using the Bash shell that adds the current directory, +@file{.}, and the relative directory @file{../my-library} to +@code{%load-compiled-path}: + +@example +$ export GUILE_LOAD_COMPILED_PATH=".:../my-library" +$ guile -c '(display %load-compiled-path) (newline)' +(. ../my-library /usr/local/lib/guile/3.0/ccache) +@end example + +@item GUILE_LOAD_PATH +@vindex GUILE_LOAD_PATH +This variable may be used to augment the path that is searched for +Scheme files when loading. Its value should be a colon-separated list +of directories. If it contains the special path component @code{...} +(ellipsis), then the default path is put in place of the ellipsis, +otherwise the default path is placed at the end. The result is stored +in @code{%load-path} (@pxref{Load Paths}). + +Here is an example using the Bash shell that prepends the current +directory to @code{%load-path}, and adds the relative directory +@file{../srfi} to the end: + +@example +$ env GUILE_LOAD_PATH=".:...:../srfi" \ +guile -c '(display %load-path) (newline)' +(. /usr/local/share/guile/3.0 \ +/usr/local/share/guile/site/3.0 \ +/usr/local/share/guile/site \ +/usr/local/share/guile \ +../srfi) +@end example + +(Note: The line breaks, above, are for documentation purposes only, and +not required in the actual example.) + +@item GUILE_WARN_DEPRECATED +@vindex GUILE_WARN_DEPRECATED +As Guile evolves, some features will be eliminated or replaced by newer +features. To help users migrate their code as this evolution occurs, +Guile will issue warning messages about code that uses features that +have been marked for eventual elimination. @env{GUILE_WARN_DEPRECATED} +can be set to ``no'' to tell Guile not to display these warning +messages, or set to ``detailed'' to tell Guile to display more lengthy +messages describing the warning. @xref{Deprecation}. + +@item HOME +@vindex HOME +Guile uses the environment variable @env{HOME}, the name of your home +directory, to locate various files, such as @file{.guile} or +@file{.guile_history}. + +@end table + +@c Local Variables: +@c mode: texinfo +@c TeX-master: "guile" +@c End: diff --git a/doc/ref/guile.texi b/doc/ref/guile.texi new file mode 100644 index 000000000..488416aad --- /dev/null +++ b/doc/ref/guile.texi @@ -0,0 +1,445 @@ +\input texinfo +@c -*-texinfo-*- +@c %**start of header +@setfilename guile.info +@documentencoding UTF-8 +@settitle Guile Reference Manual +@set guile +@set MANUAL-REVISION 1 +@c %**end of header +@include version.texi +@include effective-version.texi + +@copying +This manual documents Guile version @value{VERSION}. + +Copyright (C) 1996-1997, 2000-2005, 2009-2018 Free Software Foundation, +Inc. + +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.'' +@end copying + + +@c Notes +@c +@c We no longer use the category "primitive" to distinguish C-defined +@c Scheme procedures from those defined in Scheme. Instead, the +@c reference manual now includes a C declaration as well as a Scheme +@c declaration for each procedure that is available in both Scheme and +@c C. +@c +@c When adding a new reference entry to the Guile manual, please +@c document it with @deffn using one of the following categories: +@c +@c {Scheme Procedure} +@c {Scheme Syntax} +@c {C Function} +@c {C Macro} +@c +@c If the entry is for a new primitive, it should have both a @deffn +@c {Scheme Procedure} line and a @deffnx {C Function} line; see the +@c manual source for plenty of existing examples of this. +@c +@c For {C Function} entries where the return type and all parameter +@c types are SCM, we omit the SCMs. This is easier to read and also +@c gets round the problem that Texinfo doesn't allow a @deftypefnx +@c inside a @deffn. +@c +@c For a list of Guile primitives that are not yet incorporated into the +@c reference manual, see the file `new-docstrings.texi', which holds all +@c the docstrings snarfed from the libguile C sources for primitives +@c that are not in the reference manual. If you have worked with some +@c of these concepts, implemented them, or just happen to know what they +@c do, please write up a little explanation -- it would be a big help. +@c Alternatively, if you know of any reason why some of these should +@c *not* go in the manual, please let the mailing list +@c <guile-devel@gnu.org> know. + +@c Define indices that are used in the Guile Scheme part of the +@c reference manual to group stuff according to whether it is R5RS or a +@c Guile extension. +@defcodeindex rn + +@c vnew - For (some) new items, indicates the Guile version in which +@c item first appeared. In future, this could be made to expand to +@c something like a "New in Guile 45!" banner. +@macro vnew{VERSION} +@end macro + + +@c The following, @le{} and @ge{}, are standard tex directives, given +@c definitions for use in non-tex. +@c +@ifnottex +@macro ge +>= +@end macro +@macro le +<= +@end macro +@end ifnottex + +@c @cross{} is a \times symbol in tex, or an "x" in info. In tex it works +@c inside or outside $ $. +@tex +\gdef\cross{\ifmmode\times\else$\times$\fi} +@end tex +@ifnottex +@macro cross +x +@end macro +@end ifnottex + +@c @m{T,N} is $T$ in tex or @math{N} otherwise. This is an easy way to give +@c different forms for math in tex and info. +@iftex +@macro m {T,N} +@tex$\T\$@end tex +@end macro +@end iftex +@ifnottex +@macro m {T,N} +@math{\N\} +@end macro +@end ifnottex + +@c @nicode{S} is plain S in info, or @code{S} elsewhere. This can be used +@c when the quotes that @code{} gives in info aren't wanted, but the +@c fontification in tex or html is wanted. @alias is used rather +@c than @macro because backslashes don't work properly in an @macro. +@ifinfo +@alias nicode=asis +@end ifinfo +@ifnotinfo +@alias nicode=code +@end ifnotinfo + + +@c @iftex +@c @cropmarks +@c @end iftex + +@dircategory The Algorithmic Language Scheme +@direntry +* Guile Reference: (guile). The Guile reference manual. +@end direntry + +@setchapternewpage odd + +@titlepage +@sp 10 +@comment The title is printed in a large font. +@title Guile Reference Manual +@subtitle Edition @value{EDITION}, revision @value{MANUAL-REVISION}, for use with Guile @value{VERSION} +@c @subtitle $Id: guile.texi,v 1.49 2008-03-19 22:51:23 ossau Exp $ + +@c See preface.texi for the list of authors +@author The Guile Developers + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@c @smallbook +@finalout +@headings double + +@c Where to find Guile examples. +@set example-dir doc/examples + +@ifnottex +@node Top, Preface, (dir), (dir) +@top The Guile Reference Manual + +@insertcopying +@sp 1 +@end ifnottex + +@menu + +* Preface:: +* Introduction:: + +* Hello Guile!:: +* Hello Scheme!:: + +* Programming in Scheme:: +* Programming in C:: + +* API Reference:: + +* Guile Modules:: + +* GOOPS:: + +* Guile Implementation:: + +Appendices + +* GNU Free Documentation License:: The license of this manual. + +Indices + +* Concept Index:: +* Procedure Index:: +* Variable Index:: +* Type Index:: +* R5RS Index:: + +@end menu + +@contents + +@include preface.texi + +@include intro.texi + +@include tour.texi + +@include scheme-ideas.texi +@include scheme-reading.texi + +@node Programming in Scheme +@chapter Programming in Scheme + +Guile's core language is Scheme, and a lot can be achieved simply by using Guile +to write and run Scheme programs --- as opposed to having to dive into C code. +In this part of the manual, we explain how to use Guile in this mode, and +describe the tools that Guile provides to help you with script writing, +debugging, and packaging your programs for distribution. + +For detailed reference information on the variables, functions, and so +on that make up Guile's application programming interface (API), see +@ref{API Reference}. + +@menu +* Guile Scheme:: Guile's implementation of Scheme. +* Invoking Guile:: Selecting optional features when starting Guile. +* Guile Scripting:: How to write Guile scripts. +* Using Guile Interactively:: Guile's REPL features. +* Using Guile in Emacs:: Guile and Emacs. +* Using Guile Tools:: A guild of scheming wizards. +* Installing Site Packages:: Installing Scheme code. +@end menu + +@include scheme-intro.texi +@include guile-invoke.texi +@include scheme-scripts.texi +@include scheme-using.texi + +@node Programming in C +@chapter Programming in C + +This part of the manual explains the general concepts that you need to +understand when interfacing to Guile from C. You will learn about how +the latent typing of Scheme is embedded into the static typing of C, how +the garbage collection of Guile is made available to C code, and how +continuations influence the control flow in a C program. + +This knowledge should make it straightforward to add new functions to +Guile that can be called from Scheme. Adding new data types is also +possible and is done by defining @dfn{foreign objects}. + +The @ref{Programming Overview} section of this part contains general +musings and guidelines about programming with Guile. It explores +different ways to design a program around Guile, or how to embed Guile +into existing programs. + +For a pedagogical yet detailed explanation of how the data representation of +Guile is implemented, @xref{Data Representation}. You don't need to know the +details given there to use Guile from C, but they are useful when you want to +modify Guile itself or when you are just curious about how it is all done. + +For detailed reference information on the variables, functions +etc. that make up Guile's application programming interface (API), +@xref{API Reference}. + +@menu +* Parallel Installations:: Finding the right Guile. +* Linking Programs With Guile:: More precisely, with the libguile library. +* Linking Guile with Libraries:: To extend Guile itself. +* General Libguile Concepts:: General concepts for using libguile. +* Defining New Foreign Object Types:: Adding new types to Guile. +* Function Snarfing:: A way to define new functions. +* Programming Overview:: An overview of Guile programming. +* Autoconf Support:: Putting m4 to good use. +@end menu + +@include libguile-parallel.texi +@include libguile-linking.texi +@include libguile-extensions.texi +@include libguile-concepts.texi +@include libguile-foreign-objects.texi +@include libguile-snarf.texi +@include libguile-program.texi +@include libguile-autoconf.texi + + +@node API Reference +@chapter API Reference + +Guile provides an application programming interface (@dfn{API}) to +developers in two core languages: Scheme and C. This part of the manual +contains reference documentation for all of the functionality that is +available through both Scheme and C interfaces. + +@menu +* API Overview:: Overview of the Guile API. +* Deprecation:: Obsolete back-compatible APIs. +* The SCM Type:: The fundamental data type for C code. +* Initialization:: Initializing Guile. +* Snarfing Macros:: Macros for snarfing initialization actions. +* Data Types:: Representing values in Guile. +* Foreign Objects:: Defining new data types in C. +* Smobs:: Use foreign objects instead. +* Procedures:: Procedures. +* Macros:: Extending the syntax of Scheme. +* Utility Functions:: General utility functions. +* Binding Constructs:: Definitions and variable bindings. +* Control Mechanisms:: Controlling the flow of program execution. +* Input and Output:: Ports, reading and writing. +* Regular Expressions:: Pattern matching and substitution. +* LALR(1) Parsing:: Generating LALR(1) parsers. +* PEG Parsing:: Parsing Expression Grammars. +* Read/Load/Eval/Compile:: Reading and evaluating Scheme code. +* Memory Management:: Memory management and garbage collection. +* Modules:: Designing reusable code libraries. +* Foreign Function Interface:: Interacting with C procedures and data. +* Scheduling:: Threads, mutexes, asyncs and dynamic roots. +* Options and Config:: Configuration, features and runtime options. +* Other Languages:: Emacs Lisp, ECMAScript, and more. +* Internationalization:: Support for gettext, etc. +* Debugging:: Debugging infrastructure and Scheme interface. +* Code Coverage:: Gathering code coverage data. +@end menu + +@include api-overview.texi +@include api-deprecated.texi +@include api-scm.texi +@include api-init.texi +@include api-snarf.texi +@include api-data.texi +@include api-foreign-objects.texi +@include api-smobs.texi +@include api-procedures.texi +@include api-macros.texi +@include api-utility.texi +@include api-binding.texi +@include api-control.texi +@include api-io.texi +@include api-regex.texi +@include api-lalr.texi +@include api-peg.texi +@include api-evaluation.texi +@include api-memory.texi +@include api-modules.texi +@include api-foreign.texi +@include api-scheduling.texi +@c object orientation support here +@include api-options.texi +@include api-languages.texi +@include api-i18n.texi +@include api-debug.texi +@include api-coverage.texi + +@node Guile Modules +@chapter Guile Modules + +@menu +* SLIB:: Using the SLIB Scheme library. +* POSIX:: POSIX system calls and networking. +* Web:: HTTP, the web, and all that. +* getopt-long:: Command line handling. +* SRFI Support:: Support for various SRFIs. +* R6RS Support:: Modules defined by the R6RS. +* Pattern Matching:: Generic pattern matching constructs. +* Readline Support:: Module for using the readline library. +* Pretty Printing:: Nicely formatting Scheme objects for output. +* Formatted Output:: The @code{format} procedure. +* File Tree Walk:: Traversing the file system. +* Queues:: First-in first-out queuing. +* Streams:: Sequences of values. +* Buffered Input:: Ports made from a reader function. +* Expect:: Controlling interactive programs with Guile. +* sxml-match:: Pattern matching of SXML. +* The Scheme shell (scsh):: Using scsh interfaces in Guile. +* Curried Definitions:: Extended @code{define} syntax. +* Statprof:: An easy-to-use statistical profiler. +* SXML:: Parsing, transforming, and serializing XML. +* Texinfo Processing:: Munging documents written in Texinfo. +@end menu + +@include slib.texi +@include posix.texi +@include web.texi +@include mod-getopt-long.texi +@include srfi-modules.texi +@include r6rs.texi +@include match.texi +@include repl-modules.texi +@include misc-modules.texi +@include expect.texi + +@c XXX: Would be nicer if it were close to the (sxml simple) documentation. +@include sxml-match.texi + +@include scsh.texi +@include curried.texi + +@include statprof.texi +@include sxml.texi +@include texinfo.texi + +@include goops.texi + +@node Guile Implementation +@chapter 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@footnote{PAIP is the common abbreviation for @cite{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 @uref{http://norvig.com/Lisp-retro.html}.}, ``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. +@end menu + +@include history.texi +@include data-rep.texi +@include vm.texi +@include compiler.texi + +@node GNU Free Documentation License +@appendix GNU Free Documentation License + +@include fdl.texi + +@include indices.texi +@include scheme-indices.texi + +@bye diff --git a/doc/ref/hierarchy.dot b/doc/ref/hierarchy.dot new file mode 100644 index 000000000..f0d9daf8e --- /dev/null +++ b/doc/ref/hierarchy.dot @@ -0,0 +1,21 @@ +/* + * Process this file with graphviz to produce hierarchy.[png,eps] + * e.g. dot hierarchy.dot -Tpng > hierarchy.png + */ +digraph hierarchy { + graph [rankdir="BT"]; + node [shape="none"]; + F -> D + F -> E + D -> A + E -> A + D -> B + E -> C + A -> "<object>" + B -> "<object>" + C -> "<object>" + "<object>" -> "<top>" + "<pair>" -> "<top>" + "<procedure>" -> "<top>" + "<integer>" -> "<real>" -> "<complex>" -> "<number>" -> "<top>" +} diff --git a/doc/ref/hierarchy.eps b/doc/ref/hierarchy.eps new file mode 100644 index 000000000..d9e896ccf --- /dev/null +++ b/doc/ref/hierarchy.eps @@ -0,0 +1,601 @@ +%!PS-Adobe-3.0 +%%Creator: graphviz version 2.26.3 (20100126.1600) +%%Title: hierarchy +%%Pages: (atend) +%%BoundingBox: (atend) +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 452 368 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 416 332 boxprim clip newpath +1 1 set_scale 0 rotate 40 41 translate +% F +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +94.5 13.4 moveto 9 (F) alignedtext +grestore +% D +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +57.5 85.4 moveto 11 (D) alignedtext +grestore +% F->D +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 89.92 36.17 moveto +85.94 44.12 81.18 53.63 76.79 62.43 curveto +stroke +0 0 0 edgecolor +newpath 73.55 61.08 moveto +72.21 71.59 lineto +79.81 64.21 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 73.55 61.08 moveto +72.21 71.59 lineto +79.81 64.21 lineto +closepath stroke +grestore +% E +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +130 85.4 moveto 10 (E) alignedtext +grestore +% F->E +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 108.08 36.17 moveto +112.06 44.12 116.82 53.63 121.21 62.43 curveto +stroke +0 0 0 edgecolor +newpath 118.19 64.21 moveto +125.79 71.59 lineto +124.45 61.08 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 118.19 64.21 moveto +125.79 71.59 lineto +124.45 61.08 lineto +closepath stroke +grestore +% A +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +93.5 157.4 moveto 11 (A) alignedtext +grestore +% D->A +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 72.08 108.17 moveto +76.06 116.12 80.82 125.63 85.21 134.43 curveto +stroke +0 0 0 edgecolor +newpath 82.19 136.21 moveto +89.79 143.59 lineto +88.45 133.08 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 82.19 136.21 moveto +89.79 143.59 lineto +88.45 133.08 lineto +closepath stroke +grestore +% B +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +22 157.4 moveto 10 (B) alignedtext +grestore +% D->B +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 53.92 108.17 moveto +49.94 116.12 45.18 125.63 40.79 134.43 curveto +stroke +0 0 0 edgecolor +newpath 37.55 133.08 moveto +36.21 143.59 lineto +43.81 136.21 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 37.55 133.08 moveto +36.21 143.59 lineto +43.81 136.21 lineto +closepath stroke +grestore +% E->A +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 125.92 108.17 moveto +121.94 116.12 117.18 125.63 112.79 134.43 curveto +stroke +0 0 0 edgecolor +newpath 109.55 133.08 moveto +108.21 143.59 lineto +115.81 136.21 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 109.55 133.08 moveto +108.21 143.59 lineto +115.81 136.21 lineto +closepath stroke +grestore +% C +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +166 157.4 moveto 10 (C) alignedtext +grestore +% E->C +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 144.08 108.17 moveto +148.06 116.12 152.82 125.63 157.21 134.43 curveto +stroke +0 0 0 edgecolor +newpath 154.19 136.21 moveto +161.79 143.59 lineto +160.45 133.08 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 154.19 136.21 moveto +161.79 143.59 lineto +160.45 133.08 lineto +closepath stroke +grestore +% <object> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +73.5 229.4 moveto 51 (<object>) alignedtext +grestore +% A-><object> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 99 180.17 moveto +99 187.87 99 197.03 99 205.58 curveto +stroke +0 0 0 edgecolor +newpath 95.5 205.59 moveto +99 215.59 lineto +102.5 205.59 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 95.5 205.59 moveto +99 215.59 lineto +102.5 205.59 lineto +closepath stroke +grestore +% B-><object> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 45.17 180.17 moveto +53.72 188.72 64.06 199.06 73.38 208.38 curveto +stroke +0 0 0 edgecolor +newpath 71.04 210.99 moveto +80.59 215.59 lineto +75.99 206.04 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 71.04 210.99 moveto +80.59 215.59 lineto +75.99 206.04 lineto +closepath stroke +grestore +% C-><object> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 152.83 180.17 moveto +144.28 188.72 133.94 199.06 124.62 208.38 curveto +stroke +0 0 0 edgecolor +newpath 122.01 206.04 moveto +117.41 215.59 lineto +126.96 210.99 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 122.01 206.04 moveto +117.41 215.59 lineto +126.96 210.99 lineto +closepath stroke +grestore +% <top> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +205.5 301.4 moveto 35 (<top>) alignedtext +grestore +% <object>-><top> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 130.29 252.17 moveto +147.52 262.17 168.98 274.63 186.92 285.05 curveto +stroke +0 0 0 edgecolor +newpath 185.53 288.29 moveto +195.93 290.28 lineto +189.04 282.23 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 185.53 288.29 moveto +195.93 290.28 lineto +189.04 282.23 lineto +closepath stroke +grestore +% <pair> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +158 229.4 moveto 40 (<pair>) alignedtext +grestore +% <pair>-><top> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 189.36 252.17 moveto +194.43 260.29 200.52 270.04 206.12 278.99 curveto +stroke +0 0 0 edgecolor +newpath 203.22 280.96 moveto +211.49 287.59 lineto +209.16 277.25 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 203.22 280.96 moveto +211.49 287.59 lineto +209.16 277.25 lineto +closepath stroke +grestore +% <procedure> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +231.5 229.4 moveto 73 (<procedure>) alignedtext +grestore +% <procedure>-><top> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 256.64 252.17 moveto +251.57 260.29 245.48 270.04 239.88 278.99 curveto +stroke +0 0 0 edgecolor +newpath 236.84 277.25 moveto +234.51 287.59 lineto +242.78 280.96 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 236.84 277.25 moveto +234.51 287.59 lineto +242.78 280.96 lineto +closepath stroke +grestore +% <integer> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +339.5 13.4 moveto 57 (<integer>) alignedtext +grestore +% <real> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +348.5 85.4 moveto 39 (<real>) alignedtext +grestore +% <integer>-><real> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 368 36.17 moveto +368 43.87 368 53.03 368 61.58 curveto +stroke +0 0 0 edgecolor +newpath 364.5 61.59 moveto +368 71.59 lineto +371.5 61.59 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 364.5 61.59 moveto +368 71.59 lineto +371.5 61.59 lineto +closepath stroke +grestore +% <complex> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +336 157.4 moveto 64 (<complex>) alignedtext +grestore +% <real>-><complex> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 368 108.17 moveto +368 115.87 368 125.03 368 133.58 curveto +stroke +0 0 0 edgecolor +newpath 364.5 133.59 moveto +368 143.59 lineto +371.5 133.59 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 364.5 133.59 moveto +368 143.59 lineto +371.5 133.59 lineto +closepath stroke +grestore +% <number> +gsave +0 0 0 nodecolor +14 /Times-Roman set_font +337.5 229.4 moveto 61 (<number>) alignedtext +grestore +% <complex>-><number> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 368 180.17 moveto +368 187.87 368 197.03 368 205.58 curveto +stroke +0 0 0 edgecolor +newpath 364.5 205.59 moveto +368 215.59 lineto +371.5 205.59 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 364.5 205.59 moveto +368 215.59 lineto +371.5 205.59 lineto +closepath stroke +grestore +% <number>-><top> +gsave +1 setlinewidth +0 0 0 edgecolor +newpath 331.41 252.17 moveto +309.39 263.1 281.45 276.98 259.45 287.9 curveto +stroke +0 0 0 edgecolor +newpath 257.82 284.8 moveto +250.42 292.38 lineto +260.94 291.07 lineto +closepath fill +1 setlinewidth +solid +0 0 0 edgecolor +newpath 257.82 284.8 moveto +250.42 292.38 lineto +260.94 291.07 lineto +closepath stroke +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +%%Pages: 1 +%%BoundingBox: 36 36 452 368 +end +restore +%%EOF diff --git a/doc/ref/hierarchy.pdf b/doc/ref/hierarchy.pdf Binary files differnew file mode 100644 index 000000000..8c02d7a56 --- /dev/null +++ b/doc/ref/hierarchy.pdf diff --git a/doc/ref/hierarchy.png b/doc/ref/hierarchy.png Binary files differnew file mode 100644 index 000000000..e3a516164 --- /dev/null +++ b/doc/ref/hierarchy.png diff --git a/doc/ref/hierarchy.txt b/doc/ref/hierarchy.txt new file mode 100644 index 000000000..c7992df7b --- /dev/null +++ b/doc/ref/hierarchy.txt @@ -0,0 +1,14 @@ + <top> + / \\\_____________________ + / \\___________ \ + / \ \ \ + <object> <pair> <procedure> <number> + / | \ | + / | \ | + A B C <complex> + |\__/__ | | + \ / \ / | + D E <real> + \ / | + F | + <integer> diff --git a/doc/ref/history.texi b/doc/ref/history.texi new file mode 100644 index 000000000..d23d5a08d --- /dev/null +++ b/doc/ref/history.texi @@ -0,0 +1,293 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008, 2010, 2011, 2013, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node History +@section 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:: +@end menu + +@node The Emacs Thesis +@subsection 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 @emph{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. + +@node Early Days +@subsection 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, Jim Blandy +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. + +@node A Scheme of Many Maintainers +@subsection 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, Vollmer had mostly moved on to +other things, so Neil Jerram and Ludovic Court@`es +stepped up to take on the primary maintenance responsibility. Jerram and +Court@`es were joined by Andy Wingo in late 2009. + +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. + +@node A Timeline of Selected Guile Releases +@subsection A Timeline of Selected Guile Releases + +@table @asis +@item guile-i --- 4 February 1995 +SCM, turned into a library. + +@item 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. + +@item 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. + +@item 1.0 --- 5 January 1997 +@code{#f} was distinguished from @code{'()}. 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. + +@item 1.1 --- 16 May 1997 +@itemx 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. + +@item 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. + +@item 1.3.2 --- 20 August 1999 +@itemx 1.3.4 --- 25 September 1999 +@itemx 1.4 --- 21 June 2000 +A long list of lispy features were added: hooks, Common Lisp's +@code{format}, optional and keyword procedure arguments, +@code{getopt-long}, sorting, random numbers, and many other fixes and +enhancements. Guile also gained an interactive debugger, interactive +help, and better backtraces. + +@item 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. + +@item 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. + +@item 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. + +@item 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. + +@item 3.0 -- early 2019 (unreleased at time of writing) +Guile gained support for native code generation via a simple +just-in-time (JIT) compiler, further improving the speed of its virtual +machine. +@end table + +@node Status +@subsection 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 @code{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. + +And then 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, there is another axis of crystallization, the axis between +different Scheme implementations. Guile does not yet support the latest +Scheme standard, R7RS, and should do so. Like all standards, R7RS is +imperfect, but supporting it will allow more code to run on Guile +without modification, and will allow Guile hackers to produce code +compatible with other schemes. Help in this regard would be much +appreciated. diff --git a/doc/ref/indices.texi b/doc/ref/indices.texi new file mode 100644 index 000000000..afe571f26 --- /dev/null +++ b/doc/ref/indices.texi @@ -0,0 +1,59 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node Concept Index +@unnumbered Concept Index + +This index contains concepts, keywords and non-Schemey names for several +features, to make it easier to locate the desired sections. + +@printindex cp + + +@page +@node Procedure Index +@unnumbered Procedure Index + +@c FIXME::martin: Review me! + +This is an alphabetical list of all the procedures and macros in Guile. +It also includes Guile's Autoconf macros. + +When looking for a particular procedure, please look under its Scheme +name as well as under its C name. The C name can be constructed from +the Scheme names by a simple transformation described in the section +@xref{API Overview}. + +@printindex fn + + +@page +@node Variable Index +@unnumbered Variable Index + +@c FIXME::martin: Review me! + +This is an alphabetical list of all the important variables and +constants in Guile. + +When looking for a particular variable or constant, please look under +its Scheme name as well as under its C name. The C name can be +constructed from the Scheme names by a simple transformation described +in the section @xref{API Overview}. + +@printindex vr + + +@page +@node Type Index +@unnumbered Type Index + +This is an alphabetical list of all the important data types defined in +the Guile Programmers Manual. + +@printindex tp + diff --git a/doc/ref/intro.texi b/doc/ref/intro.texi new file mode 100644 index 000000000..28da4ac3c --- /dev/null +++ b/doc/ref/intro.texi @@ -0,0 +1,319 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010, 2011, 2013 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Introduction +@chapter Introduction + +Guile is an implementation of the Scheme programming language. Scheme +(@url{http://schemers.org/}) is an elegant and conceptually simple +dialect of Lisp, originated by Guy Steele and Gerald Sussman, and since +evolved by the series of reports known as RnRS (the +@tex +Revised$^n$ +@end tex +@ifnottex +Revised^n +@end ifnottex +Reports on Scheme). + +Unlike, for example, Python or Perl, Scheme has no benevolent +dictator. There are many Scheme implementations, with different +characteristics and with communities and academic activities around +them, and the language develops as a result of the interplay between +these. Guile's particular characteristics are that + +@itemize +@item +it is easy to combine with other code written in C +@item +it has a historical and continuing connection with the GNU Project +@item +it emphasizes interactive and incremental programming +@item +it actually supports several languages, not just Scheme. +@end itemize + +@noindent +The next few sections explain what we mean by these points. The sections after +that cover how you can obtain and install Guile, and the typographical +conventions that we use in this manual. + +@menu +* Guile and Scheme:: +* Combining with C:: +* Guile and the GNU Project:: +* Interactive Programming:: +* Supporting Multiple Languages:: +* Obtaining and Installing Guile:: +* Organisation of this Manual:: +* Typographical Conventions:: +@end menu + +@node Guile and Scheme +@section Guile and Scheme + +Guile implements Scheme as described in the +@tex +Revised$^5$ +@end tex +@ifnottex +Revised^5 +@end ifnottex +Report on the Algorithmic Language Scheme (usually known as +@acronym{R5RS}), providing clean and general data and control +structures. Guile goes beyond the rather austere language presented +in @acronym{R5RS}, extending it with a module system, full access to +@acronym{POSIX} system calls, networking support, multiple threads, +dynamic linking, a foreign function call interface, powerful string +processing, and many other features needed for programming in the real +world. + +The Scheme community has recently agreed and published R6RS, the +latest installment in the RnRS series. R6RS significantly expands the +core Scheme language, and standardises many non-core functions that +implementations---including Guile---have previously done in +different ways. Guile has been updated to incorporate some of the +features of R6RS, and to adjust some existing features to conform to +the R6RS specification, but it is by no means a complete R6RS +implementation. @xref{R6RS Support}. + +Between R5RS and R6RS, the SRFI process (@url{http://srfi.schemers.org/}) +standardised interfaces for many practical needs, such as multithreaded +programming and multidimensional arrays. Guile supports many SRFIs, as +documented in detail in @ref{SRFI Support}. + +In summary, so far as relationship to the Scheme standards is +concerned, Guile is an R5RS implementation with many extensions, some +of which conform to SRFIs or to the relevant parts of R6RS. + +@node Combining with C +@section Combining with C Code + +Like a shell, Guile can run interactively---reading expressions from the user, +evaluating them, and displaying the results---or as a script interpreter, +reading and executing Scheme code from a file. Guile also provides an object +library, @dfn{libguile}, that allows other applications to easily incorporate a +complete Scheme interpreter. An application can then use Guile as an extension +language, a clean and powerful configuration language, or as multi-purpose +``glue'', connecting primitives provided by the application. It is easy to call +Scheme code from C code and vice versa, giving the application designer full +control of how and when to invoke the interpreter. Applications can add new +functions, data types, control structures, and even syntax to Guile, creating a +domain-specific language tailored to the task at hand, but based on a robust +language design. + +This kind of combination is helped by four aspects of Guile's design +and history. First is that Guile has always been targeted as an +extension language. Hence its C API has always been of great +importance, and has been developed accordingly. Second and third are +rather technical points---that Guile uses conservative garbage +collection, and that it implements the Scheme concept of continuations +by copying and reinstating the C stack---but whose practical +consequence is that most existing C code can be glued into Guile as +is, without needing modifications to cope with strange Scheme +execution flows. Last is the module system, which helps extensions to +coexist without stepping on each others' toes. + +Guile's module system allows one to break up a large program into +manageable sections with well-defined interfaces between them. +Modules may contain a mixture of interpreted and compiled code; Guile +can use either static or dynamic linking to incorporate compiled code. +Modules also encourage developers to package up useful collections of +routines for general distribution; as of this writing, one can find +Emacs interfaces, database access routines, compilers, @acronym{GUI} +toolkit interfaces, and @acronym{HTTP} client functions, among others. + +@node Guile and the GNU Project +@section Guile and the GNU Project + +Guile was conceived by the GNU Project following the fantastic success +of Emacs Lisp as an extension language within Emacs. Just as Emacs +Lisp allowed complete and unanticipated applications to be written +within the Emacs environment, the idea was that Guile should do the +same for other GNU Project applications. This remains true today. + +The idea of extensibility is closely related to the GNU project's +primary goal, that of promoting software freedom. Software freedom +means that people receiving a software package can modify or enhance +it to their own desires, including in ways that may not have occurred +at all to the software's original developers. For programs written in +a compiled language like C, this freedom covers modifying and +rebuilding the C code; but if the program also provides an extension +language, that is usually a much friendlier and lower-barrier-of-entry +way for the user to start making their own changes. + +Guile is now used by GNU project applications such as AutoGen, Lilypond, Denemo, +Mailutils, TeXmacs and Gnucash, and we hope that there will be many more in +future. + +@node Interactive Programming +@section Interactive Programming + +Non-free software has no interest in its users being able to see how it works. +They are supposed to just accept it, or to report problems and hope that the +source code owners will choose to work on them. + +Free software aims to work reliably just as much as non-free software does, but +it should also empower its users by making its workings available. This is +useful for many reasons, including education, auditing and enhancements, as well +as for debugging problems. + +The ideal free software system achieves this by making it easy for interested +users to see the source code for a feature that they are using, and to follow +through that source code step-by-step, as it runs. In Emacs, good examples of +this are the source code hyperlinks in the help system, and @code{edebug}. +Then, for bonus points and maximising the ability for the user to experiment +quickly with code changes, the system should allow parts of the source code to +be modified and reloaded into the running program, to take immediate effect. + +Guile is designed for this kind of interactive programming, and this +distinguishes it from many Scheme implementations that instead prioritise +running a fixed Scheme program as fast as possible---because there are +tradeoffs between performance and the ability to modify parts of an already +running program. There are faster Schemes than Guile, but Guile is a GNU +project and so prioritises the GNU vision of programming freedom and +experimentation. + +@node Supporting Multiple Languages +@section Supporting Multiple Languages + +Since the 2.0 release, Guile's architecture supports compiling any language to +its core virtual machine bytecode, and Scheme is just one of the supported +languages. Other supported languages are Emacs Lisp, ECMAScript (commonly known +as Javascript) and Brainfuck, and work is under discussion for Lua, Ruby and +Python. + +This means that users can program applications which use Guile in the language +of their choice, rather than having the tastes of the application's author +imposed on them. + +@node Obtaining and Installing Guile +@section Obtaining and Installing Guile + +Guile can be obtained from the main GNU archive site +@url{ftp://ftp.gnu.org} or any of its mirrors. The file will be named +guile-@var{version}.tar.gz. The current version is @value{VERSION}, so the +file you should grab is: + +@url{ftp://ftp.gnu.org/gnu/guile/guile-@value{VERSION}.tar.gz} + +To unbundle Guile use the instruction + +@example +zcat guile-@value{VERSION}.tar.gz | tar xvf - +@end example + +@noindent +which will create a directory called @file{guile-@value{VERSION}} with +all the sources. You can look at the file @file{INSTALL} for detailed +instructions on how to build and install Guile, but you should be able +to just do + +@example +cd guile-@value{VERSION} +./configure +make +make install +@end example + +This will install the Guile executable @file{guile}, the Guile library +@file{libguile} and various associated header files and support libraries. It +will also install the Guile reference manual. + +@c [[include instructions for getting R5RS]] + +Since this manual frequently refers to the Scheme ``standard'', also +known as R5RS, or the +@tex +``Revised$^5$ Report on the Algorithmic Language Scheme'', +@end tex +@ifnottex +``Revised^5 Report on the Algorithmic Language Scheme'', +@end ifnottex +we have included the report in the Guile distribution; see +@ref{Top, , Introduction, r5rs, Revised(5) Report on the Algorithmic +Language Scheme}. +This will also be installed in your info directory. + +@node Organisation of this Manual +@section Organisation of this Manual + +The rest of this manual is organised into the following chapters. + +@table @strong +@item Chapter 2: Hello Guile! +A whirlwind tour shows how Guile can be used interactively and as +a script interpreter, how to link Guile into your own applications, +and how to write modules of interpreted and compiled code for use with +Guile. Everything introduced here is documented again and in full by +the later parts of the manual. + +@item Chapter 3: Hello Scheme! +For readers new to Scheme, this chapter provides an introduction to the basic +ideas of the Scheme language. This material would apply to any Scheme +implementation and so does not make reference to anything Guile-specific. + +@item Chapter 4: Programming in Scheme +Provides an overview of programming in Scheme with Guile. It covers how to +invoke the @code{guile} program from the command-line and how to write scripts +in Scheme. It also introduces the extensions that Guile offers beyond standard +Scheme. + +@item Chapter 5: Programming in C +Provides an overview of how to use Guile in a C program. It +discusses the fundamental concepts that you need to understand to +access the features of Guile, such as dynamic types and the garbage +collector. It explains in a tutorial like manner how to define new +data types and functions for the use by Scheme programs. + +@item Chapter 6: Guile API Reference +This part of the manual documents the Guile @acronym{API} in +functionality-based groups with the Scheme and C interfaces presented +side by side. + +@item Chapter 7: Guile Modules +Describes some important modules, distributed as part of the Guile +distribution, that extend the functionality provided by the Guile +Scheme core. + +@item Chapter 8: GOOPS +Describes GOOPS, an object oriented extension to Guile that provides +classes, multiple inheritance and generic functions. + +@end table + +@node Typographical Conventions +@section Typographical Conventions + +In examples and procedure descriptions and all other places where the +evaluation of Scheme expression is shown, we use some notation for +denoting the output and evaluation results of expressions. + +The symbol @samp{@result{}} is used to tell which value is returned by +an evaluation: + +@lisp +(+ 1 2) +@result{} 3 +@end lisp + +Some procedures produce some output besides returning a value. This +is denoted by the symbol @samp{@print{}}. + +@lisp +(begin (display 1) (newline) 'hooray) +@print{} 1 +@result{} hooray +@end lisp + +As you can see, this code prints @samp{1} (denoted by +@samp{@print{}}), and returns @code{hooray} (denoted by +@samp{@result{}}). + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/libguile-autoconf.texi b/doc/ref/libguile-autoconf.texi new file mode 100644 index 000000000..b4a9f409d --- /dev/null +++ b/doc/ref/libguile-autoconf.texi @@ -0,0 +1,151 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node Autoconf Support +@section Autoconf Support + +Autoconf, a part of the GNU build system, makes it easy for users to +build your package. This section documents Guile's Autoconf support. + +@menu +* Autoconf Background:: Why use autoconf? +* Autoconf Macros:: The GUILE_* macros. +* Using Autoconf Macros:: How to use them, plus examples. +@end menu + + +@node Autoconf Background +@subsection Autoconf Background + +As explained in the @cite{GNU Autoconf Manual}, any package needs +configuration at build-time (@pxref{Top, ,Introduction,autoconf,The GNU +Autoconf Manual}). If your package uses Guile (or uses a package that +in turn uses Guile), you probably need to know what specific Guile +features are available and details about them. + +The way to do this is to write feature tests and arrange for their execution +by the @file{configure} script, typically by adding the tests to +@file{configure.ac}, and running @code{autoconf} to create @file{configure}. +Users of your package then run @file{configure} in the normal way. + +Macros are a way to make common feature tests easy to express. +Autoconf provides a wide range of macros +(@pxref{Existing Tests,,,autoconf,The GNU Autoconf Manual}), +and Guile installation provides Guile-specific tests in the areas of: +program detection, compilation flags reporting, and Scheme module +checks. + + +@node Autoconf Macros +@subsection Autoconf Macros + +As mentioned earlier in this chapter, Guile supports parallel +installation, and uses @code{pkg-config} to let the user choose which +version of Guile they are interested in. @code{pkg-config} has its own +set of Autoconf macros that are probably installed on most every +development system. The most useful of these macros is +@code{PKG_CHECK_MODULES}. + +@findex PKG_CHECK_MODULES + +@example +PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}]) +@end example + +This example looks for Guile and sets the @code{GUILE_CFLAGS} and +@code{GUILE_LIBS} variables accordingly, or prints an error and exits if +Guile was not found. + +Guile comes with additional Autoconf macros providing more information, +installed as @file{@var{prefix}/share/aclocal/guile.m4}. Their names +all begin with @code{GUILE_}. + +@c see Makefile.am +@include autoconf-macros.texi + + +@node Using Autoconf Macros +@subsection Using Autoconf Macros + +Using the autoconf macros is straightforward: Add the macro "calls" (actually +instantiations) to @file{configure.ac}, run @code{aclocal}, and finally, +run @code{autoconf}. If your system doesn't have guile.m4 installed, place +the desired macro definitions (@code{AC_DEFUN} forms) in @file{acinclude.m4}, +and @code{aclocal} will do the right thing. + +Some of the macros can be used inside normal shell constructs: @code{if foo ; +then GUILE_BAZ ; fi}, but this is not guaranteed. It's probably a good idea +to instantiate macros at top-level. + +We now include two examples, one simple and one complicated. + +The first example is for a package that uses libguile, and thus needs to +know how to compile and link against it. So we use +@code{PKG_CHECK_MODULES} to set the vars @code{GUILE_CFLAGS} and +@code{GUILE_LIBS}, which are automatically substituted in the Makefile. + +@example +In configure.ac: + + PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}]) + +In Makefile.in: + + GUILE_CFLAGS = @@GUILE_CFLAGS@@ + GUILE_LIBS = @@GUILE_LIBS@@ + + myprog.o: myprog.c + $(CC) -o $@ $(GUILE_CFLAGS) $< + myprog: myprog.o + $(CC) -o $@ $< $(GUILE_LIBS) +@end example + +The second example is for a package of Guile Scheme modules that uses an +external program and other Guile Scheme modules (some might call this a "pure +scheme" package). So we use the @code{GUILE_SITE_DIR} macro, a regular +@code{AC_PATH_PROG} macro, and the @code{GUILE_MODULE_AVAILABLE} macro. + +@example +In configure.ac: + + GUILE_SITE_DIR + + probably_wont_work="" + + # pgtype pgtable + GUILE_MODULE_AVAILABLE(have_guile_pg, (database postgres)) + test $have_guile_pg = no && + probably_wont_work="(my pgtype) (my pgtable) $probably_wont_work" + + # gpgutils + AC_PATH_PROG(GNUPG,gpg) + test x"$GNUPG" = x && + probably_wont_work="(my gpgutils) $probably_wont_work" + + if test ! "$probably_wont_work" = "" ; then + p=" ***" + echo + echo "$p" + echo "$p NOTE:" + echo "$p The following modules probably won't work:" + echo "$p $probably_wont_work" + echo "$p They can be installed anyway, and will work if their" + echo "$p dependencies are installed later. Please see README." + echo "$p" + echo + fi + +In Makefile.in: + + instdir = @@GUILE_SITE@@/my + + install: + $(INSTALL) my/*.scm $(instdir) +@end example + + +@c autoconf.texi ends here diff --git a/doc/ref/libguile-concepts.texi b/doc/ref/libguile-concepts.texi new file mode 100644 index 000000000..34010eebf --- /dev/null +++ b/doc/ref/libguile-concepts.texi @@ -0,0 +1,623 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996-1997, 2000-2005, 2010-2011, 2013-2016 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node General Libguile Concepts +@section General concepts for using libguile + +When you want to embed the Guile Scheme interpreter into your program or +library, you need to link it against the @file{libguile} library +(@pxref{Linking Programs With Guile}). Once you have done this, your C +code has access to a number of data types and functions that can be used +to invoke the interpreter, or make new functions that you have written +in C available to be called from Scheme code, among other things. + +Scheme is different from C in a number of significant ways, and Guile +tries to make the advantages of Scheme available to C as well. Thus, in +addition to a Scheme interpreter, libguile also offers dynamic types, +garbage collection, continuations, arithmetic on arbitrary sized +numbers, and other things. + +The two fundamental concepts are dynamic types and garbage collection. +You need to understand how libguile offers them to C programs in order +to use the rest of libguile. Also, the more general control flow of +Scheme caused by continuations needs to be dealt with. + +Running asynchronous signal handlers and multi-threading is known to C +code already, but there are of course a few additional rules when using +them together with libguile. + +@menu +* Dynamic Types:: Dynamic Types. +* Garbage Collection:: Garbage Collection. +* Control Flow:: Control Flow. +* Asynchronous Signals:: Asynchronous Signals +* Multi-Threading:: Multi-Threading +@end menu + +@node Dynamic Types +@subsection Dynamic Types + +Scheme is a dynamically-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 @code{pair?} and +@code{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 @code{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. + +In Guile, this uniform representation of all Scheme values is the C type +@code{SCM}. This is an opaque type and its size is typically equivalent +to that of a pointer to @code{void}. Thus, @code{SCM} values can be +passed around efficiently and they take up reasonably little storage on +their own. + +The most important rule is: You never access a @code{SCM} value +directly; you only pass it to functions or macros defined in libguile. + +As an obvious example, although a @code{SCM} variable can contain +integers, you can of course not compute the sum of two @code{SCM} values +by adding them with the C @code{+} operator. You must use the libguile +function @code{scm_sum}. + +Less obvious and therefore more important to keep in mind is that you +also cannot directly test @code{SCM} values for trueness. In Scheme, +the value @code{#f} is considered false and of course a @code{SCM} +variable can represent that value. But there is no guarantee that the +@code{SCM} representation of @code{#f} looks false to C code as well. +You need to use @code{scm_is_true} or @code{scm_is_false} to test a +@code{SCM} value for trueness or falseness, respectively. + +You also can not directly compare two @code{SCM} values to find out +whether they are identical (that is, whether they are @code{eq?} in +Scheme terms). You need to use @code{scm_is_eq} for this. + +The one exception is that you can directly assign a @code{SCM} value to +a @code{SCM} variable by using the C @code{=} operator. + +The following (contrived) example shows how to do it right. It +implements a function of two arguments (@var{a} and @var{flag}) that +returns @var{a}+1 if @var{flag} is true, else it returns @var{a} +unchanged. + +@example +SCM +my_incrementing_function (SCM a, SCM flag) +@{ + SCM result; + + if (scm_is_true (flag)) + result = scm_sum (a, scm_from_int (1)); + else + result = a; + + return result; +@} +@end example + +Often, you need to convert between @code{SCM} values and appropriate C +values. For example, we needed to convert the integer @code{1} to its +@code{SCM} representation in order to add it to @var{a}. Libguile +provides many function to do these conversions, both from C to +@code{SCM} and from @code{SCM} to C. + +The conversion functions follow a common naming pattern: those that make +a @code{SCM} value from a C value have names of the form +@code{scm_from_@var{type} (@dots{})} and those that convert a @code{SCM} +value to a C value use the form @code{scm_to_@var{type} (@dots{})}. + +However, it is best to avoid converting values when you can. When you +must combine C values and @code{SCM} values in a computation, it is +often better to convert the C values to @code{SCM} values and do the +computation by using libguile functions than to the other way around +(converting @code{SCM} to C and doing the computation some other way). + +As a simple example, consider this version of +@code{my_incrementing_function} from above: + +@example +SCM +my_other_incrementing_function (SCM a, SCM flag) +@{ + int result; + + if (scm_is_true (flag)) + result = scm_to_int (a) + 1; + else + result = scm_to_int (a); + + return scm_from_int (result); +@} +@end example + +This version is much less general than the original one: it will only +work for values @var{A} that can fit into a @code{int}. The original +function will work for all values that Guile can represent and that +@code{scm_sum} can understand, including integers bigger than @code{long +long}, floating point numbers, complex numbers, and new numerical types +that have been added to Guile by third-party libraries. + +Also, computing with @code{SCM} is not necessarily inefficient. Small +integers will be encoded directly in the @code{SCM} value, for example, +and do not need any additional memory on the heap. See @ref{Data +Representation} to find out the details. + +Some special @code{SCM} values are available to C code without needing +to convert them from C values: + +@multitable {Scheme value} {C representation} +@item Scheme value @tab C representation +@item @nicode{#f} @tab @nicode{SCM_BOOL_F} +@item @nicode{#t} @tab @nicode{SCM_BOOL_T} +@item @nicode{()} @tab @nicode{SCM_EOL} +@end multitable + +In addition to @code{SCM}, Guile also defines the related type +@code{scm_t_bits}. This is an unsigned integral type of sufficient +size to hold all information that is directly contained in a +@code{SCM} value. The @code{scm_t_bits} type is used internally by +Guile to do all the bit twiddling explained in @ref{Data Representation}, but +you will encounter it occasionally in low-level user code as well. + + +@node Garbage Collection +@subsection Garbage Collection + +As explained above, the @code{SCM} type can represent all Scheme values. +Some values fit entirely into a @code{SCM} value (such as small +integers), but other values require additional storage in the heap (such +as strings and vectors). This additional storage is managed +automatically by Guile. You don't need to explicitly deallocate it +when a @code{SCM} value is no longer used. + +Two things must be guaranteed so that Guile is able to manage the +storage automatically: it must know about all blocks of memory that have +ever been allocated for Scheme values, and it must know about all Scheme +values that are still being used. Given this knowledge, Guile can +periodically free all blocks that have been allocated but are not used +by any active Scheme values. This activity is called @dfn{garbage +collection}. + +Guile's garbage collector will automatically discover references to +@code{SCM} objects that originate in global variables, static data +sections, function arguments or local variables on the C and Scheme +stacks, and values in machine registers. Other references to @code{SCM} +objects, such as those in other random data structures in the C heap +that contain fields of type @code{SCM}, can be made visible to the +garbage collector by calling the functions @code{scm_gc_protect_object} or +@code{scm_permanent_object}. Collectively, these values form the ``root +set'' of garbage collection; any value on the heap that is referenced +directly or indirectly by a member of the root set is preserved, and all +other objects are eligible for reclamation. + +In Guile, garbage collection has two logical phases: the @dfn{mark +phase}, in which the collector discovers the set of all live objects, +and the @dfn{sweep phase}, in which the collector reclaims the resources +associated with dead objects. The mark phase pauses the program and +traces all @code{SCM} object references, starting with the root set. +The sweep phase actually runs concurrently with the main program, +incrementally reclaiming memory as needed by allocation. + +In the mark phase, the garbage collector traces the Scheme stack and +heap @dfn{precisely}. Because the Scheme stack and heap are managed by +Guile, Guile can know precisely where in those data structures it might +find references to other heap objects. This is not the case, +unfortunately, for pointers on the C stack and static data segment. +Instead of requiring the user to inform Guile about all variables in C +that might point to heap objects, Guile traces the C stack and static +data segment @dfn{conservatively}. That is to say, Guile just treats +every word on the C stack and every C global variable as a potential +reference in to the Scheme heap@footnote{Note that Guile does not scan +the C heap for references, so a reference to a @code{SCM} object from a +memory segment allocated with @code{malloc} will have to use some other +means to keep the @code{SCM} object alive. @xref{Garbage Collection +Functions}.}. Any value that looks like a pointer to a GC-managed +object is treated as such, whether it actually is a reference or not. +Thus, scanning the C stack and static data segment is guaranteed to find +all actual references, but it might also find words that only +accidentally look like references. These ``false positives'' might keep +@code{SCM} objects alive that would otherwise be considered dead. While +this might waste memory, keeping an object around longer than it +strictly needs to is harmless. This is why this technique is called +``conservative garbage collection''. In practice, the wasted memory +seems to be no problem, as the static C root set is almost always finite +and small, given that the Scheme stack is separate from the C stack. + +The stack of every thread is scanned in this way and the registers of +the CPU and all other memory locations where local variables or function +parameters might show up are included in this scan as well. + +The consequence of the conservative scanning is that you can just +declare local variables and function parameters of type @code{SCM} and +be sure that the garbage collector will not free the corresponding +objects. + +However, a local variable or function parameter is only protected as +long as it is really on the stack (or in some register). As an +optimization, the C compiler might reuse its location for some other +value and the @code{SCM} object would no longer be protected. Normally, +this leads to exactly the right behavior: the compiler will only +overwrite a reference when it is no longer needed and thus the object +becomes unprotected precisely when the reference disappears, just as +wanted. + +There are situations, however, where a @code{SCM} object needs to be +around longer than its reference from a local variable or function +parameter. This happens, for example, when you retrieve some pointer +from a foreign object and work with that pointer directly. The +reference to the @code{SCM} foreign object might be dead after the +pointer has been retrieved, but the pointer itself (and the memory +pointed to) is still in use and thus the foreign object must be +protected. The compiler does not know about this connection and might +overwrite the @code{SCM} reference too early. + +To get around this problem, you can use @code{scm_remember_upto_here_1} +and its cousins. It will keep the compiler from overwriting the +reference. @xref{Foreign Object Memory Management}. + + +@node Control Flow +@subsection Control Flow + +Scheme has a more general view of program flow than C, both locally and +non-locally. + +Controlling the local flow of control involves things like gotos, loops, +calling functions and returning from them. Non-local control flow +refers to situations where the program jumps across one or more levels +of function activations without using the normal call or return +operations. + +The primitive means of C for local control flow is the @code{goto} +statement, together with @code{if}. Loops done with @code{for}, +@code{while} or @code{do} could in principle be rewritten with just +@code{goto} and @code{if}. In Scheme, the primitive means for local +control flow is the @emph{function call} (together with @code{if}). +Thus, the repetition of some computation in a loop is ultimately +implemented by a function that calls itself, that is, by recursion. + +This approach is theoretically very powerful since it is easier to +reason formally about recursion than about gotos. In C, using +recursion exclusively would not be practical, though, since it would eat +up the stack very quickly. In Scheme, however, it is practical: +function calls that appear in a @dfn{tail position} do not use any +additional stack space (@pxref{Tail Calls}). + +A function call is in a tail position when it is the last thing the +calling function does. The value returned by the called function is +immediately returned from the calling function. In the following +example, the call to @code{bar-1} is in a tail position, while the +call to @code{bar-2} is not. (The call to @code{1-} in @code{foo-2} +is in a tail position, though.) + +@lisp +(define (foo-1 x) + (bar-1 (1- x))) + +(define (foo-2 x) + (1- (bar-2 x))) +@end lisp + +Thus, when you take care to recurse only in tail positions, the +recursion will only use constant stack space and will be as good as a +loop constructed from gotos. + +Scheme offers a few syntactic abstractions (@code{do} and @dfn{named} +@code{let}) that make writing loops slightly easier. + +But only Scheme functions can call other functions in a tail position: +C functions can not. This matters when you have, say, two functions +that call each other recursively to form a common loop. The following +(unrealistic) example shows how one might go about determining whether a +non-negative integer @var{n} is even or odd. + +@lisp +(define (my-even? n) + (cond ((zero? n) #t) + (else (my-odd? (1- n))))) + +(define (my-odd? n) + (cond ((zero? n) #f) + (else (my-even? (1- n))))) +@end lisp + +Because the calls to @code{my-even?} and @code{my-odd?} are in tail +positions, these two procedures can be applied to arbitrary large +integers without overflowing the stack. (They will still take a lot +of time, of course.) + +However, when one or both of the two procedures would be rewritten in +C, it could no longer call its companion in a tail position (since C +does not have this concept). You might need to take this +consideration into account when deciding which parts of your program +to write in Scheme and which in C. + +In addition to calling functions and returning from them, a Scheme +program can also exit non-locally from a function so that the control +flow returns directly to an outer level. This means that some functions +might not return at all. + +Even more, it is not only possible to jump to some outer level of +control, a Scheme program can also jump back into the middle of a +function that has already exited. This might cause some functions to +return more than once. + +In general, these non-local jumps are done by invoking +@dfn{continuations} that have previously been captured using +@code{call-with-current-continuation}. Guile also offers a slightly +restricted set of functions, @code{catch} and @code{throw}, that can +only be used for non-local exits. This restriction makes them more +efficient. Error reporting (with the function @code{error}) is +implemented by invoking @code{throw}, for example. The functions +@code{catch} and @code{throw} belong to the topic of @dfn{exceptions}. + +Since Scheme functions can call C functions and vice versa, C code can +experience the more general control flow of Scheme as well. It is +possible that a C function will not return at all, or will return more +than once. While C does offer @code{setjmp} and @code{longjmp} for +non-local exits, it is still an unusual thing for C code. In +contrast, non-local exits are very common in Scheme, mostly to report +errors. + +You need to be prepared for the non-local jumps in the control flow +whenever you use a function from @code{libguile}: it is best to assume +that any @code{libguile} function might signal an error or run a pending +signal handler (which in turn can do arbitrary things). + +It is often necessary to take cleanup actions when the control leaves a +function non-locally. Also, when the control returns non-locally, some +setup actions might be called for. For example, the Scheme function +@code{with-output-to-port} needs to modify the global state so that +@code{current-output-port} returns the port passed to +@code{with-output-to-port}. The global output port needs to be reset to +its previous value when @code{with-output-to-port} returns normally or +when it is exited non-locally. Likewise, the port needs to be set again +when control enters non-locally. + +Scheme code can use the @code{dynamic-wind} function to arrange for +the setting and resetting of the global state. C code can use the +corresponding @code{scm_internal_dynamic_wind} function, or a +@code{scm_dynwind_begin}/@code{scm_dynwind_end} pair together with +suitable 'dynwind actions' (@pxref{Dynamic Wind}). + +Instead of coping with non-local control flow, you can also prevent it +by erecting a @emph{continuation barrier}, @xref{Continuation +Barriers}. The function @code{scm_c_with_continuation_barrier}, for +example, is guaranteed to return exactly once. + +@node Asynchronous Signals +@subsection Asynchronous Signals + +You can not call libguile functions from handlers for POSIX signals, but +you can register Scheme handlers for POSIX signals such as +@code{SIGINT}. These handlers do not run during the actual signal +delivery. Instead, they are run when the program (more precisely, the +thread that the handler has been registered for) reaches the next +@emph{safe point}. + +The libguile functions themselves have many such safe points. +Consequently, you must be prepared for arbitrary actions anytime you +call a libguile function. For example, even @code{scm_cons} can contain +a safe point and when a signal handler is pending for your thread, +calling @code{scm_cons} will run this handler and anything might happen, +including a non-local exit although @code{scm_cons} would not ordinarily +do such a thing on its own. + +If you do not want to allow the running of asynchronous signal handlers, +you can block them temporarily with @code{scm_dynwind_block_asyncs}, for +example. @xref{Asyncs}. + +Since signal handling in Guile relies on safe points, you need to make +sure that your functions do offer enough of them. Normally, calling +libguile functions in the normal course of action is all that is needed. +But when a thread might spent a long time in a code section that calls +no libguile function, it is good to include explicit safe points. This +can allow the user to interrupt your code with @key{C-c}, for example. + +You can do this with the macro @code{SCM_TICK}. This macro is +syntactically a statement. That is, you could use it like this: + +@example +while (1) + @{ + SCM_TICK; + do_some_work (); + @} +@end example + +Frequent execution of a safe point is even more important in multi +threaded programs, @xref{Multi-Threading}. + +@node Multi-Threading +@subsection Multi-Threading + +Guile can be used in multi-threaded programs just as well as in +single-threaded ones. + +Each thread that wants to use functions from libguile must put itself +into @emph{guile mode} and must then follow a few rules. If it doesn't +want to honor these rules in certain situations, a thread can +temporarily leave guile mode (but can no longer use libguile functions +during that time, of course). + +Threads enter guile mode by calling @code{scm_with_guile}, +@code{scm_boot_guile}, or @code{scm_init_guile}. As explained in the +reference documentation for these functions, Guile will then learn about +the stack bounds of the thread and can protect the @code{SCM} values +that are stored in local variables. When a thread puts itself into +guile mode for the first time, it gets a Scheme representation and is +listed by @code{all-threads}, for example. + +Threads in guile mode can block (e.g., do blocking I/O) without causing +any problems@footnote{In Guile 1.8, a thread blocking in guile mode +would prevent garbage collection to occur. Thus, threads had to leave +guile mode whenever they could block. This is no longer needed with +Guile 2.@var{x}.}; temporarily leaving guile mode with +@code{scm_without_guile} before blocking slightly improves GC +performance, though. For some common blocking operations, Guile +provides convenience functions. For example, if you want to lock a +pthread mutex while in guile mode, you might want to use +@code{scm_pthread_mutex_lock} which is just like +@code{pthread_mutex_lock} except that it leaves guile mode while +blocking. + + +All libguile functions are (intended to be) robust in the face of +multiple threads using them concurrently. This means that there is no +risk of the internal data structures of libguile becoming corrupted in +such a way that the process crashes. + +A program might still produce nonsensical results, though. Taking +hashtables as an example, Guile guarantees that you can use them from +multiple threads concurrently and a hashtable will always remain a valid +hashtable and Guile will not crash when you access it. It does not +guarantee, however, that inserting into it concurrently from two threads +will give useful results: only one insertion might actually happen, none +might happen, or the table might in general be modified in a totally +arbitrary manner. (It will still be a valid hashtable, but not the one +that you might have expected.) Guile might also signal an error when it +detects a harmful race condition. + +Thus, you need to put in additional synchronizations when multiple +threads want to use a single hashtable, or any other mutable Scheme +object. + +When writing C code for use with libguile, you should try to make it +robust as well. An example that converts a list into a vector will help +to illustrate. Here is a correct version: + +@example +SCM +my_list_to_vector (SCM list) +@{ + SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED); + size_t len, i; + + len = scm_c_vector_length (vector); + i = 0; + while (i < len && scm_is_pair (list)) + @{ + scm_c_vector_set_x (vector, i, scm_car (list)); + list = scm_cdr (list); + i++; + @} + + return vector; +@} +@end example + +The first thing to note is that storing into a @code{SCM} location +concurrently from multiple threads is guaranteed to be robust: you don't +know which value wins but it will in any case be a valid @code{SCM} +value. + +But there is no guarantee that the list referenced by @var{list} is not +modified in another thread while the loop iterates over it. Thus, while +copying its elements into the vector, the list might get longer or +shorter. For this reason, the loop must check both that it doesn't +overrun the vector and that it doesn't overrun the list. Otherwise, +@code{scm_c_vector_set_x} would raise an error if the index is out of +range, and @code{scm_car} and @code{scm_cdr} would raise an error if the +value is not a pair. + +It is safe to use @code{scm_car} and @code{scm_cdr} on the local +variable @var{list} once it is known that the variable contains a pair. +The contents of the pair might change spontaneously, but it will always +stay a valid pair (and a local variable will of course not spontaneously +point to a different Scheme object). + +Likewise, a vector such as the one returned by @code{scm_make_vector} is +guaranteed to always stay the same length so that it is safe to only use +scm_c_vector_length once and store the result. (In the example, +@var{vector} is safe anyway since it is a fresh object that no other +thread can possibly know about until it is returned from +@code{my_list_to_vector}.) + +Of course the behavior of @code{my_list_to_vector} is suboptimal when +@var{list} does indeed get asynchronously lengthened or shortened in +another thread. But it is robust: it will always return a valid vector. +That vector might be shorter than expected, or its last elements might +be unspecified, but it is a valid vector and if a program wants to rule +out these cases, it must avoid modifying the list asynchronously. + +Here is another version that is also correct: + +@example +SCM +my_pedantic_list_to_vector (SCM list) +@{ + SCM vector = scm_make_vector (scm_length (list), SCM_UNDEFINED); + size_t len, i; + + len = scm_c_vector_length (vector); + i = 0; + while (i < len) + @{ + scm_c_vector_set_x (vector, i, scm_car (list)); + list = scm_cdr (list); + i++; + @} + + return vector; +@} +@end example + +This version relies on the error-checking behavior of @code{scm_car} and +@code{scm_cdr}. When the list is shortened (that is, when @var{list} +holds a non-pair), @code{scm_car} will throw an error. This might be +preferable to just returning a half-initialized vector. + +The API for accessing vectors and arrays of various kinds from C takes a +slightly different approach to thread-robustness. In order to get at +the raw memory that stores the elements of an array, you need to +@emph{reserve} that array as long as you need the raw memory. During +the time an array is reserved, its elements can still spontaneously +change their values, but the memory itself and other things like the +size of the array are guaranteed to stay fixed. Any operation that +would change these parameters of an array that is currently reserved +will signal an error. In order to avoid these errors, a program should +of course put suitable synchronization mechanisms in place. As you can +see, Guile itself is again only concerned about robustness, not about +correctness: without proper synchronization, your program will likely +not be correct, but the worst consequence is an error message. + +Real thread-safety often requires that a critical section of code is +executed in a certain restricted manner. A common requirement is that +the code section is not entered a second time when it is already being +executed. Locking a mutex while in that section ensures that no other +thread will start executing it, blocking asyncs ensures that no +asynchronous code enters the section again from the current thread, and +the error checking of Guile mutexes guarantees that an error is +signalled when the current thread accidentally reenters the critical +section via recursive function calls. + +Guile provides two mechanisms to support critical sections as outlined +above. You can either use the macros +@code{SCM_CRITICAL_SECTION_START} and @code{SCM_CRITICAL_SECTION_END} +for very simple sections; or use a dynwind context together with a +call to @code{scm_dynwind_critical_section}. + +The macros only work reliably for critical sections that are +guaranteed to not cause a non-local exit. They also do not detect an +accidental reentry by the current thread. Thus, you should probably +only use them to delimit critical sections that do not contain calls +to libguile functions or to other external functions that might do +complicated things. + +The function @code{scm_dynwind_critical_section}, on the other hand, +will correctly deal with non-local exits because it requires a dynwind +context. Also, by using a separate mutex for each critical section, +it can detect accidental reentries. diff --git a/doc/ref/libguile-extensions.texi b/doc/ref/libguile-extensions.texi new file mode 100644 index 000000000..95f92cac6 --- /dev/null +++ b/doc/ref/libguile-extensions.texi @@ -0,0 +1,116 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Linking Guile with Libraries +@section Linking Guile with Libraries + +The previous section has briefly explained how to write programs that +make use of an embedded Guile interpreter. But sometimes, all you +want to do is make new primitive procedures and data types available +to the Scheme programmer. Writing a new version of @code{guile} is +inconvenient in this case and it would in fact make the life of the +users of your new features needlessly hard. + +For example, suppose that there is a program @code{guile-db} that is a +version of Guile with additional features for accessing a database. +People who want to write Scheme programs that use these features would +have to use @code{guile-db} instead of the usual @code{guile} program. +Now suppose that there is also a program @code{guile-gtk} that extends +Guile with access to the popular Gtk+ toolkit for graphical user +interfaces. People who want to write GUIs in Scheme would have to use +@code{guile-gtk}. Now, what happens when you want to write a Scheme +application that uses a GUI to let the user access a database? You +would have to write a @emph{third} program that incorporates both the +database stuff and the GUI stuff. This might not be easy (because +@code{guile-gtk} might be a quite obscure program, say) and taking this +example further makes it easy to see that this approach can not work in +practice. + +It would have been much better if both the database features and the GUI +feature had been provided as libraries that can just be linked with +@code{guile}. Guile makes it easy to do just this, and we encourage you +to make your extensions to Guile available as libraries whenever +possible. + +You write the new primitive procedures and data types in the normal +fashion, and link them into a shared library instead of into a +stand-alone program. The shared library can then be loaded dynamically +by Guile. + +@menu +* A Sample Guile Extension:: +@end menu + + +@node A Sample Guile Extension +@subsection A Sample Guile Extension + +This section explains how to make the Bessel functions of the C library +available to Scheme. First we need to write the appropriate glue code +to convert the arguments and return values of the functions from Scheme +to C and back. Additionally, we need a function that will add them to +the set of Guile primitives. Because this is just an example, we will +only implement this for the @code{j0} function. + +Consider the following file @file{bessel.c}. + +@smallexample +#include <math.h> +#include <libguile.h> + +SCM +j0_wrapper (SCM x) +@{ + return scm_from_double (j0 (scm_to_double (x))); +@} + +void +init_bessel () +@{ + scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper); +@} +@end smallexample + +This C source file needs to be compiled into a shared library. Here is +how to do it on GNU/Linux: + +@smallexample +gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` \ + -shared -o libguile-bessel.so -fPIC bessel.c +@end smallexample + +For creating shared libraries portably, we recommend the use of GNU +Libtool (@pxref{Top, , Introduction, libtool, GNU Libtool}). + +A shared library can be loaded into a running Guile process with the +function @code{load-extension}. In addition to the name of the +library to load, this function also expects the name of a function from +that library that will be called to initialize it. For our example, +we are going to call the function @code{init_bessel} which will make +@code{j0_wrapper} available to Scheme programs with the name +@code{j0}. Note that we do not specify a filename extension such as +@file{.so} when invoking @code{load-extension}. The right extension for +the host platform will be provided automatically. + +@lisp +(load-extension "libguile-bessel" "init_bessel") +(j0 2) +@result{} 0.223890779141236 +@end lisp + +For this to work, @code{load-extension} must be able to find +@file{libguile-bessel}, of course. It will look in the places that +are usual for your operating system, and it will additionally look +into the directories listed in the @code{LTDL_LIBRARY_PATH} +environment variable. + +To see how these Guile extensions via shared libraries relate to the +module system, @xref{Putting Extensions into Modules}. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/libguile-foreign-objects.texi b/doc/ref/libguile-foreign-objects.texi new file mode 100644 index 000000000..f668eedca --- /dev/null +++ b/doc/ref/libguile-foreign-objects.texi @@ -0,0 +1,491 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011, 2013, 2014, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Defining New Foreign Object Types +@section Defining New Foreign Object Types + +The @dfn{foreign object type} facility is Guile's mechanism for +importing object and types from C or other languages into Guile's +system. If you have a C @code{struct foo} type, for example, you can +define a corresponding Guile foreign object type that allows Scheme code +to handle @code{struct foo *} objects. + +To define a new foreign object type, the programmer provides Guile with +some essential information about the type --- what its name is, how many +fields it has, and its finalizer (if any) --- and Guile allocates a +fresh type for it. Foreign objects can be accessed from Scheme or from +C. + +@menu +* Defining Foreign Object Types:: +* Creating Foreign Objects:: +* Type Checking of Foreign Objects:: +* Foreign Object Memory Management:: +* Foreign Objects and Scheme:: +@end menu + +@node Defining Foreign Object Types +@subsection Defining Foreign Object Types + +To create a new foreign object type from C, call +@code{scm_make_foreign_object_type}. It returns a value of type +@code{SCM} which identifies the new type. + +Here is how one might declare a new type representing eight-bit +gray-scale images: + +@example +#include <libguile.h> + +struct image @{ + int width, height; + char *pixels; + + /* The name of this image */ + SCM name; + + /* A function to call when this image is + modified, e.g., to update the screen, + or SCM_BOOL_F if no action necessary */ + SCM update_func; +@}; + +static SCM image_type; + +void +init_image_type (void) +@{ + SCM name, slots; + scm_t_struct_finalize finalizer; + + name = scm_from_utf8_symbol ("image"); + slots = scm_list_1 (scm_from_utf8_symbol ("data")); + finalizer = NULL; + + image_type = + scm_make_foreign_object_type (name, slots, finalizer); +@} +@end example + +The result is an initialized @code{image_type} value that identifies the +new foreign object type. The next section describes how to create +foreign objects and how to access their slots. + + +@node Creating Foreign Objects +@subsection Creating Foreign Objects + +Foreign objects contain zero or more ``slots'' of data. A slot can hold +a pointer, an integer that fits into a @code{size_t} or @code{ssize_t}, +or a @code{SCM} value. + +All objects of a given foreign type have the same number of slots. In +the example from the previous section, the @code{image} type has one +slot, because the slots list passed to +@code{scm_make_foreign_object_type} is of length one. (The actual names +given to slots are unimportant for most users of the C interface, but +can be used on the Scheme side to introspect on the foreign object.) + +To construct a foreign object and initialize its first slot, call +@code{scm_make_foreign_object_1 (@var{type}, @var{first_slot_value})}. +There are similarly named constructors for initializing 0, 1, 2, or 3 +slots, or initializing @var{n} slots via an array. @xref{Foreign +Objects}, for full details. Any fields that are not explicitly +initialized are set to 0. + +To get or set the value of a slot by index, you can use the +@code{scm_foreign_object_ref} and @code{scm_foreign_object_set_x} +functions. These functions take and return values as @code{void *} +pointers; there are corresponding convenience procedures like +@code{_signed_ref}, @code{_unsigned_set_x} and so on for dealing with +slots as signed or unsigned integers. + +Foreign objects fields that are pointers can be tricky to manage. If +possible, it is best that all memory that is referenced by a foreign +object be managed by the garbage collector. That way, the GC can +automatically ensure that memory is accessible when it is needed, and +freed when it becomes inaccessible. If this is not the case for your +program -- for example, if you are exposing an object to Scheme that was +allocated by some other, Guile-unaware part of your program -- then you +will probably need to implement a finalizer. @xref{Foreign Object +Memory Management}, for more. + +Continuing the example from the previous section, if the global variable +@code{image_type} contains the type returned by +@code{scm_make_foreign_object_type}, here is how we could construct a +foreign object whose ``data'' field contains a pointer to a freshly +allocated @code{struct image}: + +@example +SCM +make_image (SCM name, SCM s_width, SCM s_height) +@{ + struct image *image; + int width = scm_to_int (s_width); + int height = scm_to_int (s_height); + + /* Allocate the `struct image'. Because we + use scm_gc_malloc, this memory block will + be automatically reclaimed when it becomes + inaccessible, and its members will be traced + by the garbage collector. */ + image = (struct image *) + scm_gc_malloc (sizeof (struct image), "image"); + + image->width = width; + image->height = height; + + /* Allocating the pixels with + scm_gc_malloc_pointerless means that the + pixels data is collectable by GC, but + that GC shouldn't spend time tracing its + contents for nested pointers because there + aren't any. */ + image->pixels = + scm_gc_malloc_pointerless (width * height, "image pixels"); + + image->name = name; + image->update_func = SCM_BOOL_F; + + /* Now wrap the struct image* in a new foreign + object, and return that object. */ + return scm_make_foreign_object_1 (image_type, image); +@} +@end example + +We use @code{scm_gc_malloc_pointerless} for the pixel buffer to tell the +garbage collector not to scan it for pointers. Calls to +@code{scm_gc_malloc}, @code{scm_make_foreign_object_1}, and +@code{scm_gc_malloc_pointerless} raise an exception in out-of-memory +conditions; the garbage collector is able to reclaim previously +allocated memory if that happens. + + +@node Type Checking of Foreign Objects +@subsection Type Checking of Foreign Objects + +Functions that operate on foreign objects should check that the passed +@code{SCM} value indeed is of the correct type before accessing its +data. They can do this with @code{scm_assert_foreign_object_type}. + +For example, here is a simple function that operates on an image object, +and checks the type of its argument. + +@example +SCM +clear_image (SCM image_obj) +@{ + int area; + struct image *image; + + scm_assert_foreign_object_type (image_type, image_obj); + + image = scm_foreign_object_ref (image_obj, 0); + area = image->width * image->height; + memset (image->pixels, 0, area); + + /* Invoke the image's update function. */ + if (scm_is_true (image->update_func)) + scm_call_0 (image->update_func); + + return SCM_UNSPECIFIED; +@} +@end example + + +@node Foreign Object Memory Management +@subsection Foreign Object Memory Management + +Once a foreign object has been released to the tender mercies of the +Scheme system, it must be prepared to survive garbage collection. In +the example above, all the memory associated with the foreign object is +managed by the garbage collector because we used the @code{scm_gc_} +allocation functions. Thus, no special care must be taken: the garbage +collector automatically scans them and reclaims any unused memory. + +However, when data associated with a foreign object is managed in some +other way---e.g., @code{malloc}'d memory or file descriptors---it is +possible to specify a @dfn{finalizer} function to release those +resources when the foreign object is reclaimed. + +As discussed in @pxref{Garbage Collection}, Guile's garbage collector +will reclaim inaccessible memory as needed. This reclamation process +runs concurrently with the main program. When Guile analyzes the heap +and determines that an object's memory can be reclaimed, that memory is +put on a ``free list'' of objects that can be reclaimed. Usually that's +the end of it---the object is available for immediate re-use. However +some objects can have ``finalizers'' associated with them---functions +that are called on reclaimable objects to effect any external cleanup +actions. + +Finalizers are tricky business and it is best to avoid them. They can +be invoked at unexpected times, or not at all---for example, they are +not invoked on process exit. They don't help the garbage collector do +its job; in fact, they are a hindrance. Furthermore, they perturb the +garbage collector's internal accounting. The GC decides to scan the +heap when it thinks that it is necessary, after some amount of +allocation. Finalizable objects almost always represent an amount of +allocation that is invisible to the garbage collector. The effect can +be that the actual resource usage of a system with finalizable objects +is higher than what the GC thinks it should be. + +All those caveats aside, some foreign object types will need finalizers. +For example, if we had a foreign object type that wrapped file +descriptors---and we aren't suggesting this, as Guile already has ports +---then you might define the type like this: + +@example +static SCM file_type; + +static void +finalize_file (SCM file) +@{ + int fd = scm_foreign_object_signed_ref (file, 0); + if (fd >= 0) + @{ + scm_foreign_object_signed_set_x (file, 0, -1); + close (fd); + @} +@} + +static void +init_file_type (void) +@{ + SCM name, slots; + scm_t_struct_finalize finalizer; + + name = scm_from_utf8_symbol ("file"); + slots = scm_list_1 (scm_from_utf8_symbol ("fd")); + finalizer = finalize_file; + + image_type = + scm_make_foreign_object_type (name, slots, finalizer); +@} + +static SCM +make_file (int fd) +@{ + return scm_make_foreign_object_1 (file_type, (void *) fd); +@} +@end example + +@cindex finalizer +@cindex finalization + +Note that the finalizer may be invoked in ways and at times you might +not expect. In a Guile built without threading support, finalizers are +invoked via ``asyncs'', which interleaves them with running Scheme code; +@pxref{Asyncs}. If the user's Guile is built with support for threads, +the finalizer will probably be called by a dedicated finalization +thread, unless the user invokes @code{scm_run_finalizers ()} explicitly. + +In either case, finalizers run concurrently with the main program, and +so they need to be async-safe and thread-safe. If for some reason this +is impossible, perhaps because you are embedding Guile in some +application that is not itself thread-safe, you have a few options. One +is to use guardians instead of finalizers, and arrange to pump the +guardians for finalizable objects. @xref{Guardians}, for more +information. The other option is to disable automatic finalization +entirely, and arrange to call @code{scm_run_finalizers ()} at +appropriate points. @xref{Foreign Objects}, for more on these +interfaces. + +Finalizers are allowed to allocate memory, access GC-managed memory, and +in general can do anything any Guile user code can do. This was not the +case in Guile 1.8, where finalizers were much more restricted. In +particular, in Guile 2.0, finalizers can resuscitate objects. We do not +recommend that users avail themselves of this possibility, however, as a +resuscitated object can re-expose other finalizable objects that have +been already finalized back to Scheme. These objects will not be +finalized again, but they could cause use-after-free problems to code +that handles objects of that particular foreign object type. To guard +against this possibility, robust finalization routines should clear +state from the foreign object, as in the above @code{free_file} example. + +One final caveat. Foreign object finalizers are associated with the +lifetime of a foreign object, not of its fields. If you access a field +of a finalizable foreign object, and do not arrange to keep a reference +on the foreign object itself, it could be that the outer foreign object +gets finalized while you are working with its field. + +For example, consider a procedure to read some data from a file, from +our example above. + +@example +SCM +read_bytes (SCM file, SCM n) +@{ + int fd; + SCM buf; + size_t len, pos; + + scm_assert_foreign_object_type (file_type, file); + + fd = scm_foreign_object_signed_ref (file, 0); + if (fd < 0) + scm_wrong_type_arg_msg ("read-bytes", SCM_ARG1, + file, "open file"); + + len = scm_to_size_t (n); + SCM buf = scm_c_make_bytevector (scm_to_size_t (n)); + + pos = 0; + while (pos < len) + @{ + char *bytes = SCM_BYTEVECTOR_CONTENTS (buf); + ssize_t count = read (fd, bytes + pos, len - pos); + if (count < 0) + scm_syserror ("read-bytes"); + if (count == 0) + break; + pos += count; + @} + + scm_remember_upto_here_1 (file); + + return scm_values (scm_list_2 (buf, scm_from_size_t (pos))); +@} +@end example + +After the prelude, only the @code{fd} value is used and the C compiler +has no reason to keep the @code{file} object around. If +@code{scm_c_make_bytevector} results in a garbage collection, +@code{file} might not be on the stack or anywhere else and could be +finalized, leaving @code{read} to read a closed (or, in a multi-threaded +program, possibly re-used) file descriptor. The use of +@code{scm_remember_upto_here_1} prevents this, by creating a reference +to @code{file} after all data accesses. @xref{Garbage Collection +Functions}. + +@code{scm_remember_upto_here_1} is only needed on finalizable objects, +because garbage collection of other values is invisible to the program +-- it happens when needed, and is not observable. But if you can, save +yourself the headache and build your program in such a way that it +doesn't need finalization. + + +@node Foreign Objects and Scheme +@subsection Foreign Objects and Scheme + +It is also possible to create foreign objects and object types from +Scheme, and to access fields of foreign objects from Scheme. For +example, the file example from the last section could be equivalently +expressed as: + +@example +(define-module (my-file) + #:use-module (system foreign-object) + #:use-module ((oop goops) #:select (make)) + #:export (make-file)) + +(define (finalize-file file) + (let ((fd (struct-ref file 0))) + (unless (< fd 0) + (struct-set! file 0 -1) + (close-fdes fd)))) + +(define <file> + (make-foreign-object-type '<file> '(fd) + #:finalizer finalize-file)) + +(define (make-file fd) + (make <file> #:fd fd)) +@end example + +Here we see that the result of @code{make-foreign-object-type}, which is +the equivalent of @code{scm_make_foreign_object_type}, is a struct +vtable. @xref{Vtables}, for more information. To instantiate the +foreign object, which is really a Guile struct, we use @code{make}. (We +could have used @code{make-struct/no-tail}, but as an implementation +detail, finalizers are attached in the @code{initialize} method called +by @code{make}). To access the fields, we use @code{struct-ref} and +@code{struct-set!}. @xref{Structure Basics}. + +There is a convenience syntax, @code{define-foreign-object-type}, that +defines a type along with a constructor, and getters for the fields. An +appropriate invocation of @code{define-foreign-object-type} for the +file object type could look like this: + +@example +(use-modules (system foreign-object)) + +(define-foreign-object-type <file> + make-file + (fd) + #:finalizer finalize-file) +@end example + +This defines the @code{<file>} type with one field, a @code{make-file} +constructor, and a getter for the @code{fd} field, bound to @code{fd}. + +Foreign object types are not only vtables but are actually GOOPS +classes, as hinted at above. @xref{GOOPS}, for more on Guile's +object-oriented programming system. Thus one can define print and +equality methods using GOOPS: + +@example +(use-modules (oop goops)) + +(define-method (write (file <file>) port) + ;; Assuming existence of the `fd' getter + (format port "#<<file> ~a>" (fd file))) + +(define-method (equal? (a <file>) (b <file>)) + (eqv? (fd a) (fd b))) +@end example + +One can even sub-class foreign types. + +@example +(define-class <named-file> (<file>) + (name #:init-keyword #:name #:init-value #f #:accessor name)) +@end example + +The question arises of how to construct these values, given that +@code{make-file} returns a plain old @code{<file>} object. It turns out +that you can use the GOOPS construction interface, where every field of +the foreign object has an associated initialization keyword argument. + +@example +(define* (my-open-file name #:optional (flags O_RDONLY)) + (make <named-file> #:fd (open-fdes name flags) #:name name)) + +(define-method (write (file <named-file>) port) + (format port "#<<file> ~s ~a>" (name file) (fd file))) +@end example + +@xref{Foreign Objects}, for full documentation on the Scheme interface +to foreign objects. @xref{GOOPS}, for more on GOOPS. + +As a final note, you might wonder how this system supports encapsulation +of sensitive values. First, we have to recognize that some facilities +are essentially unsafe and have global scope. For example, in C, the +integrity and confidentiality of a part of a program is at the mercy of +every other part of that program -- because any part of the program can +read and write anything in its address space. At the same time, +principled access to structured data is organized in C on lexical +boundaries; if you don't expose accessors for your object, you trust +other parts of the program not to work around that barrier. + +The situation is not dissimilar in Scheme. Although Scheme's unsafe +constructs are fewer in number than in C, they do exist. The +@code{(system foreign)} module can be used to violate confidentiality +and integrity, and shouldn't be exposed to untrusted code. Although +@code{struct-ref} and @code{struct-set!} are less unsafe, they still +have a cross-cutting capability of drilling through abstractions. +Performing a @code{struct-set!} on a foreign object slot could cause +unsafe foreign code to crash. Ultimately, structures in Scheme are +capabilities for abstraction, and not abstractions themselves. + +That leaves us with the lexical capabilities, like constructors and +accessors. Here is where encapsulation lies: the practical degree to +which the innards of your foreign objects are exposed is the degree to +which their accessors are lexically available in user code. If you want +to allow users to reference fields of your foreign object, provide them +with a getter. Otherwise you should assume that the only access to your +object may come from your code, which has the relevant authority, or via +code with access to cross-cutting @code{struct-ref} and such, which also +has the cross-cutting authority. diff --git a/doc/ref/libguile-linking.texi b/doc/ref/libguile-linking.texi new file mode 100644 index 000000000..433f3b378 --- /dev/null +++ b/doc/ref/libguile-linking.texi @@ -0,0 +1,199 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Linking Programs With Guile +@section Linking Programs With Guile + +This section covers the mechanics of linking your program with Guile +on a typical POSIX system. + +The header file @code{<libguile.h>} provides declarations for all of +Guile's functions and constants. You should @code{#include} it at the +head of any C source file that uses identifiers described in this +manual. Once you've compiled your source files, you need to link them +against the Guile object code library, @code{libguile}. + +As noted in the previous section, @code{<libguile.h>} is not in the +default search path for headers. The following command lines give +respectively the C compilation and link flags needed to build programs +using Guile @value{EFFECTIVE-VERSION}: + +@example +pkg-config guile-@value{EFFECTIVE-VERSION} --cflags +pkg-config guile-@value{EFFECTIVE-VERSION} --libs +@end example + +@menu +* Guile Initialization Functions:: What to call first. +* A Sample Guile Main Program:: Sources and makefiles. +@end menu + + +@node Guile Initialization Functions +@subsection Guile Initialization Functions + +To initialize Guile, you can use one of several functions. The first, +@code{scm_with_guile}, is the most portable way to initialize Guile. It +will initialize Guile when necessary and then call a function that you +can specify. Multiple threads can call @code{scm_with_guile} +concurrently and it can also be called more than once in a given thread. +The global state of Guile will survive from one call of +@code{scm_with_guile} to the next. Your function is called from within +@code{scm_with_guile} since the garbage collector of Guile needs to know +where the stack of each thread is. + +A second function, @code{scm_init_guile}, initializes Guile for the +current thread. When it returns, you can use the Guile API in the +current thread. This function employs some non-portable magic to learn +about stack bounds and might thus not be available on all platforms. + +One common way to use Guile is to write a set of C functions which +perform some useful task, make them callable from Scheme, and then link +the program with Guile. This yields a Scheme interpreter just like +@code{guile}, but augmented with extra functions for some specific +application --- a special-purpose scripting language. + +In this situation, the application should probably process its +command-line arguments in the same manner as the stock Guile +interpreter. To make that straightforward, Guile provides the +@code{scm_boot_guile} and @code{scm_shell} function. + +For more about these functions, see @ref{Initialization}. + +@node A Sample Guile Main Program +@subsection A Sample Guile Main Program + +Here is @file{simple-guile.c}, source code for a @code{main} and an +@code{inner_main} function that will produce a complete Guile +interpreter. + +@example +/* simple-guile.c --- Start Guile from C. */ + +#include <libguile.h> + +static void +inner_main (void *closure, int argc, char **argv) +@{ + /* preparation */ + scm_shell (argc, argv); + /* after exit */ +@} + +int +main (int argc, char **argv) +@{ + scm_boot_guile (argc, argv, inner_main, 0); + return 0; /* never reached, see inner_main */ +@} +@end example + +The @code{main} function calls @code{scm_boot_guile} to initialize +Guile, passing it @code{inner_main}. Once @code{scm_boot_guile} is +ready, it invokes @code{inner_main}, which calls @code{scm_shell} to +process the command-line arguments in the usual way. + +@subsection Building the Example with Make + +Here is a Makefile which you can use to compile the example program. It +uses @code{pkg-config} to learn about the necessary compiler and +linker flags. +@example +# Use GCC, if you have it installed. +CC=gcc + +# Tell the C compiler where to find <libguile.h> +CFLAGS=`pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` + +# Tell the linker what libraries to use and where to find them. +LIBS=`pkg-config --libs guile-@value{EFFECTIVE-VERSION}` + +simple-guile: simple-guile.o + $@{CC@} simple-guile.o $@{LIBS@} -o simple-guile + +simple-guile.o: simple-guile.c + $@{CC@} -c $@{CFLAGS@} simple-guile.c +@end example + +@subsection Building the Example with Autoconf + +If you are using the GNU Autoconf package to make your application more +portable, Autoconf will settle many of the details in the Makefile +automatically, making it much simpler and more portable; we recommend +using Autoconf with Guile. Here is a @file{configure.ac} file for +@code{simple-guile} that uses the standard @code{PKG_CHECK_MODULES} +macro to check for Guile. Autoconf will process this file into a +@code{configure} script. We recommend invoking Autoconf via the +@code{autoreconf} utility. + +@example +AC_INIT(simple-guile.c) + +# Find a C compiler. +AC_PROG_CC + +# Check for Guile +PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}]) + +# Generate a Makefile, based on the results. +AC_OUTPUT(Makefile) +@end example + +Run @code{autoreconf -vif} to generate @code{configure}. + +Here is a @code{Makefile.in} template, from which the @code{configure} +script produces a Makefile customized for the host system: +@example +# The configure script fills in these values. +CC=@@CC@@ +CFLAGS=@@GUILE_CFLAGS@@ +LIBS=@@GUILE_LIBS@@ + +simple-guile: simple-guile.o + $@{CC@} simple-guile.o $@{LIBS@} -o simple-guile +simple-guile.o: simple-guile.c + $@{CC@} -c $@{CFLAGS@} simple-guile.c +@end example + +The developer should use Autoconf to generate the @file{configure} +script from the @file{configure.ac} template, and distribute +@file{configure} with the application. Here's how a user might go about +building the application: + +@example +$ ls +Makefile.in configure* configure.ac simple-guile.c +$ ./configure +checking for gcc... ccache gcc +checking whether the C compiler works... yes +checking for C compiler default output file name... a.out +checking for suffix of executables... +checking whether we are cross compiling... no +checking for suffix of object files... o +checking whether we are using the GNU C compiler... yes +checking whether ccache gcc accepts -g... yes +checking for ccache gcc option to accept ISO C89... none needed +checking for pkg-config... /usr/bin/pkg-config +checking pkg-config is at least version 0.9.0... yes +checking for GUILE... yes +configure: creating ./config.status +config.status: creating Makefile +$ make +[...] +$ ./simple-guile +guile> (+ 1 2 3) +6 +guile> (getpwnam "jimb") +#("jimb" "83Z7d75W2tyJQ" 4008 10 "Jim Blandy" "/u/jimb" + "/usr/local/bin/bash") +guile> (exit) +$ +@end example + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/libguile-parallel.texi b/doc/ref/libguile-parallel.texi new file mode 100644 index 000000000..75fcd88ba --- /dev/null +++ b/doc/ref/libguile-parallel.texi @@ -0,0 +1,84 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011, +@c 2013-2014 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Parallel Installations +@section Parallel Installations + +@cindex pkg-config +@cindex effective version + +Guile provides strong API and ABI stability guarantees during stable +series, so that if a user writes a program against Guile version 2.2.3, +it will be compatible with some future version 2.2.7. We say in this +case that 2.2 is the @dfn{effective version}, composed of the major and +minor versions, in this case 2 and 2. + +Users may install multiple effective versions of Guile, with each +version's headers, libraries, and Scheme files under their own +directories. This provides the necessary stability guarantee for users, +while also allowing Guile developers to evolve the language and its +implementation. + +However, parallel installability does have a down-side, in that users +need to know which version of Guile to ask for, when they build against +Guile. Guile solves this problem by installing a file to be read by the +@code{pkg-config} utility, a tool to query installed packages by name. +Guile encodes the version into its pkg-config name, so that users can +ask for @code{guile-2.2} or @code{guile-3.0}, as appropriate. + +For effective version @value{EFFECTIVE-VERSION}, for example, you would +invoke @code{pkg-config --cflags --libs guile-@value{EFFECTIVE-VERSION}} +to get the compilation and linking flags necessary to link to version +@value{EFFECTIVE-VERSION} of Guile. You would typically run +@code{pkg-config} during the configuration phase of your program and use +the obtained information in the Makefile. + +Guile's @code{pkg-config} file, +@file{guile-@value{EFFECTIVE-VERSION}.pc}, defines additional useful +variables: + +@table @code +@item sitedir +@cindex @code{sitedir} +The default directory where Guile looks for Scheme source and compiled +files (@pxref{Installing Site Packages, %site-dir}). Run +@command{pkg-config guile-@value{EFFECTIVE-VERSION} --variable=sitedir} +to see its value. @xref{Autoconf Macros, GUILE_SITE_DIR}, for more on +how to use it from Autoconf. + +@item extensiondir +@cindex @code{extensiondir} +The default directory where Guile looks for extensions---i.e., shared +libraries providing additional features (@pxref{Modules and +Extensions}). Run @command{pkg-config guile-@value{EFFECTIVE-VERSION} +--variable=extensiondir} to see its value. + +@item guile +@itemx guild +@cindex program name transformations, dealing with +The absolute file name of the @command{guile} and @command{guild} +commands@footnote{The @code{guile} and @code{guild} variables defined +starting from Guile version 2.0.12.}. Run @command{pkg-config +guile-@value{EFFECTIVE-VERSION} --variable=guile} or +@code{--variable=guild} to see their value. + +These variables allow users to deal with program name transformations +that may be specified when configuring Guile with +@code{--program-transform-name}, @code{--program-suffix}, or +@code{--program-prefix} (@pxref{Transformation Options,,, autoconf, GNU +Autoconf Manual}). +@end table + +@noindent +See the @code{pkg-config} man page, for more information, or its web +site, @url{http://pkg-config.freedesktop.org/}. +@xref{Autoconf Support}, for more on checking for Guile from within a +@code{configure.ac} file. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/libguile-program.texi b/doc/ref/libguile-program.texi new file mode 100644 index 000000000..3b7408398 --- /dev/null +++ b/doc/ref/libguile-program.texi @@ -0,0 +1,791 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Programming Overview +@section An Overview of Guile Programming + +Guile is designed as an extension language interpreter that is +straightforward to integrate with applications written in C (and C++). +The big win here for the application developer is that Guile +integration, as the Guile web page says, ``lowers your project's +hacktivation energy.'' Lowering the hacktivation energy means that you, +as the application developer, @emph{and your users}, reap the benefits +that flow from being able to extend the application in a high level +extension language rather than in plain old C. + +In abstract terms, it's difficult to explain what this really means and +what the integration process involves, so instead let's begin by jumping +straight into an example of how you might integrate Guile into an +existing program, and what you could expect to gain by so doing. With +that example under our belts, we'll then return to a more general +analysis of the arguments involved and the range of programming options +available. + +@menu +* Extending Dia:: How one might extend Dia using Guile. +* Scheme vs C:: Why Scheme is more hackable than C. +* Testbed Example:: Example: using Guile in a testbed. +* Programming Options:: Options for Guile programming. +* User Programming:: How about application users? +@end menu + + +@node Extending Dia +@subsection How One Might Extend Dia Using Guile + +Dia is a free software program for drawing schematic diagrams like flow +charts and floor plans (@uref{http://www.gnome.org/projects/dia/}). +This section conducts the thought +experiment of adding Guile to Dia. In so doing, it aims to illustrate +several of the steps and considerations involved in adding Guile to +applications in general. + +@menu +* Dia Objective:: Deciding why you want to add Guile. +* Dia Steps:: Four steps required to add Guile. +* Dia Objects:: How to represent Dia data in Scheme. +* Dia Primitives:: Writing Guile primitives for Dia. +* Dia Hook:: Providing a hook for Scheme evaluation. +* Dia Structure:: Overall structure for adding Guile. +* Dia Advanced:: Going further with Dia and Guile. +@end menu + + +@node Dia Objective +@subsubsection Deciding Why You Want to Add Guile + +First off, you should understand why you want to add Guile to Dia at +all, and that means forming a picture of what Dia does and how it does +it. So, what are the constituents of the Dia application? + +@itemize @bullet +@item +Most importantly, the @dfn{application domain objects} --- in other +words, the concepts that differentiate Dia from another application such +as a word processor or spreadsheet: shapes, templates, connectors, +pages, plus the properties of all these things. + +@item +The code that manages the graphical face of the application, including +the layout and display of the objects above. + +@item +The code that handles input events, which indicate that the application +user is wanting to do something. +@end itemize + +@noindent +(In other words, a textbook example of the @dfn{model - view - +controller} paradigm.) + +Next question: how will Dia benefit once the Guile integration is +complete? Several (positive!) answers are possible here, and the choice +is obviously up to the application developers. Still, one answer is +that the main benefit will be the ability to manipulate Dia's +application domain objects from Scheme. + +Suppose that Dia made a set of procedures available in Scheme, +representing the most basic operations on objects such as shapes, +connectors, and so on. Using Scheme, the application user could then +write code that builds upon these basic operations to create more +complex procedures. For example, given basic procedures to enumerate +the objects on a page, to determine whether an object is a square, and +to change the fill pattern of a single shape, the user can write a +Scheme procedure to change the fill pattern of all squares on the +current page: + +@lisp +(define (change-squares'-fill-pattern new-pattern) + (for-each-shape current-page + (lambda (shape) + (if (square? shape) + (change-fill-pattern shape new-pattern))))) +@end lisp + + +@node Dia Steps +@subsubsection Four Steps Required to Add Guile + +Assuming this objective, four steps are needed to achieve it. + +First, you need a way of representing your application-specific objects +--- such as @code{shape} in the previous example --- when they are +passed into the Scheme world. Unless your objects are so simple that +they map naturally into builtin Scheme data types like numbers and +strings, you will probably want to use Guile's @dfn{foreign object} +interface to create a new Scheme data type for your objects. + +Second, you need to write code for the basic operations like +@code{for-each-shape} and @code{square?} such that they access and +manipulate your existing data structures correctly, and then make these +operations available as @dfn{primitives} on the Scheme level. + +Third, you need to provide some mechanism within the Dia application +that a user can hook into to cause arbitrary Scheme code to be +evaluated. + +Finally, you need to restructure your top-level application C code a +little so that it initializes the Guile interpreter correctly and +declares your @dfn{foreign objects} and @dfn{primitives} to the Scheme +world. + +The following subsections expand on these four points in turn. + + +@node Dia Objects +@subsubsection How to Represent Dia Data in Scheme + +For all but the most trivial applications, you will probably want to +allow some representation of your domain objects to exist on the Scheme +level. This is where foreign objects come in, and with them issues of +lifetime management and garbage collection. + +To get more concrete about this, let's look again at the example we gave +earlier of how application users can use Guile to build higher-level +functions from the primitives that Dia itself provides. + +@lisp +(define (change-squares'-fill-pattern new-pattern) + (for-each-shape current-page + (lambda (shape) + (if (square? shape) + (change-fill-pattern shape new-pattern))))) +@end lisp + +Consider what is stored here in the variable @code{shape}. For each +shape on the current page, the @code{for-each-shape} primitive calls +@code{(lambda (shape) @dots{})} with an argument representing that +shape. Question is: how is that argument represented on the Scheme +level? The issues are as follows. + +@itemize @bullet +@item +Whatever the representation, it has to be decodable again by the C code +for the @code{square?} and @code{change-fill-pattern} primitives. In +other words, a primitive like @code{square?} has somehow to be able to +turn the value that it receives back into something that points to the +underlying C structure describing a shape. + +@item +The representation must also cope with Scheme code holding on to the +value for later use. What happens if the Scheme code stores +@code{shape} in a global variable, but then that shape is deleted (in a +way that the Scheme code is not aware of), and later on some other +Scheme code uses that global variable again in a call to, say, +@code{square?}? + +@item +The lifetime and memory allocation of objects that exist @emph{only} in +the Scheme world is managed automatically by Guile's garbage collector +using one simple rule: when there are no remaining references to an +object, the object is considered dead and so its memory is freed. But +for objects that exist in both C and Scheme, the picture is more +complicated; in the case of Dia, where the @code{shape} argument passes +transiently in and out of the Scheme world, it would be quite wrong the +@strong{delete} the underlying C shape just because the Scheme code has +finished evaluation. How do we avoid this happening? +@end itemize + +One resolution of these issues is for the Scheme-level representation of +a shape to be a new, Scheme-specific C structure wrapped up as a foreign +object. The foreign object is what is passed into and out of Scheme +code, and the Scheme-specific C structure inside the foreign object +points to Dia's underlying C structure so that the code for primitives +like @code{square?} can get at it. + +To cope with an underlying shape being deleted while Scheme code is +still holding onto a Scheme shape value, the underlying C structure +should have a new field that points to the Scheme-specific foreign +object. When a shape is deleted, the relevant code chains through to +the Scheme-specific structure and sets its pointer back to the +underlying structure to NULL. Thus the foreign object value for the +shape continues to exist, but any primitive code that tries to use it +will detect that the underlying shape has been deleted because the +underlying structure pointer is NULL. + +So, to summarize the steps involved in this resolution of the problem +(and assuming that the underlying C structure for a shape is +@code{struct dia_shape}): + +@itemize @bullet +@item +Define a new Scheme-specific structure that @emph{points} to the +underlying C structure: + +@lisp +struct dia_guile_shape +@{ + struct dia_shape * c_shape; /* NULL => deleted */ +@} +@end lisp + +@item +Add a field to @code{struct dia_shape} that points to its @code{struct +dia_guile_shape} if it has one --- + +@lisp +struct dia_shape +@{ + @dots{} + struct dia_guile_shape * guile_shape; +@} +@end lisp + +@noindent +--- so that C code can set @code{guile_shape->c_shape} to NULL when the +underlying shape is deleted. + +@item +Wrap @code{struct dia_guile_shape} as a foreign object type. + +@item +Whenever you need to represent a C shape onto the Scheme level, create a +foreign object instance for it, and pass that. + +@item +In primitive code that receives a shape foreign object instance, check the +@code{c_shape} field when decoding it, to find out whether the +underlying C shape is still there. +@end itemize + +As far as memory management is concerned, the foreign object values and +their Scheme-specific structures are under the control of the garbage +collector, whereas the underlying C structures are explicitly managed in +exactly the same way that Dia managed them before we thought of adding +Guile. + +When the garbage collector decides to free a shape foreign object value, +it calls the @dfn{finalizer} function that was specified when defining +the shape foreign object type. To maintain the correctness of the +@code{guile_shape} field in the underlying C structure, this function +should chain through to the underlying C structure (if it still exists) +and set its @code{guile_shape} field to NULL. + +For full documentation on defining and using foreign object types, see +@ref{Defining New Foreign Object Types}. + + +@node Dia Primitives +@subsubsection Writing Guile Primitives for Dia + +Once the details of object representation are decided, writing the +primitive function code that you need is usually straightforward. + +A primitive is simply a C function whose arguments and return value are +all of type @code{SCM}, and whose body does whatever you want it to do. +As an example, here is a possible implementation of the @code{square?} +primitive: + +@lisp +static SCM square_p (SCM shape) +@{ + struct dia_guile_shape * guile_shape; + + /* Check that arg is really a shape object. */ + scm_assert_foreign_object_type (shape_type, shape); + + /* Access Scheme-specific shape structure. */ + guile_shape = scm_foreign_object_ref (shape, 0); + + /* Find out if underlying shape exists and is a + square; return answer as a Scheme boolean. */ + return scm_from_bool (guile_shape->c_shape && + (guile_shape->c_shape->type == DIA_SQUARE)); +@} +@end lisp + +Notice how easy it is to chain through from the @code{SCM shape} +parameter that @code{square_p} receives --- which is a foreign object +--- to the Scheme-specific structure inside the foreign object, and +thence to the underlying C structure for the shape. + +In this code, @code{scm_assert_foreign_object_type}, +@code{scm_foreign_object_ref}, and @code{scm_from_bool} are from the +standard Guile API. We assume that @code{shape_type} was given to us +when we made the shape foreign object type, using +@code{scm_make_foreign_object_type}. The call to +@code{scm_assert_foreign_object_type} ensures that @var{shape} is indeed +a shape. This is needed to guard against Scheme code using the +@code{square?} procedure incorrectly, as in @code{(square? "hello")}; +Scheme's latent typing means that usage errors like this must be caught +at run time. + +Having written the C code for your primitives, you need to make them +available as Scheme procedures by calling the @code{scm_c_define_gsubr} +function. @code{scm_c_define_gsubr} (@pxref{Primitive Procedures}) +takes arguments that specify the Scheme-level name for the primitive and +how many required, optional and rest arguments it can accept. The +@code{square?} primitive always requires exactly one argument, so the +call to make it available in Scheme reads like this: + +@lisp +scm_c_define_gsubr ("square?", 1, 0, 0, square_p); +@end lisp + +For where to put this call, see the subsection after next on the +structure of Guile-enabled code (@pxref{Dia Structure}). + + +@node Dia Hook +@subsubsection Providing a Hook for the Evaluation of Scheme Code + +To make the Guile integration useful, you have to design some kind of +hook into your application that application users can use to cause their +Scheme code to be evaluated. + +Technically, this is straightforward; you just have to decide on a +mechanism that is appropriate for your application. Think of Emacs, for +example: when you type @kbd{@key{ESC} :}, you get a prompt where you can +type in any Elisp code, which Emacs will then evaluate. Or, again like +Emacs, you could provide a mechanism (such as an init file) to allow +Scheme code to be associated with a particular key sequence, and +evaluate the code when that key sequence is entered. + +In either case, once you have the Scheme code that you want to evaluate, +as a null terminated string, you can tell Guile to evaluate it by +calling the @code{scm_c_eval_string} function. + + +@node Dia Structure +@subsubsection Top-level Structure of Guile-enabled Dia + +Let's assume that the pre-Guile Dia code looks structurally like this: + +@itemize @bullet +@item +@code{main ()} + +@itemize @bullet +@item +do lots of initialization and setup stuff +@item +enter Gtk main loop +@end itemize +@end itemize + +When you add Guile to a program, one (rather technical) requirement is +that Guile's garbage collector needs to know where the bottom of the C +stack is. The easiest way to ensure this is to use +@code{scm_boot_guile} like this: + +@itemize @bullet +@item +@code{main ()} + +@itemize @bullet +@item +do lots of initialization and setup stuff +@item +@code{scm_boot_guile (argc, argv, inner_main, NULL)} +@end itemize + +@item +@code{inner_main ()} + +@itemize @bullet +@item +define all foreign object types +@item +export primitives to Scheme using @code{scm_c_define_gsubr} +@item +enter Gtk main loop +@end itemize +@end itemize + +In other words, you move the guts of what was previously in your +@code{main} function into a new function called @code{inner_main}, and +then add a @code{scm_boot_guile} call, with @code{inner_main} as a +parameter, to the end of @code{main}. + +Assuming that you are using foreign objects and have written primitive +code as described in the preceding subsections, you also need to insert +calls to declare your new foreign objects and export the primitives to +Scheme. These declarations must happen @emph{inside} the dynamic scope +of the @code{scm_boot_guile} call, but also @emph{before} any code is +run that could possibly use them --- the beginning of @code{inner_main} +is an ideal place for this. + + +@node Dia Advanced +@subsubsection Going Further with Dia and Guile + +The steps described so far implement an initial Guile integration that +already gives a lot of additional power to Dia application users. But +there are further steps that you could take, and it's interesting to +consider a few of these. + +In general, you could progressively move more of Dia's source code from +C into Scheme. This might make the code more maintainable and +extensible, and it could open the door to new programming paradigms that +are tricky to effect in C but straightforward in Scheme. + +A specific example of this is that you could use the guile-gtk package, +which provides Scheme-level procedures for most of the Gtk+ library, to +move the code that lays out and displays Dia objects from C to Scheme. + +As you follow this path, it naturally becomes less useful to maintain a +distinction between Dia's original non-Guile-related source code, and +its later code implementing foreign objects and primitives for the +Scheme world. + +For example, suppose that the original source code had a +@code{dia_change_fill_pattern} function: + +@lisp +void dia_change_fill_pattern (struct dia_shape * shape, + struct dia_pattern * pattern) +@{ + /* real pattern change work */ +@} +@end lisp + +During initial Guile integration, you add a @code{change_fill_pattern} +primitive for Scheme purposes, which accesses the underlying structures +from its foreign object values and uses @code{dia_change_fill_pattern} +to do the real work: + +@lisp +SCM change_fill_pattern (SCM shape, SCM pattern) +@{ + struct dia_shape * d_shape; + struct dia_pattern * d_pattern; + + @dots{} + + dia_change_fill_pattern (d_shape, d_pattern); + + return SCM_UNSPECIFIED; +@} +@end lisp + +At this point, it makes sense to keep @code{dia_change_fill_pattern} and +@code{change_fill_pattern} separate, because +@code{dia_change_fill_pattern} can also be called without going through +Scheme at all, say because the user clicks a button which causes a +C-registered Gtk+ callback to be called. + +But, if the code for creating buttons and registering their callbacks is +moved into Scheme (using guile-gtk), it may become true that +@code{dia_change_fill_pattern} can no longer be called other than +through Scheme. In which case, it makes sense to abolish it and move +its contents directly into @code{change_fill_pattern}, like this: + +@lisp +SCM change_fill_pattern (SCM shape, SCM pattern) +@{ + struct dia_shape * d_shape; + struct dia_pattern * d_pattern; + + @dots{} + + /* real pattern change work */ + + return SCM_UNSPECIFIED; +@} +@end lisp + +So further Guile integration progressively @emph{reduces} the amount of +functional C code that you have to maintain over the long term. + +A similar argument applies to data representation. In the discussion of +foreign objects earlier, issues arose because of the different memory +management and lifetime models that normally apply to data structures in +C and in Scheme. However, with further Guile integration, you can +resolve this issue in a more radical way by allowing all your data +structures to be under the control of the garbage collector, and kept +alive by references from the Scheme world. Instead of maintaining an +array or linked list of shapes in C, you would instead maintain a list +in Scheme. + +Rather like the coalescing of @code{dia_change_fill_pattern} and +@code{change_fill_pattern}, the practical upshot of such a change is +that you would no longer have to keep the @code{dia_shape} and +@code{dia_guile_shape} structures separate, and so wouldn't need to +worry about the pointers between them. Instead, you could change the +foreign object definition to wrap the @code{dia_shape} structure +directly, and send @code{dia_guile_shape} off to the scrap yard. Cut +out the middle man! + +Finally, we come to the holy grail of Guile's free software / extension +language approach. Once you have a Scheme representation for +interesting Dia data types like shapes, and a handy bunch of primitives +for manipulating them, it suddenly becomes clear that you have a bundle +of functionality that could have far-ranging use beyond Dia itself. In +other words, the data types and primitives could now become a library, +and Dia becomes just one of the many possible applications using that +library --- albeit, at this early stage, a rather important one! + +In this model, Guile becomes just the glue that binds everything +together. Imagine an application that usefully combined functionality +from Dia, Gnumeric and GnuCash --- it's tricky right now, because no +such application yet exists; but it'll happen some day @dots{} + + +@node Scheme vs C +@subsection Why Scheme is More Hackable Than C + +Underlying Guile's value proposition is the assumption that programming +in a high level language, specifically Guile's implementation of Scheme, +is necessarily better in some way than programming in C. What do we +mean by this claim, and how can we be so sure? + +One class of advantages applies not only to Scheme, but more generally +to any interpretable, high level, scripting language, such as Emacs +Lisp, Python, Ruby, or @TeX{}'s macro language. Common features of all +such languages, when compared to C, are that: + +@itemize @bullet +@item +They lend themselves to rapid and experimental development cycles, +owing usually to a combination of their interpretability and the +integrated development environment in which they are used. + +@item +They free developers from some of the low level bookkeeping tasks +associated with C programming, notably memory management. + +@item +They provide high level features such as container objects and exception +handling that make common programming tasks easier. +@end itemize + +In the case of Scheme, particular features that make programming easier +--- and more fun! --- are its powerful mechanisms for abstracting parts +of programs (closures --- @pxref{About Closure}) and for iteration +(@pxref{while do}). + +The evidence in support of this argument is empirical: the huge amount +of code that has been written in extension languages for applications +that support this mechanism. Most notable are extensions written in +Emacs Lisp for GNU Emacs, in @TeX{}'s macro language for @TeX{}, and in +Script-Fu for the Gimp, but there is increasingly now a significant code +eco-system for Guile-based applications as well, such as Lilypond and +GnuCash. It is close to inconceivable that similar amounts of +functionality could have been added to these applications just by +writing new code in their base implementation languages. + + +@node Testbed Example +@subsection Example: Using Guile for an Application Testbed + +As an example of what this means in practice, imagine writing a testbed +for an application that is tested by submitting various requests (via a +C interface) and validating the output received. Suppose further that +the application keeps an idea of its current state, and that the +``correct'' output for a given request may depend on the current +application state. A complete ``white box''@footnote{A @dfn{white box} +test plan is one that incorporates knowledge of the internal design of +the application under test.} test plan for this application would aim to +submit all possible requests in each distinguishable state, and validate +the output for all request/state combinations. + +To write all this test code in C would be very tedious. Suppose instead +that the testbed code adds a single new C function, to submit an +arbitrary request and return the response, and then uses Guile to export +this function as a Scheme procedure. The rest of the testbed can then +be written in Scheme, and so benefits from all the advantages of +programming in Scheme that were described in the previous section. + +(In this particular example, there is an additional benefit of writing +most of the testbed in Scheme. A common problem for white box testing +is that mistakes and mistaken assumptions in the application under test +can easily be reproduced in the testbed code. It is more difficult to +copy mistakes like this when the testbed is written in a different +language from the application.) + + +@node Programming Options +@subsection A Choice of Programming Options + +The preceding arguments and example point to a model of Guile +programming that is applicable in many cases. According to this model, +Guile programming involves a balance between C and Scheme programming, +with the aim being to extract the greatest possible Scheme level benefit +from the least amount of C level work. + +The C level work required in this model usually consists of packaging +and exporting functions and application objects such that they can be +seen and manipulated on the Scheme level. To help with this, Guile's C +language interface includes utility features that aim to make this kind +of integration very easy for the application developer. These features +are documented later in this part of the manual: see REFFIXME. + +This model, though, is really just one of a range of possible +programming options. If all of the functionality that you need is +available from Scheme, you could choose instead to write your whole +application in Scheme (or one of the other high level languages that +Guile supports through translation), and simply use Guile as an +interpreter for Scheme. (In the future, we hope that Guile will also be +able to compile Scheme code, so lessening the performance gap between C +and Scheme code.) Or, at the other end of the C--Scheme scale, you +could write the majority of your application in C, and only call out to +Guile occasionally for specific actions such as reading a configuration +file or executing a user-specified extension. The choices boil down to +two basic questions: + +@itemize @bullet +@item +Which parts of the application do you write in C, and which in Scheme +(or another high level translated language)? + +@item +How do you design the interface between the C and Scheme parts of your +application? +@end itemize + +These are of course design questions, and the right design for any given +application will always depend upon the particular requirements that you +are trying to meet. In the context of Guile, however, there are some +generally applicable considerations that can help you when designing +your answers. + +@menu +* Available Functionality:: What functionality is already available? +* Basic Constraints:: Functional and performance constraints. +* Style Choices:: Your preferred programming style. +* Program Control:: What controls program execution? +@end menu + + +@node Available Functionality +@subsubsection What Functionality is Already Available? + +Suppose, for the sake of argument, that you would prefer to write your +whole application in Scheme. Then the API available to you consists of: + +@itemize @bullet +@item +standard Scheme + +@item +plus the extensions to standard Scheme provided by +Guile in its core distribution + +@item +plus any additional functionality that you or others have packaged so +that it can be loaded as a Guile Scheme module. +@end itemize + +A module in the last category can either be a pure Scheme module --- in +other words a collection of utility procedures coded in Scheme --- or a +module that provides a Scheme interface to an extension library coded in +C --- in other words a nice package where someone else has done the work +of wrapping up some useful C code for you. The set of available modules +is growing quickly and already includes such useful examples as +@code{(gtk gtk)}, which makes Gtk+ drawing functions available in +Scheme, and @code{(database postgres)}, which provides SQL access to a +Postgres database. + +Given the growing collection of pre-existing modules, it is quite +feasible that your application could be implemented by combining a +selection of these modules together with new application code written in +Scheme. + +If this approach is not enough, because the functionality that your +application needs is not already available in this form, and it is +impossible to write the new functionality in Scheme, you will need to +write some C code. If the required function is already available in C +(e.g.@: in a library), all you need is a little glue to connect it to the +world of Guile. If not, you need both to write the basic code and to +plumb it into Guile. + +In either case, two general considerations are important. Firstly, what +is the interface by which the functionality is presented to the Scheme +world? Does the interface consist only of function calls (for example, +a simple drawing interface), or does it need to include @dfn{objects} of +some kind that can be passed between C and Scheme and manipulated by +both worlds. Secondly, how does the lifetime and memory management of +objects in the C code relate to the garbage collection governed approach +of Scheme objects? In the case where the basic C code is not already +written, most of the difficulties of memory management can be avoided by +using Guile's C interface features from the start. + +For the full documentation on writing C code for Guile and connecting +existing C code to the Guile world, see REFFIXME. + + +@node Basic Constraints +@subsubsection Functional and Performance Constraints + + +@node Style Choices +@subsubsection Your Preferred Programming Style + + +@node Program Control +@subsubsection What Controls Program Execution? + + +@node User Programming +@subsection How About Application Users? + +So far we have considered what Guile programming means for an +application developer. But what if you are instead @emph{using} an +existing Guile-based application, and want to know what your +options are for programming and extending this application? + +The answer to this question varies from one application to another, +because the options available depend inevitably on whether the +application developer has provided any hooks for you to hang your own +code on and, if there are such hooks, what they allow you to +do.@footnote{Of course, in the world of free software, you always have +the freedom to modify the application's source code to your own +requirements. Here we are concerned with the extension options that the +application has provided for without your needing to modify its source +code.} For example@dots{} + +@itemize @bullet +@item +If the application permits you to load and execute any Guile code, the +world is your oyster. You can extend the application in any way that +you choose. + +@item +A more cautious application might allow you to load and execute Guile +code, but only in a @dfn{safe} environment, where the interface +available is restricted by the application from the standard Guile API. + +@item +Or a really fearful application might not provide a hook to really +execute user code at all, but just use Scheme syntax as a convenient way +for users to specify application data or configuration options. +@end itemize + +In the last two cases, what you can do is, by definition, restricted by +the application, and you should refer to the application's own manual to +find out your options. + +The most well known example of the first case is Emacs, with its +extension language Emacs Lisp: as well as being a text editor, Emacs +supports the loading and execution of arbitrary Emacs Lisp code. The +result of such openness has been dramatic: Emacs now benefits from +user-contributed Emacs Lisp libraries that extend the basic editing +function to do everything from reading news to psychoanalysis and +playing adventure games. The only limitation is that extensions are +restricted to the functionality provided by Emacs's built-in set of +primitive operations. For example, you can interact and display data by +manipulating the contents of an Emacs buffer, but you can't pop-up and +draw a window with a layout that is totally different to the Emacs +standard. + +This situation with a Guile application that supports the loading of +arbitrary user code is similar, except perhaps even more so, because +Guile also supports the loading of extension libraries written in C. +This last point enables user code to add new primitive operations to +Guile, and so to bypass the limitation present in Emacs Lisp. + +At this point, the distinction between an application developer and an +application user becomes rather blurred. Instead of seeing yourself as +a user extending an application, you could equally well say that you are +developing a new application of your own using some of the primitive +functionality provided by the original application. As such, all the +discussions of the preceding sections of this chapter are relevant to +how you can proceed with developing your extension. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/libguile-snarf.texi b/doc/ref/libguile-snarf.texi new file mode 100644 index 000000000..9b0e42fa3 --- /dev/null +++ b/doc/ref/libguile-snarf.texi @@ -0,0 +1,131 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2012, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Function Snarfing +@section Function Snarfing + +When writing C code for use with Guile, you typically define a set of +C functions, and then make some of them visible to the Scheme world by +calling @code{scm_c_define_gsubr} or related functions. If you have +many functions to publish, it can sometimes be annoying to keep the +list of calls to @code{scm_c_define_gsubr} in sync with the list of +function definitions. + +Guile provides the @code{guile-snarf} program to manage this problem. +Using this tool, you can keep all the information needed to define the +function alongside the function definition itself; @code{guile-snarf} +will extract this information from your source code, and automatically +generate a file of calls to @code{scm_c_define_gsubr} which you can +@code{#include} into an initialization function. + +The snarfing mechanism works for many kind of initialization actions, +not just for collecting calls to @code{scm_c_define_gsubr}. For a +full list of what can be done, @xref{Snarfing Macros}. + +@cindex guile-snarf invocation +@cindex guile-snarf example + +The @code{guile-snarf} program is invoked like this: + +@smallexample +guile-snarf [-o @var{outfile}] [@var{cpp-args} ...] +@end smallexample + +This command will extract initialization actions to @var{outfile}. +When no @var{outfile} has been specified or when @var{outfile} is +@code{-}, standard output will be used. The C preprocessor is called +with @var{cpp-args} (which usually include an input file) and the +output is filtered to extract the initialization actions. + +If there are errors during processing, @var{outfile} is deleted and the +program exits with non-zero status. + +During snarfing, the pre-processor macro @code{SCM_MAGIC_SNARFER} is +defined. You could use this to avoid including snarfer output files +that don't yet exist by writing code like this: + +@smallexample +#ifndef SCM_MAGIC_SNARFER +#include "foo.x" +#endif +@end smallexample + +Here is how you might define the Scheme function @code{clear-image}, +implemented by the C function @code{clear_image}: + +@example +@group +#include <libguile.h> + +SCM_DEFINE (clear_image, "clear-image", 1, 0, 0, + (SCM image), + "Clear the image.") +@{ + /* C code to clear the image in @code{image}... */ +@} + +void +init_image_type () +@{ +#include "image-type.x" +@} +@end group +@end example + +The @code{SCM_DEFINE} declaration says that the C function +@code{clear_image} implements a Scheme function called +@code{clear-image}, which takes one required argument (of type +@code{SCM} and named @code{image}), no optional arguments, and no rest +argument. The string @code{"Clear the image."} provides a short help +text for the function, it is called a @dfn{docstring}. + +@code{SCM_DEFINE} macro also defines a static array of characters +initialized to the Scheme name of the function. In this case, +@code{s_clear_image} is set to the C string, "clear-image". You might +want to use this symbol when generating error messages. + +Assuming the text above lives in a file named @file{image-type.c}, you +will need to execute the following command to prepare this file for +compilation: + +@example +guile-snarf -o image-type.x image-type.c +@end example + +This scans @file{image-type.c} for @code{SCM_DEFINE} +declarations, and writes to @file{image-type.x} the output: + +@example +scm_c_define_gsubr ("clear-image", 1, 0, 0, (SCM (*)() ) clear_image); +@end example + +When compiled normally, @code{SCM_DEFINE} is a macro which expands to +the function header for @code{clear_image}. + +Note that the output file name matches the @code{#include} from the +input file. Also, you still need to provide all the same information +you would if you were using @code{scm_c_define_gsubr} yourself, but you +can place the information near the function definition itself, so it is +less likely to become incorrect or out-of-date. + +If you have many files that @code{guile-snarf} must process, you should +consider using a fragment like the following in your Makefile: + +@example +snarfcppopts = $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +.SUFFIXES: .x +.c.x: + guile-snarf -o $@@ $< $(snarfcppopts) +@end example + +This tells make to run @code{guile-snarf} to produce each needed +@file{.x} file from the corresponding @file{.c} file. + +The program @code{guile-snarf} passes its command-line arguments +directly to the C preprocessor, which it uses to extract the +information it needs from the source code. this means you can pass +normal compilation flags to @code{guile-snarf} to define preprocessor +symbols, add header file directories, and so on. diff --git a/doc/ref/match.texi b/doc/ref/match.texi new file mode 100644 index 000000000..0fc5105d1 --- /dev/null +++ b/doc/ref/match.texi @@ -0,0 +1,308 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. +@c + +@c The pattern syntax is taken from the documentation available in +@c Andrew K. Wright's implementation of `match.scm', which is in the +@c public domain. See Guile before commit +@c d967913f05301a35573c5d3f7217d0994bbb1016 (Thu Jun 17 2010) or +@c <http://www.cs.indiana.edu/scheme-repository/code.match.html>. + +@c FIXME: This section is a bit rough on the edges. The introduction +@c could be improved, e.g., by adding examples. + +@node Pattern Matching +@section Pattern Matching + +@cindex pattern matching +@cindex (ice-9 match) + +The @code{(ice-9 match)} module provides a @dfn{pattern matcher}, +written by Alex Shinn, and compatible with Andrew K. Wright's pattern +matcher found in many Scheme implementations. + +@cindex pattern variable +A pattern matcher can match an object against several patterns and +extract the elements that make it up. Patterns can represent any Scheme +object: lists, strings, symbols, records, etc. They can optionally contain +@dfn{pattern variables}. When a matching pattern is found, an +expression associated with the pattern is evaluated, optionally with all +pattern variables bound to the corresponding elements of the object: + +@example +(let ((l '(hello (world)))) + (match l ;; <- the input object + (('hello (who)) ;; <- the pattern + who))) ;; <- the expression evaluated upon matching +@result{} world +@end example + +In this example, list @var{l} matches the pattern @code{('hello (who))}, +because it is a two-element list whose first element is the symbol +@code{hello} and whose second element is a one-element list. Here +@var{who} is a pattern variable. @code{match}, the pattern matcher, +locally binds @var{who} to the value contained in this one-element +list---i.e., the symbol @code{world}. An error would be raised if +@var{l} did not match the pattern. + +The same object can be matched against a simpler pattern: + +@example +(let ((l '(hello (world)))) + (match l + ((x y) + (values x y)))) +@result{} hello +@result{} (world) +@end example + +Here pattern @code{(x y)} matches any two-element list, regardless of +the types of these elements. Pattern variables @var{x} and @var{y} are +bound to, respectively, the first and second element of @var{l}. + +Patterns can be composed, and nested. For instance, @code{...} +(ellipsis) means that the previous pattern may be matched zero or more +times in a list: + +@example +(match lst + (((heads tails ...) ...) + heads)) +@end example + +@noindent +This expression returns the first element of each list within @var{lst}. +For proper lists of proper lists, it is equivalent to @code{(map car +lst)}. However, it performs additional checks to make sure that +@var{lst} and the lists therein are proper lists, as prescribed by the +pattern, raising an error if they are not. + +Compared to hand-written code, pattern matching noticeably improves +clarity and conciseness---no need to resort to series of @code{car} and +@code{cdr} calls when matching lists, for instance. It also improves +robustness, by making sure the input @emph{completely} matches the +pattern---conversely, hand-written code often trades robustness for +conciseness. And of course, @code{match} is a macro, and the code it +expands to is just as efficient as equivalent hand-written code. + +The pattern matcher is defined as follows: + +@deffn {Scheme Syntax} match exp clause1 clause2 @dots{} +Match object @var{exp} against the patterns in @var{clause1} +@var{clause2} @dots{} in the order in which they appear. Return the +value produced by the first matching clause. If no clause matches, +throw an exception with key @code{match-error}. + +Each clause has the form @code{(pattern body1 body2 @dots{})}. Each +@var{pattern} must follow the syntax described below. Each body is an +arbitrary Scheme expression, possibly referring to pattern variables of +@var{pattern}. +@end deffn + +@c FIXME: Document other forms: +@c +@c exp ::= ... +@c | (match exp clause ...) +@c | (match-lambda clause ...) +@c | (match-lambda* clause ...) +@c | (match-let ((pat exp) ...) body) +@c | (match-let* ((pat exp) ...) body) +@c | (match-letrec ((pat exp) ...) body) +@c | (match-define pat exp) +@c +@c clause ::= (pat body) | (pat => exp) + +The syntax and interpretation of patterns is as follows: + +@verbatim + patterns: matches: + +pat ::= identifier anything, and binds identifier + | _ anything + | () the empty list + | #t #t + | #f #f + | string a string + | number a number + | character a character + | 'sexp an s-expression + | 'symbol a symbol (special case of s-expr) + | (pat_1 ... pat_n) list of n elements + | (pat_1 ... pat_n . pat_{n+1}) list of n or more + | (pat_1 ... pat_n pat_n+1 ooo) list of n or more, each element + of remainder must match pat_n+1 + | #(pat_1 ... pat_n) vector of n elements + | #(pat_1 ... pat_n pat_n+1 ooo) vector of n or more, each element + of remainder must match pat_n+1 + | #&pat box + | ($ record-name pat_1 ... pat_n) a record + | (= field pat) a ``field'' of an object + | (and pat_1 ... pat_n) if all of pat_1 thru pat_n match + | (or pat_1 ... pat_n) if any of pat_1 thru pat_n match + | (not pat_1 ... pat_n) if all pat_1 thru pat_n don't match + | (? predicate pat_1 ... pat_n) if predicate true and all of + pat_1 thru pat_n match + | (set! identifier) anything, and binds setter + | (get! identifier) anything, and binds getter + | `qp a quasi-pattern + | (identifier *** pat) matches pat in a tree and binds + identifier to the path leading + to the object that matches pat + +ooo ::= ... zero or more + | ___ zero or more + | ..1 1 or more + + quasi-patterns: matches: + +qp ::= () the empty list + | #t #t + | #f #f + | string a string + | number a number + | character a character + | identifier a symbol + | (qp_1 ... qp_n) list of n elements + | (qp_1 ... qp_n . qp_{n+1}) list of n or more + | (qp_1 ... qp_n qp_n+1 ooo) list of n or more, each element + of remainder must match qp_n+1 + | #(qp_1 ... qp_n) vector of n elements + | #(qp_1 ... qp_n qp_n+1 ooo) vector of n or more, each element + of remainder must match qp_n+1 + | #&qp box + | ,pat a pattern + | ,@pat a pattern +@end verbatim + +The names @code{quote}, @code{quasiquote}, @code{unquote}, +@code{unquote-splicing}, @code{?}, @code{_}, @code{$}, @code{and}, +@code{or}, @code{not}, @code{set!}, @code{get!}, @code{...}, and +@code{___} cannot be used as pattern variables. + +Here is a more complex example: + +@example +(use-modules (srfi srfi-9)) + +(let () + (define-record-type person + (make-person name friends) + person? + (name person-name) + (friends person-friends)) + + (letrec ((alice (make-person "Alice" (delay (list bob)))) + (bob (make-person "Bob" (delay (list alice))))) + (match alice + (($ person name (= force (($ person "Bob")))) + (list 'friend-of-bob name)) + (_ #f)))) + +@result{} (friend-of-bob "Alice") +@end example + +@noindent +Here the @code{$} pattern is used to match a SRFI-9 record of type +@var{person} containing two or more slots. The value of the first slot +is bound to @var{name}. The @code{=} pattern is used to apply +@code{force} on the second slot, and then checking that the result +matches the given pattern. In other words, the complete pattern matches +any @var{person} whose second slot is a promise that evaluates to a +one-element list containing a @var{person} whose first slot is +@code{"Bob"}. + +The @code{(ice-9 match)} module also provides the following convenient +syntactic sugar macros wrapping around @code{match}. + +@deffn {Scheme Syntax} match-lambda exp clause1 clause2 @dots{} +Create a procedure of one argument that matches its argument against +each clause, and returns the result of evaluating the corresponding +expressions. + +@example +(match-lambda clause1 clause2 @dots{}) +@equiv{} +(lambda (arg) (match arg clause1 clause2 @dots{})) +@end example +@end deffn + +@example +((match-lambda + (('hello (who)) + who)) + '(hello (world))) +@result{} world +@end example + +@deffn {Scheme Syntax} match-lambda* exp clause1 clause2 @dots{} +Create a procedure of any number of arguments that matches its argument +list against each clause, and returns the result of evaluating the +corresponding expressions. + +@example +(match-lambda* clause1 clause2 @dots{}) +@equiv{} +(lambda args (match args clause1 clause2 @dots{})) +@end example +@end deffn + +@example +((match-lambda* + (('hello (who)) + who)) + 'hello '(world)) +@result{} world +@end example + +@deffn {Scheme Syntax} match-let ((pattern expression) @dots{}) body +Match each pattern to the corresponding expression, and evaluate the +body with all matched variables in scope. Raise an error if any of the +expressions fail to match. @code{match-let} is analogous to named let +and can also be used for recursive functions which match on their +arguments as in @code{match-lambda*}. + +@example +(match-let (((x y) (list 1 2)) + ((a b) (list 3 4))) + (list a b x y)) +@result{} +(3 4 1 2) +@end example +@end deffn + +@deffn {Scheme Syntax} match-let variable ((pattern init) @dots{}) body +Similar to @code{match-let}, but analogously to @dfn{named let}, locally +bind VARIABLE to a new procedure which accepts as many arguments as +there are INIT expressions. The procedure is initially applied to the +results of evaluating the INIT expressions. When called, the procedure +matches each argument against the corresponding PATTERN, and returns the +result(s) of evaluating the BODY expressions. @xref{while do, +Iteration}, for more on @dfn{named let}. +@end deffn + +@deffn {Scheme Syntax} match-let* ((variable expression) @dots{}) body +Similar to @code{match-let}, but analogously to @code{let*}, match and +bind the variables in sequence, with preceding match variables in scope. + +@example +(match-let* (((x y) (list 1 2)) + ((a b) (list x 4))) + (list a b x y)) +@equiv{} +(match-let (((x y) (list 1 2))) + (match-let (((a b) (list x 4))) + (list a b x y))) +@result{} +(1 4 1 2) +@end example +@end deffn + +@deffn {Scheme Syntax} match-letrec ((variable expression) @dots{}) body +Similar to @code{match-let}, but analogously to @code{letrec}, match and +bind the variables with all match variables in scope. +@end deffn + +Guile also comes with a pattern matcher specifically tailored to SXML +trees, @xref{sxml-match}. diff --git a/doc/ref/misc-modules.texi b/doc/ref/misc-modules.texi new file mode 100644 index 000000000..6c899a905 --- /dev/null +++ b/doc/ref/misc-modules.texi @@ -0,0 +1,1801 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2009, +@c 2010, 2011, 2012 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Pretty Printing +@section Pretty Printing + +@c FIXME::martin: Review me! + +@cindex pretty printing +The module @code{(ice-9 pretty-print)} provides the procedure +@code{pretty-print}, which provides nicely formatted output of Scheme +objects. This is especially useful for deeply nested or complex data +structures, such as lists and vectors. + +The module is loaded by entering the following: + +@lisp +(use-modules (ice-9 pretty-print)) +@end lisp + +This makes the procedure @code{pretty-print} available. As an example +how @code{pretty-print} will format the output, see the following: + +@lisp +(pretty-print '(define (foo) (lambda (x) +(cond ((zero? x) #t) ((negative? x) -x) (else +(if (= x 1) 2 (* x x x))))))) +@print{} +(define (foo) + (lambda (x) + (cond ((zero? x) #t) + ((negative? x) -x) + (else (if (= x 1) 2 (* x x x)))))) +@end lisp + +@deffn {Scheme Procedure} pretty-print obj [port] [keyword-options] +Print the textual representation of the Scheme object @var{obj} to +@var{port}. @var{port} defaults to the current output port, if not +given. + +The further @var{keyword-options} are keywords and parameters as +follows, + +@table @asis +@item @nicode{#:display?} @var{flag} +If @var{flag} is true then print using @code{display}. The default is +@code{#f} which means use @code{write} style. @xref{Scheme Write}. + +@item @nicode{#:per-line-prefix} @var{string} +Print the given @var{string} as a prefix on each line. The default is +no prefix. + +@item @nicode{#:width} @var{columns} +Print within the given @var{columns}. The default is 79. + +@item @nicode{#:max-expr-width} @var{columns} +The maximum width of an expression. The default is 50. +@end table +@end deffn + + +@cindex truncated printing +Also exported by the @code{(ice-9 pretty-print)} module is +@code{truncated-print}, a procedure to print Scheme datums, truncating +the output to a certain number of characters. This is useful when you +need to present an arbitrary datum to the user, but you only have one +line in which to do so. + +@lisp +(define exp '(a b #(c d e) f . g)) +(truncated-print exp #:width 10) (newline) +@print{} (a b . #) +(truncated-print exp #:width 15) (newline) +@print{} (a b # f . g) +(truncated-print exp #:width 18) (newline) +@print{} (a b #(c ...) . #) +(truncated-print exp #:width 20) (newline) +@print{} (a b #(c d e) f . g) +(truncated-print "The quick brown fox" #:width 20) (newline) +@print{} "The quick brown..." +(truncated-print (current-module) #:width 20) (newline) +@print{} #<directory (gui...> +@end lisp + +@code{truncated-print} will not output a trailing newline. If an expression does +not fit in the given width, it will be truncated -- possibly +ellipsized@footnote{On Unicode-capable ports, the ellipsis is represented by +character `HORIZONTAL ELLIPSIS' (U+2026), otherwise it is represented by three +dots.}, or in the worst case, displayed as @nicode{#}. + +@deffn {Scheme Procedure} truncated-print obj [port] [keyword-options] +Print @var{obj}, truncating the output, if necessary, to make it fit +into @var{width} characters. By default, @var{obj} will be printed using +@code{write}, though that behavior can be overridden via the +@var{display?} keyword argument. + +The default behaviour is to print depth-first, meaning that the entire +remaining width will be available to each sub-expression of @var{obj} -- +e.g., if @var{obj} is a vector, each member of @var{obj}. One can attempt to +``ration'' the available width, trying to allocate it equally to each +sub-expression, via the @var{breadth-first?} keyword argument. + +The further @var{keyword-options} are keywords and parameters as +follows, + +@table @asis +@item @nicode{#:display?} @var{flag} +If @var{flag} is true then print using @code{display}. The default is +@code{#f} which means use @code{write} style. @pxref{Scheme Write}. + +@item @nicode{#:width} @var{columns} +Print within the given @var{columns}. The default is 79. + +@item @nicode{#:breadth-first?} @var{flag} +If @var{flag} is true, then allocate the available width breadth-first +among elements of a compound data structure (list, vector, pair, +etc.). The default is @code{#f} which means that any element is +allowed to consume all of the available width. +@end table +@end deffn + + +@node Formatted Output +@section Formatted Output +@cindex formatted output + +@c For reference, in this section escapes like ~a are given in +@c @nicode, to give code font in TeX etc, but leave them unadorned in +@c Info. +@c +@c The idea is to reduce clutter around what's shown, and avoid any +@c possible confusion over whether the ` ' quotes are part of what +@c should be entered. (In particular for instance of course ' is +@c meaningful in a format string, introducing a char parameter). + +The @code{format} function is a powerful way to print numbers, strings +and other objects together with literal text under the control of a +format string. This function is available from + +@example +(use-modules (ice-9 format)) +@end example + +A format string is generally more compact and easier than using just +the standard procedures like @code{display}, @code{write} and +@code{newline}. Parameters in the output string allow various output +styles, and parameters can be taken from the arguments for runtime +flexibility. + +@code{format} is similar to the Common Lisp procedure of the same +name, but it's not identical and doesn't have quite all the features +found in Common Lisp. + +C programmers will note the similarity between @code{format} and +@code{printf}, though escape sequences are marked with @nicode{~} +instead of @nicode{%}, and are more powerful. + +@sp 1 +@deffn {Scheme Procedure} format dest fmt arg @dots{} +Write output specified by the @var{fmt} string to @var{dest}. +@var{dest} can be an output port, @code{#t} for +@code{current-output-port} (@pxref{Default Ports}), or @code{#f} to +return the output as a string. + +@var{fmt} can contain literal text to be output, and @nicode{~} +escapes. Each escape has the form + +@example +~ [param [, param@dots{}] [:] [@@] code +@end example + +@nicode{code} is a character determining the escape sequence. The +@nicode{:} and @nicode{@@} characters are optional modifiers, one or +both of which change the way various codes operate. Optional +parameters are accepted by some codes too. Parameters have the +following forms, + +@table @asis +@item @nicode{[+/-]number} +An integer, with optional @nicode{+} or @nicode{-}. +@item @nicode{'} (apostrophe) +The following character in the format string, for instance @nicode{'z} +for @nicode{z}. +@item @nicode{v} +The next function argument as the parameter. @nicode{v} stands for +``variable'', a parameter can be calculated at runtime and included in +the arguments. Upper case @nicode{V} can be used too. +@item @nicode{#} +The number of arguments remaining. (See @nicode{~*} below for some +usages.) +@end table + +Parameters are separated by commas (@nicode{,}). A parameter can be +left empty to keep its default value when supplying later parameters. + +@sp 1 +The following escapes are available. The code letters are not +case-sensitive, upper and lower case are the same. + +@table @asis +@item @nicode{~a} +@itemx @nicode{~s} +Object output. Parameters: @var{minwidth}, @var{padinc}, +@var{minpad}, @var{padchar}. + +@nicode{~a} outputs an argument like @code{display}, @nicode{~s} +outputs an argument like @code{write} (@pxref{Scheme Write}). + +@example +(format #t "~a" "foo") @print{} foo +(format #t "~s" "foo") @print{} "foo" +@end example + +@nicode{~:a} and @nicode{~:s} put objects that don't have an external +representation in quotes like a string. + +@example +(format #t "~:a" car) @print{} "#<primitive-procedure car>" +@end example + +If the output is less than @var{minwidth} characters (default 0), it's +padded on the right with @var{padchar} (default space). @nicode{~@@a} +and @nicode{~@@s} put the padding on the left instead. + +@example +(format #f "~5a" 'abc) @result{} "abc " +(format #f "~5,,,'-@@a" 'abc) @result{} "--abc" +@end example + +@var{minpad} is a minimum for the padding then plus a multiple of +@var{padinc}. Ie.@: the padding is @math{@var{minpad} + @var{N} * +@var{padinc}}, where @var{n} is the smallest integer making the total +object plus padding greater than or equal to @var{minwidth}. The +default @var{minpad} is 0 and the default @var{padinc} is 1 (imposing +no minimum or multiple). + +@example +(format #f "~5,1,4a" 'abc) @result{} "abc " +@end example + +@item @nicode{~c} +Character. Parameter: @var{charnum}. + +Output a character. The default is to simply output, as per +@code{write-char} (@pxref{Venerable Port Interfaces}). @nicode{~@@c} +prints in @code{write} style. @nicode{~:c} prints control characters +(ASCII 0 to 31) in @nicode{^X} form. + +@example +(format #t "~c" #\z) @print{} z +(format #t "~@@c" #\z) @print{} #\z +(format #t "~:c" #\newline) @print{} ^J +@end example + +If the @var{charnum} parameter is given then an argument is not taken +but instead the character is @code{(integer->char @var{charnum})} +(@pxref{Characters}). This can be used for instance to output +characters given by their ASCII code. + +@example +(format #t "~65c") @print{} A +@end example + +@item @nicode{~d} +@itemx @nicode{~x} +@itemx @nicode{~o} +@itemx @nicode{~b} +Integer. Parameters: @var{minwidth}, @var{padchar}, @var{commachar}, +@var{commawidth}. + +Output an integer argument as a decimal, hexadecimal, octal or binary +integer (respectively), in a locale-independent way. + +@example +(format #t "~d" 123) @print{} 123 +@end example + +@nicode{~@@d} etc shows a @nicode{+} sign is shown on positive +numbers. + +@c FIXME: "+" is not shown on zero, unlike in Common Lisp. Should +@c that be changed in the code, or is it too late and should just be +@c documented that way? + +@example +(format #t "~@@b" 12) @print{} +1100 +@end example + +If the output is less than the @var{minwidth} parameter (default no +minimum), it's padded on the left with the @var{padchar} parameter +(default space). + +@example +(format #t "~5,'*d" 12) @print{} ***12 +(format #t "~5,'0d" 12) @print{} 00012 +(format #t "~3d" 1234) @print{} 1234 +@end example + +@nicode{~:d} adds commas (or the @var{commachar} parameter) every +three digits (or the @var{commawidth} parameter many). However, when +your intent is to write numbers in a way that follows typographical +conventions, using @nicode{~h} is recommended. + +@example +(format #t "~:d" 1234567) @print{} 1,234,567 +(format #t "~10,'*,'/,2:d" 12345) @print{} ***1/23/45 +@end example + +Hexadecimal @nicode{~x} output is in lower case, but the @nicode{~(} +and @nicode{~)} case conversion directives described below can be used +to get upper case. + +@example +(format #t "~x" 65261) @print{} feed +(format #t "~:@@(~x~)" 65261) @print{} FEED +@end example + +@item @nicode{~r} +Integer in words, roman numerals, or a specified radix. Parameters: +@var{radix}, @var{minwidth}, @var{padchar}, @var{commachar}, +@var{commawidth}. + +With no parameters output is in words as a cardinal like ``ten'', or +@nicode{~:r} prints an ordinal like ``tenth''. + +@example +(format #t "~r" 9) @print{} nine ;; cardinal +(format #t "~r" -9) @print{} minus nine ;; cardinal +(format #t "~:r" 9) @print{} ninth ;; ordinal +@end example + +And also with no parameters, @nicode{~@@r} gives roman numerals and +@nicode{~:@@r} gives old roman numerals. In old roman numerals +there's no ``subtraction'', so 9 is @nicode{VIIII} instead of +@nicode{IX}. In both cases only positive numbers can be output. + +@example +(format #t "~@@r" 89) @print{} LXXXIX ;; roman +(format #t "~:@@r" 89) @print{} LXXXVIIII ;; old roman +@end example + +When a parameter is given it means numeric output in the specified +@var{radix}. The modifiers and parameters following the radix are the +same as described for @nicode{~d} etc above. + +@example +(format #f "~3r" 27) @result{} "1000" ;; base 3 +(format #f "~3,5r" 26) @result{} " 222" ;; base 3 width 5 +@end example + +@item @nicode{~f} +Fixed-point float. Parameters: @var{width}, @var{decimals}, +@var{scale}, @var{overflowchar}, @var{padchar}. + +Output a number or number string in fixed-point format, ie.@: with a +decimal point. + +@example +(format #t "~f" 5) @print{} 5.0 +(format #t "~f" "123") @print{} 123.0 +(format #t "~f" "1e-1") @print{} 0.1 +@end example + +@nicode{~@@f} prints a @nicode{+} sign on positive numbers (including +zero). + +@example +(format #t "~@@f" 0) @print{} +0.0 +@end example + +If the output is less than @var{width} characters it's padded on the +left with @var{padchar} (space by default). If the output equals or +exceeds @var{width} then there's no padding. The default for +@var{width} is no padding. + +@example +(format #f "~6f" -1.5) @result{} " -1.5" +(format #f "~6,,,,'*f" 23) @result{} "**23.0" +(format #f "~6f" 1234567.0) @result{} "1234567.0" +@end example + +@var{decimals} is how many digits to print after the decimal point, +with the value rounded or padded with zeros as necessary. (The +default is to output as many decimals as required.) + +@example +(format #t "~1,2f" 3.125) @print{} 3.13 +(format #t "~1,2f" 1.5) @print{} 1.50 +@end example + +@var{scale} is a power of 10 applied to the value, moving the decimal +point that many places. A positive @var{scale} increases the value +shown, a negative decreases it. + +@example +(format #t "~,,2f" 1234) @print{} 123400.0 +(format #t "~,,-2f" 1234) @print{} 12.34 +@end example + +If @var{overflowchar} and @var{width} are both given and if the output +would exceed @var{width}, then that many @var{overflowchar}s are +printed instead of the value. + +@example +(format #t "~6,,,'xf" 12345) @print{} 12345. +(format #t "~5,,,'xf" 12345) @print{} xxxxx +@end example + +@item @nicode{~h} +Localized number@footnote{The @nicode{~h} format specifier first +appeared in Guile version 2.0.6.}. Parameters: @var{width}, +@var{decimals}, @var{padchar}. + +Like @nicode{~f}, output an exact or floating point number, but do so +according to the current locale, or according to the given locale object +when the @code{:} modifier is used (@pxref{Number Input and Output, +@code{number->locale-string}}). + +@example +(format #t "~h" 12345.5678) ; with "C" as the current locale +@print{} 12345.5678 + +(format #t "~14,,'*:h" 12345.5678 + (make-locale LC_ALL "en_US")) +@print{} ***12,345.5678 + +(format #t "~,2:h" 12345.5678 + (make-locale LC_NUMERIC "fr_FR")) +@print{} 12 345,56 +@end example + +@item @nicode{~e} +Exponential float. Parameters: @var{width}, @var{mantdigits}, +@var{expdigits}, @var{intdigits}, @var{overflowchar}, @var{padchar}, +@var{expchar}. + +Output a number or number string in exponential notation. + +@example +(format #t "~e" 5000.25) @print{} 5.00025E+3 +(format #t "~e" "123.4") @print{} 1.234E+2 +(format #t "~e" "1e4") @print{} 1.0E+4 +@end example + +@nicode{~@@e} prints a @nicode{+} sign on positive numbers (including +zero). (This is for the mantissa, a @nicode{+} or @nicode{-} sign is +always shown on the exponent.) + +@example +(format #t "~@@e" 5000.0) @print{} +5.0E+3 +@end example + +If the output is less than @var{width} characters it's padded on the +left with @var{padchar} (space by default). The default for +@var{width} is to output with no padding. + +@example +(format #f "~10e" 1234.0) @result{} " 1.234E+3" +(format #f "~10,,,,,'*e" 0.5) @result{} "****5.0E-1" +@end example + +@c FIXME: Describe what happens when the number is bigger than WIDTH. +@c There seems to be a bit of dodginess about this, or some deviation +@c from Common Lisp. + +@var{mantdigits} is the number of digits shown in the mantissa after +the decimal point. The value is rounded or trailing zeros are added +as necessary. The default @var{mantdigits} is to show as much as +needed by the value. + +@example +(format #f "~,3e" 11111.0) @result{} "1.111E+4" +(format #f "~,8e" 123.0) @result{} "1.23000000E+2" +@end example + +@var{expdigits} is the minimum number of digits shown for the +exponent, with leading zeros added if necessary. The default for +@var{expdigits} is to show only as many digits as required. At least +1 digit is always shown. + +@example +(format #f "~,,1e" 1.0e99) @result{} "1.0E+99" +(format #f "~,,6e" 1.0e99) @result{} "1.0E+000099" +@end example + +@var{intdigits} (default 1) is the number of digits to show before the +decimal point in the mantissa. @var{intdigits} can be zero, in which +case the integer part is a single @nicode{0}, or it can be negative, +in which case leading zeros are shown after the decimal point. + +@c FIXME: When INTDIGITS is 0, Common Lisp format apparently only +@c shows the single 0 digit if it fits in WIDTH. format.scm seems to +@c show it always. Is it meant to? + +@example +(format #t "~,,,3e" 12345.0) @print{} 123.45E+2 +(format #t "~,,,0e" 12345.0) @print{} 0.12345E+5 +(format #t "~,,,-3e" 12345.0) @print{} 0.00012345E+8 +@end example + +@c FIXME: MANTDIGITS with negative INTDIGITS doesn't match CL spec, +@c believe the spec says it ought to still show mantdigits+1 sig +@c figures, i.e. leading zeros don't count towards MANTDIGITS, but it +@c seems to just treat MANTDIGITS as how many digits after the +@c decimal point. + +If @var{overflowchar} is given then @var{width} is a hard limit. If +the output would exceed @var{width} then instead that many +@var{overflowchar}s are printed. + +@example +(format #f "~6,,,,'xe" 100.0) @result{} "1.0E+2" +(format #f "~3,,,,'xe" 100.0) @result{} "xxx" +@end example + +@var{expchar} is the exponent marker character (default @nicode{E}). + +@example +(format #t "~,,,,,,'ee" 100.0) @print{} 1.0e+2 +@end example + +@item @nicode{~g} +General float. Parameters: @var{width}, @var{mantdigits}, +@var{expdigits}, @var{intdigits}, @var{overflowchar}, @var{padchar}, +@var{expchar}. + +Output a number or number string in either exponential format the same +as @nicode{~e}, or fixed-point format like @nicode{~f} but aligned +where the mantissa would have been and followed by padding where the +exponent would have been. + +@c FIXME: The default MANTDIGITS is apparently max(needed,min(n,7)) +@c where 10^(n-1)<=abs(x)<=10^n. But the Common Lisp spec seems to +@c ask for "needed" to be without leading or trailing zeros, whereas +@c format.scm seems to include trailing zeros, ending up with it +@c using fixed format for bigger values than it should. + +Fixed-point is used when the absolute value is 0.1 or more and it +takes no more space than the mantissa in exponential format, ie.@: +basically up to @var{mantdigits} digits. + +@example +(format #f "~12,4,2g" 999.0) @result{} " 999.0 " +(format #f "~12,4,2g" "100000") @result{} " 1.0000E+05" +@end example + +The parameters are interpreted as per @nicode{~e} above. When +fixed-point is used, the @var{decimals} parameter to @nicode{~f} is +established from @var{mantdigits}, so as to give a total +@math{@var{mantdigits}+1} figures. + +@item @nicode{~$} +Monetary style fixed-point float. Parameters: @var{decimals}, +@var{intdigits}, @var{width}, @var{padchar}. + +@c For reference, fmtdoc.txi from past versions of slib showed the +@c INTDIGITS parameter as SCALE. That looks like a typo, in the code +@c and in the Common Lisp spec it's a minimum digits for the integer +@c part, it isn't a power of 10 like in ~f. + +Output a number or number string in fixed-point format, ie.@: with a +decimal point. @var{decimals} is the number of decimal places to +show, default 2. + +@example +(format #t "~$" 5) @print{} 5.00 +(format #t "~4$" "2.25") @print{} 2.2500 +(format #t "~4$" "1e-2") @print{} 0.0100 +@end example + +@nicode{~@@$} prints a @nicode{+} sign on positive numbers (including +zero). + +@example +(format #t "~@@$" 0) @print{} +0.00 +@end example + +@var{intdigits} is a minimum number of digits to show in the integer +part of the value (default 1). + +@example +(format #t "~,3$" 9.5) @print{} 009.50 +(format #t "~,0$" 0.125) @print{} .13 +@end example + +If the output is less than @var{width} characters (default 0), it's +padded on the left with @var{padchar} (default space). @nicode{~:$} +puts the padding after the sign. + +@example +(format #f "~,,8$" -1.5) @result{} " -1.50" +(format #f "~,,8:$" -1.5) @result{} "- 1.50" +(format #f "~,,8,'.:@@$" 3) @result{} "+...3.00" +@end example + +Note that floating point for dollar amounts is generally not a good +idea, because a cent @math{0.01} cannot be represented exactly in the +binary floating point Guile uses, which leads to slowly accumulating +rounding errors. Keeping values as cents (or fractions of a cent) in +integers then printing with the scale option in @nicode{~f} may be a +better approach. + +@c For reference, fractions don't work with ~$ (or any of the float +@c conversions) currently. If they did work then we could perhaps +@c suggest keeping dollar amounts as rationals, which would of course +@c give exact cents. An integer as cents is probably still a better +@c recommendation though, since it forces one to think about where +@c and when rounding can or should occur. + +@item @nicode{~i} +Complex fixed-point float. Parameters: @var{width}, @var{decimals}, +@var{scale}, @var{overflowchar}, @var{padchar}. + +@c For reference, in Common Lisp ~i is an indent, but slib fmtdoc.txi +@c described it as complex number output, so we keep that. + +Output the argument as a complex number, with both real and imaginary +part shown (even if one or both are zero). + +The parameters and modifiers are the same as for fixed-point +@nicode{~f} described above. The real and imaginary parts are both +output with the same given parameters and modifiers, except that for +the imaginary part the @nicode{@@} modifier is always enabled, so as +to print a @nicode{+} sign between the real and imaginary parts. + +@example +(format #t "~i" 1) @print{} 1.0+0.0i +@end example + +@item @nicode{~p} +Plural. No parameters. + +Output nothing if the argument is 1, or @samp{s} for any other +value. + +@example +(format #t "enter name~p" 1) @print{} enter name +(format #t "enter name~p" 2) @print{} enter names +@end example + +@nicode{~@@p} prints @samp{y} for 1 or @samp{ies} otherwise. + +@example +(format #t "pupp~@@p" 1) @print{} puppy +(format #t "pupp~@@p" 2) @print{} puppies +@end example + +@nicode{~:p} re-uses the preceding argument instead of taking a new +one, which can be convenient when printing some sort of count. + +@example +(format #t "~d cat~:p" 9) @print{} 9 cats +(format #t "~d pupp~:@@p" 5) @print{} 5 puppies +@end example + +@nicode{~p} is designed for English plurals and there's no attempt to +support other languages. @nicode{~[} conditionals (below) may be able +to help. When using @code{gettext} to translate messages +@code{ngettext} is probably best though +(@pxref{Internationalization}). + +@item @nicode{~y} +Structured printing. Parameters: @var{width}. + +@nicode{~y} outputs an argument using @code{pretty-print} +(@pxref{Pretty Printing}). The result will be formatted to fit within +@var{width} columns (79 by default), consuming multiple lines if +necessary. + +@nicode{~@@y} outputs an argument using @code{truncated-print} +(@pxref{Pretty Printing}). The resulting code will be formatted to fit +within @var{width} columns (79 by default), on a single line. The +output will be truncated if necessary. + +@nicode{~:@@y} is like @nicode{~@@y}, except the @var{width} parameter +is interpreted to be the maximum column to which to output. That is to +say, if you are at column 10, and @nicode{~60:@@y} is seen, the datum +will be truncated to 50 columns. + +@item @nicode{~?} +@itemx @nicode{~k} +Sub-format. No parameters. + +Take a format string argument and a second argument which is a list of +arguments for that string, and output the result. + +@example +(format #t "~?" "~d ~d" '(1 2)) @print{} 1 2 +@end example + +@nicode{~@@?} takes arguments for the sub-format directly rather than +in a list. + +@example +(format #t "~@@? ~s" "~d ~d" 1 2 "foo") @print{} 1 2 "foo" +@end example + +@nicode{~?} and @nicode{~k} are the same, @nicode{~k} is provided for +T-Scheme compatibility. + +@item @nicode{~*} +Argument jumping. Parameter: @var{N}. + +Move forward @var{N} arguments (default 1) in the argument list. +@nicode{~:*} moves backwards. (@var{N} cannot be negative.) + +@example +(format #f "~d ~2*~d" 1 2 3 4) @result{} "1 4" +(format #f "~d ~:*~d" 6) @result{} "6 6" +@end example + +@nicode{~@@*} moves to argument number @var{N}. The first argument is +number 0 (and that's the default for @var{N}). + +@example +(format #f "~d~d again ~@@*~d~d" 1 2) @result{} "12 again 12" +(format #f "~d~d~d ~1@@*~d~d" 1 2 3) @result{} "123 23" +@end example + +A @nicode{#} move to the end followed by a @nicode{:} modifier move +back can be used for an absolute position relative to the end of the +argument list, a reverse of what the @nicode{@@} modifier does. + +@example +(format #t "~#*~2:*~a" 'a 'b 'c 'd) @print{} c +@end example + +At the end of the format string the current argument position doesn't +matter, any further arguments are ignored. + +@item @nicode{~t} +Advance to a column position. Parameters: @var{colnum}, @var{colinc}, +@var{padchar}. + +Output @var{padchar} (space by default) to move to the given +@var{colnum} column. The start of the line is column 0, the default +for @var{colnum} is 1. + +@example +(format #f "~tX") @result{} " X" +(format #f "~3tX") @result{} " X" +@end example + +If the current column is already past @var{colnum}, then the move is +to there plus a multiple of @var{colinc}, ie.@: column +@math{@var{colnum} + @var{N} * @var{colinc}} for the smallest @var{N} +which makes that value greater than or equal to the current column. +The default @var{colinc} is 1 (which means no further move). + +@example +(format #f "abcd~2,5,'.tx") @result{} "abcd...x" +@end example + +@nicode{~@@t} takes @var{colnum} as an offset from the current column. +@var{colnum} many pad characters are output, then further padding to +make the current column a multiple of @var{colinc}, if it isn't +already so. + +@example +(format #f "a~3,5'*@@tx") @result{} "a****x" +@end example + +@nicode{~t} is implemented using @code{port-column} (@pxref{Textual +I/O}), so it works even there has been other output before +@code{format}. + +@item @nicode{~~} +Tilde character. Parameter: @var{n}. + +Output a tilde character @nicode{~}, or @var{n} many if a parameter is +given. Normally @nicode{~} introduces an escape sequence, @nicode{~~} +is the way to output a literal tilde. + +@item @nicode{~%} +Newline. Parameter: @var{n}. + +Output a newline character, or @var{n} many if a parameter is given. +A newline (or a few newlines) can of course be output just by +including them in the format string. + +@item @nicode{~&} +Start a new line. Parameter: @var{n}. + +Output a newline if not already at the start of a line. With a +parameter, output that many newlines, but with the first only if not +already at the start of a line. So for instance 3 would be a newline +if not already at the start of a line, and 2 further newlines. + +@item @nicode{~_} +Space character. Parameter: @var{n}. + +@c For reference, in Common Lisp ~_ is a conditional newline, but +@c slib fmtdoc.txi described it as a space, so we keep that. + +Output a space character, or @var{n} many if a parameter is given. + +With a variable parameter this is one way to insert runtime calculated +padding (@nicode{~t} or the various field widths can do similar +things). + +@example +(format #f "~v_foo" 4) @result{} " foo" +@end example + +@item @nicode{~/} +Tab character. Parameter: @var{n}. + +Output a tab character, or @var{n} many if a parameter is given. + +@item @nicode{~|} +Formfeed character. Parameter: @var{n}. + +Output a formfeed character, or @var{n} many if a parameter is given. + +@item @nicode{~!} +Force output. No parameters. + +At the end of output, call @code{force-output} to flush any buffers on +the destination (@pxref{Buffering}). @nicode{~!} can occur anywhere in +the format string, but the force is done at the end of output. + +When output is to a string (destination @code{#f}), @nicode{~!} does +nothing. + +@item @nicode{~newline} (ie.@: newline character) +Continuation line. No parameters. + +Skip this newline and any following whitespace in the format string, +ie.@: don't send it to the output. This can be used to break up a +long format string for readability, but not print the extra +whitespace. + +@example +(format #f "abc~ + ~d def~ + ~d" 1 2) @result{} "abc1 def2" +@end example + +@nicode{~:newline} skips the newline but leaves any further whitespace +to be printed normally. + +@nicode{~@@newline} prints the newline then skips following +whitespace. + +@item @nicode{~(} @nicode{~)} +Case conversion. No parameters. + +Between @nicode{~(} and @nicode{~)} the case of all output is changed. +The modifiers on @nicode{~(} control the conversion. + +@itemize @w{} +@item +@nicode{~(} --- lower case. +@c +@c FIXME: The : and @ modifiers are not yet documented because the +@c code applies string-capitalize and string-capitalize-first to each +@c separate format:out-str call, which has various subtly doubtful +@c effects. And worse they're applied to individual characters, +@c including literal characters in the format string, which has the +@c silly effect of being always an upcase. +@c +@c The Common Lisp spec is apparently for the capitalization to be +@c applied in one hit to the whole of the output between ~( and ~). +@c (This can no doubt be implemented without accumulating all that +@c text, just by keeping a state or the previous char to tell whether +@c within a word.) +@c +@c @item +@c @nicode{:} --- first letter of each word upper case, the rest lower +@c case, as per the @code{string-capitalize} function (@pxref{Alphabetic +@c Case Mapping}). +@c @item +@c @nicode{@@} --- first letter of just the first word upper case, the +@c rest lower case. +@c +@item +@nicode{~:@@(} --- upper case. +@end itemize + +For example, + +@example +(format #t "~(Hello~)") @print{} hello +(format #t "~:@@(Hello~)") @print{} HELLO +@end example + +In the future it's intended the modifiers @nicode{:} and @nicode{@@} +alone will capitalize the first letters of words, as per Common Lisp +@code{format}, but the current implementation of this is flawed and +not recommended for use. + +Case conversions do not nest, currently. This might change in the +future, but if it does then it will be to Common Lisp style where the +outermost conversion has priority, overriding inner ones (making those +fairly pointless). + +@item @nicode{~@{} @nicode{~@}} +Iteration. Parameter: @var{maxreps} (for @nicode{~@{}). + +The format between @nicode{~@{} and @nicode{~@}} is iterated. The +modifiers to @nicode{~@{} determine how arguments are taken. The +default is a list argument with each iteration successively consuming +elements from it. This is a convenient way to output a whole list. + +@example +(format #t "~@{~d~@}" '(1 2 3)) @print{} 123 +(format #t "~@{~s=~d ~@}" '("x" 1 "y" 2)) @print{} "x"=1 "y"=2 +@end example + +@nicode{~:@{} takes a single argument which is a list of lists, each +of those contained lists gives the arguments for the iterated format. + +@c @print{} on a new line here to avoid overflowing page width in DVI +@example +(format #t "~:@{~dx~d ~@}" '((1 2) (3 4) (5 6))) +@print{} 1x2 3x4 5x6 +@end example + +@nicode{~@@@{} takes arguments directly, with each iteration +successively consuming arguments. + +@example +(format #t "~@@@{~d~@}" 1 2 3) @print{} 123 +(format #t "~@@@{~s=~d ~@}" "x" 1 "y" 2) @print{} "x"=1 "y"=2 +@end example + +@nicode{~:@@@{} takes list arguments, one argument for each iteration, +using that list for the format. + +@c @print{} on a new line here to avoid overflowing page width in DVI +@example +(format #t "~:@@@{~dx~d ~@}" '(1 2) '(3 4) '(5 6)) +@print{} 1x2 3x4 5x6 +@end example + +Iterating stops when there are no more arguments or when the +@var{maxreps} parameter to @nicode{~@{} is reached (default no +maximum). + +@example +(format #t "~2@{~d~@}" '(1 2 3 4)) @print{} 12 +@end example + +If the format between @nicode{~@{} and @nicode{~@}} is empty, then a +format string argument is taken (before iteration argument(s)) and +used instead. This allows a sub-format (like @nicode{~?} above) to be +iterated. + +@example +(format #t "~@{~@}" "~d" '(1 2 3)) @print{} 123 +@end example + +@c FIXME: What is the @nicode{:} modifier to ~} meant to do? The +@c Common Lisp spec says it's a minimum of 1 iteration, but the +@c format.scm code seems to merely make it have MAXREPS default to 1. + +Iterations can be nested, an inner iteration operates in the same way +as described, but of course on the arguments the outer iteration +provides it. This can be used to work into nested list structures. +For example in the following the inner @nicode{~@{~d~@}x} is applied +to @code{(1 2)} then @code{(3 4 5)} etc. + +@example +(format #t "~@{~@{~d~@}x~@}" '((1 2) (3 4 5))) @print{} 12x345x +@end example + +See also @nicode{~^} below for escaping from iteration. + +@item @nicode{~[} @nicode{~;} @nicode{~]} +Conditional. Parameter: @var{selector}. + +A conditional block is delimited by @nicode{~[} and @nicode{~]}, and +@nicode{~;} separates clauses within the block. @nicode{~[} takes an +integer argument and that number clause is used. The first clause is +number 0. + +@example +(format #f "~[peach~;banana~;mango~]" 1) @result{} "banana" +@end example + +The @var{selector} parameter can be used for the clause number, +instead of taking an argument. + +@example +(format #f "~2[peach~;banana~;mango~]") @result{} "mango" +@end example + +If the clause number is out of range then nothing is output. Or the +last clause can be @nicode{~:;} to use that for a number out of range. + +@example +(format #f "~[banana~;mango~]" 99) @result{} "" +(format #f "~[banana~;mango~:;fruit~]" 99) @result{} "fruit" +@end example + +@nicode{~:[} treats the argument as a flag, and expects two clauses. +The first is used if the argument is @code{#f} or the second +otherwise. + +@example +(format #f "~:[false~;not false~]" #f) @result{} "false" +(format #f "~:[false~;not false~]" 'abc) @result{} "not false" + +(let ((n 3)) + (format #t "~d gnu~:[s are~; is~] here" n (= 1 n))) +@print{} 3 gnus are here +@end example + +@nicode{~@@[} also treats the argument as a flag, and expects one +clause. If the argument is @code{#f} then no output is produced and +the argument is consumed, otherwise the clause is used and the +argument is not consumed, it's left for the clause. This can be used +for instance to suppress output if @code{#f} means something not +available. + +@example +(format #f "~@@[temperature=~d~]" 27) @result{} "temperature=27" +(format #f "~@@[temperature=~d~]" #f) @result{} "" +@end example + +@item @nicode{~^} +Escape. Parameters: @var{val1}, @var{val2}, @var{val3}. + +Stop formatting if there are no more arguments. This can be used for +instance to have a format string adapt to a variable number of +arguments. + +@example +(format #t "~d~^ ~d" 1) @print{} 1 +(format #t "~d~^ ~d" 1 2) @print{} 1 2 +@end example + +Within a @nicode{~@{} @nicode{~@}} iteration, @nicode{~^} stops the +current iteration step if there are no more arguments to that step, +but continuing with possible further steps and the rest of the format. +This can be used for instance to avoid a separator on the last +iteration, or to adapt to variable length argument lists. + +@example +(format #f "~@{~d~^/~@} go" '(1 2 3)) @result{} "1/2/3 go" +(format #f "~:@{ ~d~^~d~@} go" '((1) (2 3))) @result{} " 1 23 go" +@end example + +@c For reference, format.scm doesn't implement that Common Lisp ~:^ +@c modifier which stops the entire iterating of ~:{ or ~@:{. + +@c FIXME: Believe the Common Lisp spec is for ~^ within ~[ ~] +@c conditional to terminate the whole format (or iteration step if in +@c an iteration). But format.scm seems to terminate just the +@c conditional form. +@c +@c (format #f "~[abc~^def~;ghi~] blah" 0) +@c @result{} "abc blah" ;; looks wrong + +@c FIXME: Believe the Common Lisp spec is for ~^ within ~( ~) to end +@c that case conversion and then also terminate the whole format (or +@c iteration step if in an iteration). But format.scm doesn't seem +@c to do that quite right. +@c +@c (format #f "~d ~^ ~d" 1) @result{} "1 " +@c (format #f "~(~d ~^ ~d~)" 1) @result{} ERROR + +Within a @nicode{~?} sub-format, @nicode{~^} operates just on that +sub-format. If it terminates the sub-format then the originating +format will still continue. + +@example +(format #t "~? items" "~d~^ ~d" '(1)) @print{} 1 items +(format #t "~? items" "~d~^ ~d" '(1 2)) @print{} 1 2 items +@end example + +The parameters to @nicode{~^} (which are numbers) change the condition +used to terminate. For a single parameter, termination is when that +value is zero (notice this makes plain @nicode{~^} equivalent to +@nicode{~#^}). For two parameters, termination is when those two are +equal. For three parameters, termination is when @math{@var{val1} +@le{} @var{val2}} and @math{@var{val2} @le{} @var{val3}}. + +@c FIXME: Good examples of these? + +@item @nicode{~q} +Inquiry message. Insert a copyright message into the output. + +@nicode{~:q} inserts the format implementation version. +@end table + +@sp 1 +It's an error if there are not enough arguments for the escapes in the +format string, but any excess arguments are ignored. + +Iterations @nicode{~@{} @nicode{~@}} and conditionals @nicode{~[} +@nicode{~;} @nicode{~]} can be nested, but must be properly nested, +meaning the inner form must be entirely within the outer form. So +it's not possible, for instance, to try to conditionalize the endpoint +of an iteration. + +@example +(format #t "~@{ ~[ ... ~] ~@}" ...) ;; good +(format #t "~@{ ~[ ... ~@} ... ~]" ...) ;; bad +@end example + +The same applies to case conversions @nicode{~(} @nicode{~)}, they +must properly nest with respect to iterations and conditionals (though +currently a case conversion cannot nest within another case +conversion). + +When a sub-format (@nicode{~?}) is used, that sub-format string must +be self-contained. It cannot for instance give a @nicode{~@{} to +begin an iteration form and have the @nicode{~@}} up in the +originating format, or similar. +@end deffn + +@sp 1 +Guile contains a @code{format} procedure even when the module +@code{(ice-9 format)} is not loaded. The default @code{format} is +@code{simple-format} (@pxref{Simple Output}), it doesn't support all +escape sequences documented in this section, and will signal an error if +you try to use one of them. The reason for two versions is that the +full @code{format} is fairly large and requires some time to load. +@code{simple-format} is often adequate too. + + +@node File Tree Walk +@section File Tree Walk +@cindex file tree walk + +@cindex file system traversal +@cindex directory traversal + +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 @code{ftw} +and @code{nftw} routines (@pxref{Working with Directory Trees,,, libc, +GNU C Library Reference Manual}). + +@example +(use-modules (ice-9 ftw)) +@end example +@sp 1 + +@deffn {Scheme Procedure} file-system-tree file-name [enter? [stat]] +Return a tree of the form @code{(@var{file-name} @var{stat} +@var{children} ...)} where @var{stat} is the result of @code{(@var{stat} +@var{file-name})} and @var{children} are similar structures for each +file contained in @var{file-name} when it designates a directory. + +The optional @var{enter?} predicate is invoked as @code{(@var{enter?} +@var{name} @var{stat})} and should return true to allow recursion into +directory @var{name}; the default value is a procedure that always +returns @code{#t}. When a directory does not match @var{enter?}, it +nonetheless appears in the resulting tree, only with zero children. + +The @var{stat} argument is optional and defaults to @code{lstat}, as for +@code{file-system-fold} (see below.) + +The example below shows how to obtain a hierarchical listing of the +files under the @file{module/language} directory in the Guile source +tree, discarding their @code{stat} info: + +@example +(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))) + +@result{} +("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" + @dots{})) + @dots{})) +@end example +@end deffn + +@cindex file system combinator + +It is often desirable to process directories entries directly, rather +than building up a tree of entries in memory, like +@code{file-system-tree} does. The following procedure, a +@dfn{combinator}, is designed to allow directory entries to be processed +directly as a directory tree is traversed; in fact, +@code{file-system-tree} is implemented in terms of it. + +@deffn {Scheme Procedure} file-system-fold enter? leaf down up skip error init file-name [stat] +Traverse the directory at @var{file-name}, recursively, and return the +result of the successive applications of the @var{leaf}, @var{down}, +@var{up}, and @var{skip} procedures as described below. + +Enter sub-directories only when @code{(@var{enter?} @var{path} +@var{stat} @var{result})} returns true. When a sub-directory is +entered, call @code{(@var{down} @var{path} @var{stat} @var{result})}, +where @var{path} is the path of the sub-directory and @var{stat} the +result of @code{(false-if-exception (@var{stat} @var{path}))}; when it is +left, call @code{(@var{up} @var{path} @var{stat} @var{result})}. + +For each file in a directory, call @code{(@var{leaf} @var{path} +@var{stat} @var{result})}. + +When @var{enter?} returns @code{#f}, or when an unreadable directory is +encountered, call @code{(@var{skip} @var{path} @var{stat} +@var{result})}. + +When @var{file-name} names a flat file, @code{(@var{leaf} @var{path} +@var{stat} @var{init})} is returned. + +When an @code{opendir} or @var{stat} call fails, call @code{(@var{error} +@var{path} @var{stat} @var{errno} @var{result})}, with @var{errno} being +the operating system error number that was raised---e.g., +@code{EACCES}---and @var{stat} either @code{#f} or the result of the +@var{stat} call for that entry, when available. + +The special @file{.} and @file{..} entries are not passed to these +procedures. The @var{path} argument to the procedures is a full file +name---e.g., @code{"../foo/bar/gnu"}; if @var{file-name} is an absolute +file name, then @var{path} is also an absolute file name. Files and +directories, as identified by their device/inode number pair, are +traversed only once. + +The optional @var{stat} argument defaults to @code{lstat}, which means +that symbolic links are not followed; the @code{stat} procedure can be +used instead when symbolic links are to be followed (@pxref{File System, +stat}). + +The example below illustrates the use of @code{file-system-fold}: + +@example +(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 ".") +@result{} 8217554 + +(total-file-size "/dev/null") +@result{} 0 +@end example +@end deffn + +The alternative C-like functions are described below. + +@deffn {Scheme Procedure} scandir name [select? [entry<?]] +Return the list of the names of files contained in directory @var{name} +that match predicate @var{select?} (by default, all files). The +returned list of file names is sorted according to @var{entry<?}, which +defaults to @code{string-locale<?} such that file names are sorted in +the locale's alphabetical order (@pxref{Text Collation}). Return +@code{#f} when @var{name} is unreadable or is not a directory. + +This procedure is modeled after the C library function of the same name +(@pxref{Scanning Directory Content,,, libc, GNU C Library Reference +Manual}). +@end deffn + +@deffn {Scheme Procedure} ftw startname proc ['hash-size n] +Walk the file system tree descending from @var{startname}, calling +@var{proc} for each file and directory. + +Hard links and symbolic links are followed. A file or directory is +reported to @var{proc} only once, and skipped if seen again in another +place. One consequence of this is that @code{ftw} is safe against +circularly linked directory structures. + +Each @var{proc} call is @code{(@var{proc} filename statinfo flag)} and +it should return @code{#t} to continue, or any other value to stop. + +@var{filename} is the item visited, being @var{startname} plus a +further path and the name of the item. @var{statinfo} is the return +from @code{stat} (@pxref{File System}) on @var{filename}. @var{flag} +is one of the following symbols, + +@table @code +@item regular +@var{filename} is a file, this includes special files like devices, +named pipes, etc. + +@item directory +@var{filename} is a directory. + +@item invalid-stat +An error occurred when calling @code{stat}, so nothing is known. +@var{statinfo} is @code{#f} in this case. + +@item directory-not-readable +@var{filename} is a directory, but one which cannot be read and hence +won't be recursed into. + +@item symlink +@var{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. +@end table + +The return value from @code{ftw} is @code{#t} if it ran to completion, +or otherwise the non-@code{#t} value from @var{proc} which caused the +stop. + +Optional argument symbol @code{hash-size} and an integer can be given +to set the size of the hash table used to track items already visited. +(@pxref{Hash Table Reference}) + +@c Actually, it's probably safe to escape from ftw, just need to +@c check it. +@c +In the current implementation, returning non-@code{#t} from @var{proc} +is the only valid way to terminate @code{ftw}. @var{proc} must not +use @code{throw} or similar to escape. +@end deffn + + +@deffn {Scheme Procedure} nftw startname proc ['chdir] ['depth] ['hash-size n] ['mount] ['physical] +Walk the file system tree starting at @var{startname}, calling +@var{proc} for each file and directory. @code{nftw} has extra +features over the basic @code{ftw} described above. + +Like @code{ftw}, hard links and symbolic links are followed. A file +or directory is reported to @var{proc} only once, and skipped if seen +again in another place. One consequence of this is that @code{nftw} +is safe against circular linked directory structures. + +Each @var{proc} call is @code{(@var{proc} filename statinfo flag +base level)} and it should return @code{#t} to continue, or any +other value to stop. + +@var{filename} is the item visited, being @var{startname} plus a +further path and the name of the item. @var{statinfo} is the return +from @code{stat} on @var{filename} (@pxref{File System}). @var{base} +is an integer offset into @var{filename} which is where the basename +for this item begins. @var{level} is an integer giving the directory +nesting level, starting from 0 for the contents of @var{startname} (or +that item itself if it's a file). @var{flag} is one of the following +symbols, + +@table @code +@item regular +@var{filename} is a file, including special files like devices, named +pipes, etc. + +@item directory +@var{filename} is a directory. + +@item directory-processed +@var{filename} is a directory, and its contents have all been visited. +This flag is given instead of @code{directory} when the @code{depth} +option below is used. + +@item invalid-stat +An error occurred when applying @code{stat} to @var{filename}, so +nothing is known about it. @var{statinfo} is @code{#f} in this case. + +@item directory-not-readable +@var{filename} is a directory, but one which cannot be read and hence +won't be recursed into. + +@item stale-symlink +@var{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. + +@item symlink +When the @code{physical} option described below is used, this +indicates @var{filename} is a symbolic link whose target exists (and +is not being followed). +@end table + +The following optional arguments can be given to modify the way +@code{nftw} works. Each is passed as a symbol (and @code{hash-size} +takes a following integer value). + +@table @asis +@item @code{chdir} +Change to the directory containing the item before calling @var{proc}. +When @code{nftw} returns the original current directory is restored. + +Under this option, generally the @var{base} parameter to each +@var{proc} call should be used to pick out the base part of the +@var{filename}. The @var{filename} is still a path but with a changed +directory it won't be valid (unless the @var{startname} directory was +absolute). + +@item @code{depth} +Visit files ``depth first'', meaning @var{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 @var{flag} to @var{proc} for a directory is +@code{directory-processed} instead of @code{directory}. + +@item @code{hash-size @var{n}} +Set the size of the hash table used to track items already visited. +(@pxref{Hash Table Reference}) + +@item @code{mount} +Don't cross a mount point, meaning only visit items on the same +file system as @var{startname} (ie.@: the same @code{stat:dev}). + +@item @code{physical} +Don't follow symbolic links, instead report them to @var{proc} as +@code{symlink}. Dangling links (those whose target doesn't exist) are +still reported as @code{stale-symlink}. +@end table + +The return value from @code{nftw} is @code{#t} if it ran to +completion, or otherwise the non-@code{#t} value from @var{proc} which +caused the stop. + +@c For reference, one reason not to escape is that the current +@c directory is not saved and restored with dynamic-wind. Maybe +@c changing that would be enough to allow escaping. +@c +In the current implementation, returning non-@code{#t} from @var{proc} +is the only valid way to terminate @code{ftw}. @var{proc} must not +use @code{throw} or similar to escape. +@end deffn + + +@node Queues +@section Queues +@cindex queues +@tindex Queues + +@noindent +The functions in this section are provided by + +@example +(use-modules (ice-9 q)) +@end example + +This module implements queues holding arbitrary scheme objects and +designed for efficient first-in / first-out operations. + +@code{make-q} creates a queue, and objects are entered and removed +with @code{enq!} and @code{deq!}. @code{q-push!} and @code{q-pop!} +can be used too, treating the front of the queue like a stack. + +@sp 1 + +@deffn {Scheme Procedure} make-q +Return a new queue. +@end deffn + +@deffn {Scheme Procedure} q? obj +Return @code{#t} if @var{obj} is a queue, or @code{#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 @code{#t} from @code{q?}. +@end deffn + +@deffn {Scheme Procedure} enq! q obj +Add @var{obj} to the rear of @var{q}, and return @var{q}. +@end deffn + +@deffn {Scheme Procedure} deq! q +@deffnx {Scheme Procedure} q-pop! q +Remove and return the front element from @var{q}. If @var{q} is +empty, a @code{q-empty} exception is thrown. + +@code{deq!} and @code{q-pop!} are the same operation, the two names +just let an application match @code{enq!} with @code{deq!}, or +@code{q-push!} with @code{q-pop!}. +@end deffn + +@deffn {Scheme Procedure} q-push! q obj +Add @var{obj} to the front of @var{q}, and return @var{q}. +@end deffn + +@deffn {Scheme Procedure} q-length q +Return the number of elements in @var{q}. +@end deffn + +@deffn {Scheme Procedure} q-empty? q +Return true if @var{q} is empty. +@end deffn + +@deffn {Scheme Procedure} q-empty-check q +Throw a @code{q-empty} exception if @var{q} is empty. +@end deffn + +@deffn {Scheme Procedure} q-front q +Return the first element of @var{q} (without removing it). If @var{q} +is empty, a @code{q-empty} exception is thrown. +@end deffn + +@deffn {Scheme Procedure} q-rear q +Return the last element of @var{q} (without removing it). If @var{q} +is empty, a @code{q-empty} exception is thrown. +@end deffn + +@deffn {Scheme Procedure} q-remove! q obj +Remove all occurrences of @var{obj} from @var{q}, and return @var{q}. +@var{obj} is compared to queue elements using @code{eq?}. +@end deffn + +@sp 1 +@cindex @code{q-empty} +The @code{q-empty} exceptions described above are thrown just as +@code{(throw 'q-empty)}, there's no message etc like an error throw. + +A queue is implemented as a cons cell, the @code{car} containing a +list of queued elements, and the @code{cdr} being the last cell in +that list (for ease of enqueuing). + +@example +(@var{list} . @var{last-cell}) +@end example + +@noindent +If the queue is empty, @var{list} is the empty list and +@var{last-cell} is @code{#f}. + +An application can directly access the queue list if desired, for +instance to search the elements or to insert at a specific point. + +@deffn {Scheme Procedure} sync-q! q +Recompute the @var{last-cell} field in @var{q}. + +All the operations above maintain @var{last-cell} as described, so +normally there's no need for @code{sync-q!}. But if an application +modifies the queue @var{list} then it must either maintain +@var{last-cell} similarly, or call @code{sync-q!} to recompute it. +@end deffn + + +@node Streams +@section Streams +@cindex streams + +This section documents Guile's legacy stream module. For a more +complete and portable stream library, @pxref{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 + +@example +(use-modules (ice-9 streams)) +@end example + +Streams are implemented using promises (@pxref{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. + +@noindent +Here is a simple example producing a stream of all odd numbers, + +@example +(define odds (make-stream (lambda (state) + (cons state (+ state 2))) + 1)) +(stream-car odds) @result{} 1 +(stream-car (stream-cdr odds)) @result{} 3 +@end example + +@noindent +@code{stream-map} could be used to derive a stream of odd squares, + +@example +(define (square n) (* n n)) +(define oddsquares (stream-map square odds)) +@end example + +These are infinite sequences, so it's not possible to convert them to +a list, but they could be printed (infinitely) with for example + +@example +(stream-for-each (lambda (n sq) + (format #t "~a squared is ~a\n" n sq)) + odds oddsquares) +@print{} +1 squared is 1 +3 squared is 9 +5 squared is 25 +7 squared is 49 +@dots{} +@end example + +@sp 1 +@deffn {Scheme Procedure} make-stream proc initial-state +Return a new stream, formed by calling @var{proc} successively. + +Each call is @code{(@var{proc} @var{state})}, it should return a pair, +the @code{car} being the value for the stream, and the @code{cdr} +being the new @var{state} for the next call. For the first call +@var{state} is the given @var{initial-state}. At the end of the +stream, @var{proc} should return some non-pair object. +@end deffn + +@deffn {Scheme Procedure} stream-car stream +Return the first element from @var{stream}. @var{stream} must not be +empty. +@end deffn + +@deffn {Scheme Procedure} stream-cdr stream +Return a stream which is the second and subsequent elements of +@var{stream}. @var{stream} must not be empty. +@end deffn + +@deffn {Scheme Procedure} stream-null? stream +Return true if @var{stream} is empty. +@end deffn + +@deffn {Scheme Procedure} list->stream list +@deffnx {Scheme Procedure} vector->stream vector +Return a stream with the contents of @var{list} or @var{vector}. + +@var{list} or @var{vector} should not be modified subsequently, since +it's unspecified whether changes there will be reflected in the stream +returned. +@end deffn + +@deffn {Scheme Procedure} port->stream port readproc +Return a stream which is the values obtained by reading from @var{port} +using @var{readproc}. Each read call is @code{(@var{readproc} +@var{port})}, and it should return an EOF object (@pxref{Binary I/O}) at +the end of input. + +For example a stream of characters from a file, + +@example +(port->stream (open-input-file "/foo/bar.txt") read-char) +@end example +@end deffn + +@deffn {Scheme Procedure} stream->list stream +Return a list which is the entire contents of @var{stream}. +@end deffn + +@deffn {Scheme Procedure} stream->reversed-list stream +Return a list which is the entire contents of @var{stream}, but in +reverse order. +@end deffn + +@deffn {Scheme Procedure} stream->list&length stream +Return two values (@pxref{Multiple Values}), being firstly a list +which is the entire contents of @var{stream}, and secondly the number +of elements in that list. +@end deffn + +@deffn {Scheme Procedure} stream->reversed-list&length stream +Return two values (@pxref{Multiple Values}) being firstly a list which +is the entire contents of @var{stream}, but in reverse order, and +secondly the number of elements in that list. +@end deffn + +@deffn {Scheme Procedure} stream->vector stream +Return a vector which is the entire contents of @var{stream}. +@end deffn + +@defun stream-fold proc init stream1 stream2 @dots{} +Apply @var{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 @var{proc} call. + +Each call is @code{(@var{proc} elem1 elem2 @dots{} prev)}, where each +@var{elem} is from the corresponding @var{stream}. @var{prev} is the +return from the previous @var{proc} call, or the given @var{init} for +the first call. +@end defun + +@defun stream-for-each proc stream1 stream2 @dots{} +Call @var{proc} on the elements from the given @var{stream}s. The +return value is unspecified. + +Each call is @code{(@var{proc} elem1 elem2 @dots{})}, where each +@var{elem} is from the corresponding @var{stream}. +@code{stream-for-each} stops when it reaches the end of the shortest +@var{stream}. +@end defun + +@defun stream-map proc stream1 stream2 @dots{} +Return a new stream which is the results of applying @var{proc} to the +elements of the given @var{stream}s. + +Each call is @code{(@var{proc} elem1 elem2 @dots{})}, where each +@var{elem} is from the corresponding @var{stream}. The new stream +ends when the end of the shortest given @var{stream} is reached. +@end defun + + +@node Buffered Input +@section Buffered Input +@cindex Buffered input +@cindex Line continuation + +The following functions are provided by + +@example +(use-modules (ice-9 buffered-input)) +@end example + +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. + +@deffn {Scheme Procedure} make-buffered-input-port reader +Create an input port which returns characters obtained from the given +@var{reader} function. @var{reader} is called (@var{reader} cont), +and should return a string or an EOF object. + +The new port gives precisely the characters returned by @var{reader}, +nothing is added, so if any newline characters or other separators are +desired they must come from the reader function. + +The @var{cont} parameter to @var{reader} is @code{#f} for initial +input, or @code{#t} when continuing an expression. This is an +application level notion, set with +@code{set-buffered-input-continuation?!} below. If the user has +entered a partial expression then it allows @var{reader} for instance +to give a different prompt to show more is required. +@end deffn + +@deffn {Scheme Procedure} make-line-buffered-input-port reader +@cindex Line buffered input +Create an input port which returns characters obtained from the +specified @var{reader} function, similar to +@code{make-buffered-input-port} above, but where @var{reader} is +expected to be a line-oriented. + +@var{reader} is called (@var{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. +@end deffn + +@deffn {Scheme Procedure} set-buffered-input-continuation?! port cont +Set the input continuation flag for a given buffered input +@var{port}. + +An application uses this by calling with a @var{cont} flag of +@code{#f} when beginning to read a new logical expression. For +example with the Scheme @code{read} function (@pxref{Scheme Read}), + +@example +(define my-port (make-buffered-input-port my-reader)) + +(set-buffered-input-continuation?! my-port #f) +(let ((obj (read my-port))) + ... +@end example +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/mod-getopt-long.texi b/doc/ref/mod-getopt-long.texi new file mode 100644 index 000000000..cf043418f --- /dev/null +++ b/doc/ref/mod-getopt-long.texi @@ -0,0 +1,367 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node getopt-long +@section The (ice-9 getopt-long) Module + +The @code{(ice-9 getopt-long)} facility is designed to help parse +arguments that are passed to Guile programs on the command line, and is +modelled after the C library's facility of the same name +(@pxref{Getopt,,,libc,The GNU C Library Reference Manual}). For a more +low-level interface to command-line argument parsing, @xref{SRFI-37}. + +The @code{(ice-9 getopt-long)} module exports two procedures: +@code{getopt-long} and @code{option-ref}. + +@itemize @bullet +@item +@code{getopt-long} takes a list of strings --- the command line +arguments --- an @dfn{option specification}, and some optional keyword +parameters. It parses the command line arguments according to the +option specification and keyword parameters, and returns a data +structure that encapsulates the results of the parsing. + +@item +@code{option-ref} then takes the parsed data structure and a specific +option's name, and returns information about that option in particular. +@end itemize + +To make these procedures available to your Guile script, include the +expression @code{(use-modules (ice-9 getopt-long))} somewhere near the +top, before the first usage of @code{getopt-long} or @code{option-ref}. + +@menu +* getopt-long Example:: A short getopt-long example. +* Option Specification:: How to write an option specification. +* Command Line Format:: The expected command line format. +* getopt-long Reference:: Full documentation for @code{getopt-long}. +* option-ref Reference:: Full documentation for @code{option-ref}. +@end menu + + +@node getopt-long Example +@subsection A Short getopt-long Example + +This section illustrates how @code{getopt-long} is used by presenting +and dissecting a simple example. The first thing that we need is an +@dfn{option specification} that tells @code{getopt-long} how to parse +the command line. This specification is an association list with the +long option name as the key. Here is how such a specification might +look: + +@lisp +(define option-spec + '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) +@end lisp + +This alist tells @code{getopt-long} that it should accept two long +options, called @emph{version} and @emph{help}, and that these options +can also be selected by the single-letter abbreviations @emph{v} and +@emph{h}, respectively. The @code{(value #f)} clauses indicate that +neither of the options accepts a value. + +With this specification we can use @code{getopt-long} to parse a given +command line: + +@lisp +(define options (getopt-long (command-line) option-spec)) +@end lisp + +After this call, @code{options} contains the parsed command line and is +ready to be examined by @code{option-ref}. @code{option-ref} is called +like this: + +@lisp +(option-ref options 'help #f) +@end lisp + +@noindent +It expects the parsed command line, a symbol indicating the option to +examine, and a default value. The default value is returned if the +option was not present in the command line, or if the option was present +but without a value; otherwise the value from the command line is +returned. Usually @code{option-ref} is called once for each possible +option that a script supports. + +The following example shows a main program which puts all this together +to parse its command line and figure out what the user wanted. + +@lisp +(define (main args) + (let* ((option-spec '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args option-spec)) + (help-wanted (option-ref options 'help #f)) + (version-wanted (option-ref options 'version #f))) + (if (or version-wanted help-wanted) + (begin + (if version-wanted + (display "getopt-long-example version 0.3\n")) + (if help-wanted + (display "\ +getopt-long-example [options] + -v, --version Display version + -h, --help Display this help +"))) + (begin + (display "Hello, World!") (newline))))) +@end lisp + + +@node Option Specification +@subsection How to Write an Option Specification + +An option specification is an association list (@pxref{Association +Lists}) with one list element for each supported option. The key of each +list element is a symbol that names the option, while the value is a +list of option properties: + +@lisp +OPTION-SPEC ::= '( (OPT-NAME1 (PROP-NAME PROP-VALUE) @dots{}) + (OPT-NAME2 (PROP-NAME PROP-VALUE) @dots{}) + (OPT-NAME3 (PROP-NAME PROP-VALUE) @dots{}) + @dots{} + ) +@end lisp + +Each @var{opt-name} specifies the long option name for that option. For +example, a list element with @var{opt-name} @code{background} specifies +an option that can be specified on the command line using the long +option @code{--background}. Further information about the option --- +whether it takes a value, whether it is required to be present in the +command line, and so on --- is specified by the option properties. + +In the example of the preceding section, we already saw that a long +option name can have a equivalent @dfn{short option} character. The +equivalent short option character can be set for an option by specifying +a @code{single-char} property in that option's property list. For +example, a list element like @code{'(output (single-char #\o) @dots{})} +specifies an option with long name @code{--output} that can also be +specified by the equivalent short name @code{-o}. + +The @code{value} property specifies whether an option requires or +accepts a value. If the @code{value} property is set to @code{#t}, the +option requires a value: @code{getopt-long} will signal an error if the +option name is present without a corresponding value. If set to +@code{#f}, the option does not take a value; in this case, a non-option +word that follows the option name in the command line will be treated as +a non-option argument. If set to the symbol @code{optional}, the option +accepts a value but does not require one: a non-option word that follows +the option name in the command line will be interpreted as that option's +value. If the option name for an option with @code{'(value optional)} +is immediately followed in the command line by @emph{another} option +name, the value for the first option is implicitly @code{#t}. + +The @code{required?} property indicates whether an option is required to +be present in the command line. If the @code{required?} property is +set to @code{#t}, @code{getopt-long} will signal an error if the option +is not specified. + +Finally, the @code{predicate} property can be used to constrain the +possible values of an option. If used, the @code{predicate} property +should be set to a procedure that takes one argument --- the proposed +option value as a string --- and returns either @code{#t} or @code{#f} +according as the proposed value is or is not acceptable. If the +predicate procedure returns @code{#f}, @code{getopt-long} will signal an +error. + +By default, options do not have single-character equivalents, are not +required, and do not take values. Where the list element for an option +includes a @code{value} property but no @code{predicate} property, the +option values are unconstrained. + + +@node Command Line Format +@subsection Expected Command Line Format + +In order for @code{getopt-long} to correctly parse a command line, that +command line must conform to a standard set of rules for how command +line options are specified. This section explains what those rules +are. + +@code{getopt-long} splits a given command line into several pieces. All +elements of the argument list are classified to be either options or +normal arguments. Options consist of two dashes and an option name +(so-called @dfn{long} options), or of one dash followed by a single +letter (@dfn{short} options). + +Options can behave as switches, when they are given without a value, or +they can be used to pass a value to the program. The value for an +option may be specified using an equals sign, or else is simply the next +word in the command line, so the following two invocations are +equivalent: + +@example +$ ./foo.scm --output=bar.txt +$ ./foo.scm --output bar.txt +@end example + +Short options can be used instead of their long equivalents and can be +grouped together after a single dash. For example, the following +commands are equivalent. + +@example +$ ./foo.scm --version --help +$ ./foo.scm -v --help +$ ./foo.scm -vh +@end example + +If an option requires a value, it can only be grouped together with other +short options if it is the last option in the group; the value is the +next argument. So, for example, with the following option +specification --- + +@lisp +((apples (single-char #\a)) + (blimps (single-char #\b) (value #t)) + (catalexis (single-char #\c) (value #t))) +@end lisp + +@noindent +--- the following command lines would all be acceptable: + +@example +$ ./foo.scm -a -b bang -c couth +$ ./foo.scm -ab bang -c couth +$ ./foo.scm -ac couth -b bang +@end example + +But the next command line is an error, because @code{-b} is not the last +option in its combination, and because a group of short options cannot +include two options that both require values: + +@example +$ ./foo.scm -abc couth bang +@end example + +If an option's value is optional, @code{getopt-long} decides whether the +option has a value by looking at what follows it in the argument list. +If the next element is a string, and it does not appear to be an option +itself, then that string is the option's value. + +If the option @code{--} appears in the argument list, argument parsing +stops there and subsequent arguments are returned as ordinary arguments, +even if they resemble options. So, with the command line + +@example +$ ./foo.scm --apples "Granny Smith" -- --blimp Goodyear +@end example + +@noindent +@code{getopt-long} will recognize the @code{--apples} option as having +the value "Granny Smith", but will not treat @code{--blimp} as an +option. The strings @code{--blimp} and @code{Goodyear} will be returned +as ordinary argument strings. + + +@node getopt-long Reference +@subsection Reference Documentation for @code{getopt-long} + +@deffn {Scheme Procedure} getopt-long args grammar [#:stop-at-first-non-option #t] +Parse the command line given in @var{args} (which must be a list of +strings) according to the option specification @var{grammar}. + +The @var{grammar} argument is expected to be a list of this form: + +@code{((@var{option} (@var{property} @var{value}) @dots{}) @dots{})} + +where each @var{option} is a symbol denoting the long option, but +without the two leading dashes (e.g.@: @code{version} if the option is +called @code{--version}). + +For each option, there may be list of arbitrarily many property/value +pairs. The order of the pairs is not important, but every property may +only appear once in the property list. The following table lists the +possible properties: + +@table @asis +@item @code{(single-char @var{char})} +Accept @code{-@var{char}} as a single-character equivalent to +@code{--@var{option}}. This is how to specify traditional Unix-style +flags. +@item @code{(required? @var{bool})} +If @var{bool} is true, the option is required. @code{getopt-long} will +raise an error if it is not found in @var{args}. +@item @code{(value @var{bool})} +If @var{bool} is @code{#t}, the option accepts a value; if it is +@code{#f}, it does not; and if it is the symbol @code{optional}, the +option may appear in @var{args} with or without a value. +@item @code{(predicate @var{func})} +If the option accepts a value (i.e.@: you specified @code{(value #t)} for +this option), then @code{getopt-long} will apply @var{func} to the +value, and throw an exception if it returns @code{#f}. @var{func} +should be a procedure which accepts a string and returns a boolean +value; you may need to use quasiquotes to get it into @var{grammar}. +@end table + +The @code{#:stop-at-first-non-option} keyword, if specified with any +true value, tells @code{getopt-long} to stop when it gets to the first +non-option in the command line. That is, at the first word which is +neither an option itself, nor the value of an option. Everything in the +command line from that word onwards will be returned as non-option +arguments. +@end deffn + +@code{getopt-long}'s @var{args} parameter is expected to be a list of +strings like the one returned by @code{command-line}, with the first +element being the name of the command. Therefore @code{getopt-long} +ignores the first element in @var{args} and starts argument +interpretation with the second element. + +@code{getopt-long} signals an error if any of the following conditions +hold. + +@itemize @bullet +@item +The option grammar has an invalid syntax. + +@item +One of the options in the argument list was not specified by the +grammar. + +@item +A required option is omitted. + +@item +An option which requires an argument did not get one. + +@item +An option that doesn't accept an argument does get one (this can only +happen using the long option @code{--opt=@var{value}} syntax). + +@item +An option predicate fails. +@end itemize + +@code{#:stop-at-first-non-option} is useful for command line invocations +like @code{guild [--help | --version] [script [script-options]]} +and @code{cvs [general-options] command [command-options]}, where there +are options at two levels: some generic and understood by the outer +command, and some that are specific to the particular script or command +being invoked. To use @code{getopt-long} in such cases, you would call +it twice: firstly with @code{#:stop-at-first-non-option #t}, so as to +parse any generic options and identify the wanted script or sub-command; +secondly, and after trimming off the initial generic command words, with +a script- or sub-command-specific option grammar, so as to process those +specific options. + + +@node option-ref Reference +@subsection Reference Documentation for @code{option-ref} + +@deffn {Scheme Procedure} option-ref options key default +Search @var{options} for a command line option named @var{key} and +return its value, if found. If the option has no value, but was given, +return @code{#t}. If the option was not given, return @var{default}. +@var{options} must be the result of a call to @code{getopt-long}. +@end deffn + +@code{option-ref} always succeeds, either by returning the requested +option value from the command line, or the default value. + +The special key @code{'()} can be used to get a list of all +non-option arguments. diff --git a/doc/ref/mop.text b/doc/ref/mop.text new file mode 100644 index 000000000..0180f2c1e --- /dev/null +++ b/doc/ref/mop.text @@ -0,0 +1,66 @@ +*** NOTE: This information needs updating! *** + +P - procedure +L - local procedure +S - syntax +G - generic +M - method + +define-class (S) + make-class (S) + ensure-metaclass (P) + ensure-metaclass-with-supers (P) + make (G) + ensure-class (P) + make (G) + class-redefinition (G) + remove-class-accessors (G) + update-direct-method (G) + update-direct-subclass (G) + +define-generic (S) + make-generic-function (S) + ensure-generic-function (P) + make (G) + +define-method (S) + ensure-method (P) + ensure-generic-function (P) + make (G) + make (G) + add-method (P) + +method (S) + ensure-method (P) + +initialize (class) (M) + compute-cpl (P) + compute-slots (G) + compute-getters-n-setters (P) + compute-slot-init-function (L) + compute-get-n-set (G) + compute-slot-accessors (P) + ensure-method (P) + %inherit-magic! (P) + %prep-layout! (P) + +initialize (generic) (M) + make (G) + +change-class (G) + change-object-class (P) + update-instance-for-different-class (G) + +make = make-instance (G) + allocate-instance (G) + %allocate-instance (P) + initialize (G) + %initialize-object (P) + +apply-generic (G) + compute-applicable-methods (G) + find-method (P) + sort-applicable-methods (G) + sort (P) + apply-methods (G) + apply-method (G) diff --git a/doc/ref/new-docstrings.texi b/doc/ref/new-docstrings.texi new file mode 100644 index 000000000..65dda6e4f --- /dev/null +++ b/doc/ref/new-docstrings.texi @@ -0,0 +1,274 @@ +@c module-for-docstring (guile) + + + +@deffn {Scheme Procedure} uniform-array->bytevector array +@deffnx {C Function} scm_uniform_array_to_bytevector (array) +Return a newly allocated bytevector whose contents +will be copied from the uniform array @var{array}. +@end deffn + +@deffn {Scheme Procedure} %start-stack id thunk +@deffnx {C Function} scm_sys_start_stack (id, thunk) +Call @var{thunk} on an evaluator stack tagged with @var{id}. +@end deffn + +@deffn {Scheme Procedure} guardian-destroyed? guardian +@deffnx {C Function} scm_guardian_destroyed_p (guardian) +Return @code{#t} if @var{guardian} has been destroyed, otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} guardian-greedy? guardian +@deffnx {C Function} scm_guardian_greedy_p (guardian) +Return @code{#t} if @var{guardian} is a greedy guardian, otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} destroy-guardian! guardian +@deffnx {C Function} scm_destroy_guardian_x (guardian) +Destroys @var{guardian}, by making it impossible to put any more +objects in it or get any objects from it. It also unguards any +objects guarded by @var{guardian}. +@end deffn + +@deffn {Scheme Procedure} gc-dump +@deffnx {C Function} scm_gc_dump () +Dump information about the garbage collector's internal data structures and memory usage to the standard output. +@end deffn + +@deffn {Scheme Procedure} gc-disable +@deffnx {C Function} scm_gc_disable () +Disables the garbage collector. Nested calls are permitted. GC is re-enabled once @code{gc-enable} has been called the same number of times @code{gc-disable} was called. +@end deffn + +@deffn {Scheme Procedure} gc-enable +@deffnx {C Function} scm_gc_enable () +Enables the garbage collector. +@end deffn + +@deffn {Scheme Procedure} make-generalized-vector type len [fill] +@deffnx {C Function} scm_make_generalized_vector (type, len, fill) +Make a generalized vector +@end deffn + +@deffn {Scheme Procedure} set-primitive-generic! subr generic +@deffnx {C Function} scm_set_primitive_generic_x (subr, generic) + +@end deffn + +@deffn {Scheme Procedure} nl-langinfo item [locale] +@deffnx {C Function} scm_nl_langinfo (item, locale) +Return a string denoting locale information for @var{item} in the current locale or that specified by @var{locale}. The semantics and arguments are the same as those of the X/Open @code{nl_langinfo} function (@pxref{The Elegant and Fast Way, @code{nl_langinfo},, libc, The GNU C Library Reference Manual}). +@end deffn + +@deffn {Scheme Procedure} %warn-autocompilation-enabled +@deffnx {C Function} scm_sys_warn_autocompilation_enabled () + +@end deffn + +@deffn {Scheme Procedure} make-syncase-macro type binding +@deffnx {C Function} scm_make_syncase_macro (type, binding) +Return a @dfn{macro} that requires expansion by syntax-case. +While users should not call this function, it is useful to know +that syntax-case macros are represented as Guile primitive macros. +@end deffn + +@deffn {Scheme Procedure} make-extended-syncase-macro m type binding +@deffnx {C Function} scm_make_extended_syncase_macro (m, type, binding) +Extend a core macro @var{m} with a syntax-case binding. +@end deffn + +@deffn {Scheme Procedure} syncase-macro-type m +@deffnx {C Function} scm_syncase_macro_type (m) +Return the type of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} syncase-macro-binding m +@deffnx {C Function} scm_syncase_macro_binding (m) +Return the binding of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} memoize-expression exp +@deffnx {C Function} scm_memoize_expression (exp) +Memoize the expression @var{exp}. +@end deffn + +@deffn {Scheme Procedure} unmemoize-expression m +@deffnx {C Function} scm_unmemoize_expression (m) +Unmemoize the memoized expression @var{m}. +@end deffn + +@deffn {Scheme Procedure} memoized-expression-typecode m +@deffnx {C Function} scm_memoized_expression_typecode (m) +Return the typecode from the memoized expression @var{m}. +@end deffn + +@deffn {Scheme Procedure} memoized-expression-data m +@deffnx {C Function} scm_memoized_expression_data (m) +Return the data from the memoized expression @var{m}. +@end deffn + +@deffn {Scheme Procedure} memoized-typecode sym +@deffnx {C Function} scm_memoized_typecode (sym) +Return the memoized typecode corresponding to the symbol @var{sym}. +@end deffn + +@deffn {Scheme Procedure} memoize-variable-access! m mod +@deffnx {C Function} scm_memoize_variable_access_x (m, mod) +Look up and cache the variable that @var{m} will access, returning the variable. +@end deffn + +@deffn {Scheme Procedure} module-local-variable module sym +@deffnx {C Function} scm_module_local_variable (module, sym) +Return the variable bound to @var{sym} in @var{module}. Return @code{#f} is @var{sym} is not bound locally in @var{module}. +@end deffn + +@deffn {Scheme Procedure} module-variable module sym +@deffnx {C Function} scm_module_variable (module, sym) +Return the variable bound to @var{sym} in @var{module}. This may be both a local variable or an imported variable. Return @code{#f} is @var{sym} is not bound in @var{module}. +@end deffn + +@deffn {Scheme Procedure} eval-closure-module eval_closure +@deffnx {C Function} scm_eval_closure_module (eval_closure) +Return the module associated with this eval closure. +@end deffn + +@deffn {Scheme Procedure} module-transformer module +@deffnx {C Function} scm_module_transformer (module) +Returns the syntax expander for the given module. +@end deffn + +@deffn {Scheme Procedure} module-public-interface module +@deffnx {C Function} scm_module_public_interface (module) +Return the public interface of @var{module}. + +If @var{module} has no public interface, @code{#f} is returned. +@end deffn + +@deffn {Scheme Procedure} define! sym value +@deffnx {C Function} scm_define (sym, value) +Define @var{sym} to be @var{value} in the current module.Returns the variable itself. Note that this is a procedure, not a macro. +@end deffn + +@deffn {Scheme Procedure} module-reverse-lookup module variable +@deffnx {C Function} scm_module_reverse_lookup (module, variable) +Return the symbol under which @var{variable} is bound in @var{module} or @var{#f} if @var{variable} is not visible from @var{module}. If @var{module} is @code{#f}, then the pre-module obarray is used. +@end deffn + +@deffn {Scheme Procedure} cddr x +@deffnx {C Function} scm_cddr (x) + +@end deffn + +@deffn {Scheme Procedure} make-promise thunk +@deffnx {C Function} scm_make_promise (thunk) +Create a new promise object. + +@code{make-promise} is a procedural form of @code{delay}. +These two expressions are equivalent: +@lisp +(delay @var{exp}) +(make-promise (lambda () @var{exp})) +@end lisp + +@end deffn + +@deffn {Scheme Procedure} %get-stack-size +@deffnx {C Function} scm_sys_get_stack_size () +Return the current thread's C stack size (in Scheme objects). +@end deffn + +@deffn {Scheme Procedure} %string-dump str +@deffnx {C Function} scm_sys_string_dump (str) +Returns an association list containing debugging information +for @var{str}. The association list has the following entries.@table @code +@item string +The string itself. +@item start +The start index of the string into its stringbuf +@item length +The length of the string +@item shared +If this string is a substring, it returns its parent string. +Otherwise, it returns @code{#f} +@item read-only +@code{#t} if the string is read-only +@item stringbuf-chars +A new string containing this string's stringbuf's characters +@item stringbuf-length +The number of characters in this stringbuf +@item stringbuf-shared +@code{#t} if this stringbuf is shared +@item stringbuf-wide +@code{#t} if this stringbuf's characters are stored in a +32-bit buffer, or @code{#f} if they are stored in an 8-bit +buffer +@end table +@end deffn + +@deffn {Scheme Procedure} %symbol-dump sym +@deffnx {C Function} scm_sys_symbol_dump (sym) +Returns an association list containing debugging information +for @var{sym}. The association list has the following entries.@table @code +@item symbol +The symbol itself +@item hash +Its hash value +@item interned +@code{#t} if it is an interned symbol +@item stringbuf-chars +A new string containing this symbols's stringbuf's characters +@item stringbuf-length +The number of characters in this stringbuf +@item stringbuf-shared +@code{#t} if this stringbuf is shared +@item stringbuf-wide +@code{#t} if this stringbuf's characters are stored in a +32-bit buffer, or @code{#f} if they are stored in an 8-bit +buffer +@end table +@end deffn + +@deffn {Scheme Procedure} string-bytes-per-char string +@deffnx {C Function} scm_string_bytes_per_char (string) +Return the bytes used to represent a character in @var{string}.This will return 1 or 4. +@end deffn + +@deffn {Scheme Procedure} uniform-vector-element-type v +@deffnx {C Function} scm_uniform_vector_element_type (v) +Return the type of the elements in the uniform vector, @var{v}. +@end deffn + +@deffn {Scheme Procedure} uniform-vector-element-size v +@deffnx {C Function} scm_uniform_vector_element_size (v) +Return the number of bytes allocated to each element in the +uniform vector, @var{v}. +@end deffn + +@deffn {Scheme Procedure} canonicalize-path path +@deffnx {C Function} scm_canonicalize_path (path) +Return the canonical path of @var{path}. A canonical path has +no @code{.} or @code{..} components, nor any repeated path +separators (@code{/}) nor symlinks. + +Raises an error if any component of @var{path} does not exist. +@end deffn + +@deffn {Scheme Procedure} getrlimit resource +@deffnx {C Function} scm_getrlimit (resource) +Get a resource limit for this process. @var{resource} identifies the resource, +either as an integer or as a symbol. For example, @code{(getrlimit 'stack)} +gets the limits associated with @code{RLIMIT_STACK}. + +@code{getrlimit} returns two values, the soft and the hard limit. If no +limit is set for the resource in question, the returned limit will be @code{#f}. +@end deffn + +@deffn {Scheme Procedure} setrlimit resource soft hard +@deffnx {C Function} scm_setrlimit (resource, soft, hard) +Set a resource limit for this process. @var{resource} identifies the resource, +either as an integer or as a symbol. @var{soft} and @var{hard} should be integers, +or @code{#f} to indicate no limit (i.e., @code{RLIM_INFINITY}). + +For example, @code{(setrlimit 'stack 150000 300000)} sets the @code{RLIMIT_STACK} +limit to 150 kilobytes, with a hard limit of 300 kB. +@end deffn diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi new file mode 100644 index 000000000..5cb68a292 --- /dev/null +++ b/doc/ref/posix.texi @@ -0,0 +1,3624 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, +@c 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2017 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node POSIX +@section @acronym{POSIX} System Calls and Networking +@cindex POSIX + +@menu +* Conventions:: Conventions employed by the POSIX interface. +* Ports and File Descriptors:: Scheme ``ports'' and Unix file descriptors + have different representations. +* File System:: stat, chown, chmod, etc. +* User Information:: Retrieving a user's GECOS (/etc/passwd) entry. +* Time:: gettimeofday, localtime, strftime, etc. +* Runtime Environment:: Accessing and modifying Guile's environment. +* Processes:: getuid, getpid, etc. +* Signals:: sigaction, kill, pause, alarm, setitimer, etc. +* Terminals and Ptys:: ttyname, tcsetpgrp, etc. +* Pipes:: Communicating data between processes. +* Networking:: gethostbyaddr, getnetent, socket, bind, listen. +* System Identification:: Obtaining information about the system. +* Locales:: setlocale, etc. +* Encryption:: +@end menu + +@node Conventions +@subsection @acronym{POSIX} Interface Conventions + +These interfaces provide access to operating system facilities. +They provide a simple wrapping around the underlying C interfaces +to make usage from Scheme more convenient. They are also used +to implement the Guile port of scsh (@pxref{The Scheme shell (scsh)}). + +Generally there is a single procedure for each corresponding Unix +facility. There are some exceptions, such as procedures implemented for +speed and convenience in Scheme with no primitive Unix equivalent, +e.g.@: @code{copy-file}. + +The interfaces are intended as far as possible to be portable across +different versions of Unix. In some cases procedures which can't be +implemented on particular systems may become no-ops, or perform limited +actions. In other cases they may throw errors. + +General naming conventions are as follows: + +@itemize @bullet +@item +The Scheme name is often identical to the name of the underlying Unix +facility. +@item +Underscores in Unix procedure names are converted to hyphens. +@item +Procedures which destructively modify Scheme data have exclamation +marks appended, e.g., @code{recv!}. +@item +Predicates (returning only @code{#t} or @code{#f}) have question marks +appended, e.g., @code{access?}. +@item +Some names are changed to avoid conflict with dissimilar interfaces +defined by scsh, e.g., @code{primitive-fork}. +@item +Unix preprocessor names such as @code{EPERM} or @code{R_OK} are converted +to Scheme variables of the same name (underscores are not replaced +with hyphens). +@end itemize + +Unexpected conditions are generally handled by raising exceptions. +There are a few procedures which return a special value if they don't +succeed, e.g., @code{getenv} returns @code{#f} if it the requested +string is not found in the environment. These cases are noted in +the documentation. + +For ways to deal with exceptions, see @ref{Exceptions}. + +@cindex @code{errno} +Errors which the C library would report by returning a null pointer or +through some other means are reported by raising a @code{system-error} +exception with @code{scm-error} (@pxref{Error Reporting}). The +@var{data} parameter is a list containing the Unix @code{errno} value +(an integer). For example, + +@example +(define (my-handler key func fmt fmtargs data) + (display key) (newline) + (display func) (newline) + (apply format #t fmt fmtargs) (newline) + (display data) (newline)) + +(catch 'system-error + (lambda () (dup2 -123 -456)) + my-handler) + +@print{} +system-error +dup2 +Bad file descriptor +(9) +@end example + + +@sp 1 +@defun system-error-errno arglist +@cindex @code{errno} +Return the @code{errno} value from a list which is the arguments to an +exception handler. If the exception is not a @code{system-error}, +then the return is @code{#f}. For example, + +@example +(catch + 'system-error + (lambda () + (mkdir "/this-ought-to-fail-if-I'm-not-root")) + (lambda stuff + (let ((errno (system-error-errno stuff))) + (cond + ((= errno EACCES) + (display "You're not allowed to do that.")) + ((= errno EEXIST) + (display "Already exists.")) + (#t + (display (strerror errno)))) + (newline)))) +@end example +@end defun + + +@node Ports and File Descriptors +@subsection Ports and File Descriptors +@cindex file descriptor + +Conventions generally follow those of scsh, @ref{The Scheme shell (scsh)}. + +Each open file port has an associated operating system file descriptor. +File descriptors are generally not useful in Scheme programs; however +they may be needed when interfacing with foreign code and the Unix +environment. + +A file descriptor can be extracted from a port and a new port can be +created from a file descriptor. However a file descriptor is just an +integer and the garbage collector doesn't recognize it as a reference +to the port. If all other references to the port were dropped, then +it's likely that the garbage collector would free the port, with the +side-effect of closing the file descriptor prematurely. + +To assist the programmer in avoiding this problem, each port has an +associated @dfn{revealed count} which can be used to keep track of how many +times the underlying file descriptor has been stored in other places. +If a port's revealed count is greater than zero, the file descriptor +will not be closed when the port is garbage collected. A programmer +can therefore ensure that the revealed count will be greater than +zero if the file descriptor is needed elsewhere. + +For the simple case where a file descriptor is ``imported'' once to become +a port, it does not matter if the file descriptor is closed when the +port is garbage collected. There is no need to maintain a revealed +count. Likewise when ``exporting'' a file descriptor to the external +environment, setting the revealed count is not required provided the +port is kept open (i.e., is pointed to by a live Scheme binding) while +the file descriptor is in use. + +To correspond with traditional Unix behaviour, three file descriptors +(0, 1, and 2) are automatically imported when a program starts up and +assigned to the initial values of the current/standard input, output, +and error ports, respectively. The revealed count for each is +initially set to one, so that dropping references to one of these +ports will not result in its garbage collection: it could be retrieved +with @code{fdopen} or @code{fdes->ports}. + +Guile's ports can be buffered. This means that writing a byte to a file +port goes to the internal buffer first, and only when the buffer is full +(or the user invokes @code{force-output} on the port) is the data +actually written to the file descriptor. Likewise on input, bytes are +read in from the file descriptor in blocks and placed in a buffer. +Reading a character via @code{read-char} first goes to the buffer, +filling it as needed. Usually read buffering is more or less +transparent, but write buffering can sometimes cause writes to be +delayed unexpectedly, if you forget to call @code{force-output}. +@xref{Buffering}, for more on how to control port buffers. + +Note however that some procedures (e.g., @code{recv!}) will accept ports +as arguments, but will actually operate directly on the file descriptor +underlying the port. Any port buffering is ignored, including the +buffer which implements @code{peek-char} and @code{unread-char}. + +@deffn {Scheme Procedure} port-revealed port +@deffnx {C Function} scm_port_revealed (port) +Return the revealed count for @var{port}. +@end deffn + +@deffn {Scheme Procedure} set-port-revealed! port rcount +@deffnx {C Function} scm_set_port_revealed_x (port, rcount) +Sets the revealed count for a @var{port} to @var{rcount}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} fileno port +@deffnx {C Function} scm_fileno (port) +Return the integer file descriptor underlying @var{port}. Does +not change its revealed count. +@end deffn + +@deffn {Scheme Procedure} port->fdes port +Returns the integer file descriptor underlying @var{port}. As a +side effect the revealed count of @var{port} is incremented. +@end deffn + +@deffn {Scheme Procedure} fdopen fdes modes +@deffnx {C Function} scm_fdopen (fdes, modes) +Return a new port based on the file descriptor @var{fdes}. Modes are +given by the string @var{modes}. The revealed count of the port is +initialized to zero. The @var{modes} string is the same as that +accepted by @code{open-file} (@pxref{File Ports, open-file}). +@end deffn + +@deffn {Scheme Procedure} fdes->ports fdes +@deffnx {C Function} scm_fdes_to_ports (fdes) +Return a list of existing ports which have @var{fdes} as an +underlying file descriptor, without changing their revealed +counts. +@end deffn + +@deffn {Scheme Procedure} fdes->inport fdes +Returns an existing input port which has @var{fdes} as its underlying file +descriptor, if one exists, and increments its revealed count. +Otherwise, returns a new input port with a revealed count of 1. +@end deffn + +@deffn {Scheme Procedure} fdes->outport fdes +Returns an existing output port which has @var{fdes} as its underlying file +descriptor, if one exists, and increments its revealed count. +Otherwise, returns a new output port with a revealed count of 1. +@end deffn + +@deffn {Scheme Procedure} primitive-move->fdes port fdes +@deffnx {C Function} scm_primitive_move_to_fdes (port, fdes) +Moves the underlying file descriptor for @var{port} to the integer +value @var{fdes} without changing the revealed count of @var{port}. +Any other ports already using this descriptor will be automatically +shifted to new descriptors and their revealed counts reset to zero. +The return value is @code{#f} if the file descriptor already had the +required value or @code{#t} if it was moved. +@end deffn + +@deffn {Scheme Procedure} move->fdes port fdes +Moves the underlying file descriptor for @var{port} to the integer +value @var{fdes} and sets its revealed count to one. Any other ports +already using this descriptor will be automatically +shifted to new descriptors and their revealed counts reset to zero. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} release-port-handle port +Decrements the revealed count for a port. +@end deffn + +@deffn {Scheme Procedure} fsync port_or_fd +@deffnx {C Function} scm_fsync (port_or_fd) +Copies any unwritten data for the specified output file descriptor to disk. +If @var{port_or_fd} is a port, its buffer is flushed before the underlying +file descriptor is fsync'd. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} open path flags [mode] +@deffnx {C Function} scm_open (path, flags, mode) +Open the file named by @var{path} for reading and/or writing. +@var{flags} is an integer specifying how the file should be opened. +@var{mode} is an integer specifying the permission bits of the file, +if it needs to be created, before the umask (@pxref{Processes}) is +applied. The default is 666 (Unix itself has no default). + +@var{flags} can be constructed by combining variables using @code{logior}. +Basic flags are: + +@defvar O_RDONLY +Open the file read-only. +@end defvar +@defvar O_WRONLY +Open the file write-only. +@end defvar +@defvar O_RDWR +Open the file read/write. +@end defvar +@defvar O_APPEND +Append to the file instead of truncating. +@end defvar +@defvar O_CREAT +Create the file if it does not already exist. +@end defvar + +@xref{File Status Flags,,,libc,The GNU C Library Reference Manual}, +for additional flags. +@end deffn + +@deffn {Scheme Procedure} open-fdes path flags [mode] +@deffnx {C Function} scm_open_fdes (path, flags, mode) +Similar to @code{open} but return a file descriptor instead of +a port. +@end deffn + +@deffn {Scheme Procedure} close fd_or_port +@deffnx {C Function} scm_close (fd_or_port) +Similar to @code{close-port} (@pxref{Ports, close-port}), +but also works on file descriptors. A side +effect of closing a file descriptor is that any ports using that file +descriptor are moved to a different file descriptor and have +their revealed counts set to zero. +@end deffn + +@deffn {Scheme Procedure} close-fdes fd +@deffnx {C Function} scm_close_fdes (fd) +A simple wrapper for the @code{close} system call. Close file +descriptor @var{fd}, which must be an integer. Unlike @code{close}, +the file descriptor will be closed even if a port is using it. The +return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} pipe +@deffnx {C Function} scm_pipe () +@cindex pipe +Return a newly created pipe: a pair of ports which are linked together +on the local machine. The @acronym{CAR} is the input port and the +@acronym{CDR} is the output port. Data written (and flushed) to the +output port can be read from the input port. Pipes are commonly used +for communication with a newly forked child process. The need to flush +the output port can be avoided by making it unbuffered using +@code{setvbuf} (@pxref{Buffering}). + +@defvar PIPE_BUF +A write of up to @code{PIPE_BUF} many bytes to a pipe is atomic, +meaning when done it goes into the pipe instantaneously and as a +contiguous block (@pxref{Pipe Atomicity,, Atomicity of Pipe I/O, libc, +The GNU C Library Reference Manual}). +@end defvar + +Note that the output port is likely to block if too much data has been +written but not yet read from the input port. Typically the capacity +is @code{PIPE_BUF} bytes. +@end deffn + +The next group of procedures perform a @code{dup2} +system call, if @var{newfd} (an +integer) is supplied, otherwise a @code{dup}. The file descriptor to be +duplicated can be supplied as an integer or contained in a port. The +type of value returned varies depending on which procedure is used. + +All procedures also have the side effect when performing @code{dup2} that any +ports using @var{newfd} are moved to a different file descriptor and have +their revealed counts set to zero. + +@deffn {Scheme Procedure} dup->fdes fd_or_port [fd] +@deffnx {C Function} scm_dup_to_fdes (fd_or_port, fd) +Return a new integer file descriptor referring to the open file +designated by @var{fd_or_port}, which must be either an open +file port or a file descriptor. +@end deffn + +@deffn {Scheme Procedure} dup->inport port/fd [newfd] +Returns a new input port using the new file descriptor. +@end deffn + +@deffn {Scheme Procedure} dup->outport port/fd [newfd] +Returns a new output port using the new file descriptor. +@end deffn + +@deffn {Scheme Procedure} dup port/fd [newfd] +Returns a new port if @var{port/fd} is a port, with the same mode as the +supplied port, otherwise returns an integer file descriptor. +@end deffn + +@deffn {Scheme Procedure} dup->port port/fd mode [newfd] +Returns a new port using the new file descriptor. @var{mode} supplies a +mode string for the port (@pxref{File Ports, open-file}). +@end deffn + +@deffn {Scheme Procedure} duplicate-port port modes +Returns a new port which is opened on a duplicate of the file +descriptor underlying @var{port}, with mode string @var{modes} +as for @ref{File Ports, open-file}. The two ports +will share a file position and file status flags. + +Unexpected behaviour can result if both ports are subsequently used +and the original and/or duplicate ports are buffered. +The mode string can include @code{0} to obtain an unbuffered duplicate +port. + +This procedure is equivalent to @code{(dup->port @var{port} @var{modes})}. +@end deffn + +@deffn {Scheme Procedure} redirect-port old_port new_port +@deffnx {C Function} scm_redirect_port (old_port, new_port) +This procedure takes two ports and duplicates the underlying file +descriptor from @var{old_port} into @var{new_port}. The +current file descriptor in @var{new_port} will be closed. +After the redirection the two ports will share a file position +and file status flags. + +The return value is unspecified. + +Unexpected behaviour can result if both ports are subsequently used +and the original and/or duplicate ports are buffered. + +This procedure does not have any side effects on other ports or +revealed counts. +@end deffn + +@deffn {Scheme Procedure} dup2 oldfd newfd +@deffnx {C Function} scm_dup2 (oldfd, newfd) +A simple wrapper for the @code{dup2} system call. +Copies the file descriptor @var{oldfd} to descriptor +number @var{newfd}, replacing the previous meaning +of @var{newfd}. Both @var{oldfd} and @var{newfd} must +be integers. +Unlike for @code{dup->fdes} or @code{primitive-move->fdes}, no attempt +is made to move away ports which are using @var{newfd}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} port-for-each proc +@deffnx {C Function} scm_port_for_each (SCM proc) +@deffnx {C Function} scm_c_port_for_each (void (*proc)(void *, SCM), void *data) +Apply @var{proc} to each port in the Guile port table +(FIXME: what is the Guile port table?) +in turn. The return value is unspecified. More specifically, +@var{proc} is applied exactly once to every port that exists in the +system at the time @code{port-for-each} is invoked. Changes to the +port table while @code{port-for-each} is running have no effect as far +as @code{port-for-each} is concerned. + +The C function @code{scm_port_for_each} takes a Scheme procedure +encoded as a @code{SCM} value, while @code{scm_c_port_for_each} takes +a pointer to a C function and passes along a arbitrary @var{data} +cookie. +@end deffn + +@deffn {Scheme Procedure} fcntl port/fd cmd [value] +@deffnx {C Function} scm_fcntl (object, cmd, value) +Apply @var{cmd} on @var{port/fd}, either a port or file descriptor. +The @var{value} argument is used by the @code{SET} commands described +below, it's an integer value. + +Values for @var{cmd} are: + +@defvar F_DUPFD +Duplicate the file descriptor, the same as @code{dup->fdes} above +does. +@end defvar + +@defvar F_GETFD +@defvarx F_SETFD +Get or set flags associated with the file descriptor. The only flag +is the following, + +@defvar FD_CLOEXEC +``Close on exec'', meaning the file descriptor will be closed on an +@code{exec} call (a successful such call). For example to set that +flag, + +@example +(fcntl port F_SETFD FD_CLOEXEC) +@end example + +Or better, set it but leave any other possible future flags unchanged, + +@example +(fcntl port F_SETFD (logior FD_CLOEXEC + (fcntl port F_GETFD))) +@end example +@end defvar +@end defvar + +@defvar F_GETFL +@defvarx F_SETFL +Get or set flags associated with the open file. These flags are +@code{O_RDONLY} etc described under @code{open} above. + +A common use is to set @code{O_NONBLOCK} on a network socket. The +following sets that flag, and leaves other flags unchanged. + +@example +(fcntl sock F_SETFL (logior O_NONBLOCK + (fcntl sock F_GETFL))) +@end example +@end defvar + +@defvar F_GETOWN +@defvarx F_SETOWN +Get or set the process ID of a socket's owner, for @code{SIGIO} signals. +@end defvar +@end deffn + +@deffn {Scheme Procedure} flock file operation +@deffnx {C Function} scm_flock (file, operation) +@cindex file locking +Apply or remove an advisory lock on an open file. +@var{operation} specifies the action to be done: + +@defvar LOCK_SH +Shared lock. More than one process may hold a shared lock +for a given file at a given time. +@end defvar +@defvar LOCK_EX +Exclusive lock. Only one process may hold an exclusive lock +for a given file at a given time. +@end defvar +@defvar LOCK_UN +Unlock the file. +@end defvar +@defvar LOCK_NB +Don't block when locking. This is combined with one of the other +operations using @code{logior} (@pxref{Bitwise Operations}). If +@code{flock} would block an @code{EWOULDBLOCK} error is thrown +(@pxref{Conventions}). +@end defvar + +The return value is not specified. @var{file} may be an open +file descriptor or an open file descriptor port. + +Note that @code{flock} does not lock files across NFS. +@end deffn + +@deffn {Scheme Procedure} select reads writes excepts [secs [usecs]] +@deffnx {C Function} scm_select (reads, writes, excepts, secs, usecs) +This procedure has a variety of uses: waiting for the ability +to provide input, accept output, or the existence of +exceptional conditions on a collection of ports or file +descriptors, or waiting for a timeout to occur. + +When an error occurs, this procedure throws a @code{system-error} +exception (@pxref{Conventions, @code{system-error}}). Note that +@code{select} may return early for other reasons, for example due to +pending interrupts. @xref{Asyncs}, for more on interrupts. + +@var{reads}, @var{writes} and @var{excepts} can be lists or +vectors, with each member a port or a file descriptor. +The value returned is a list of three corresponding +lists or vectors containing only the members which meet the +specified requirement. The ability of port buffers to +provide input or accept output is taken into account. +Ordering of the input lists or vectors is not preserved. + +The optional arguments @var{secs} and @var{usecs} specify the +timeout. Either @var{secs} can be specified alone, as +either an integer or a real number, or both @var{secs} and +@var{usecs} can be specified as integers, in which case +@var{usecs} is an additional timeout expressed in +microseconds. If @var{secs} is omitted or is @code{#f} then +select will wait for as long as it takes for one of the other +conditions to be satisfied. + +The scsh version of @code{select} differs as follows: +Only vectors are accepted for the first three arguments. +The @var{usecs} argument is not supported. +Multiple values are returned instead of a list. +Duplicates in the input vectors appear only once in output. +An additional @code{select!} interface is provided. +@end deffn + +While it is sometimes necessary to operate at the level of file +descriptors, this is an operation whose correctness can only be +considered as part of a whole program. So for example while the effects +of @code{(string-set! x 34 #\y)} are limited to the bits of code that +can access @var{x}, @code{(close-fdes 34)} mutates the state of the +entire process. In particular if another thread is using file +descriptor 34 then their state might be corrupted; and another thread +which opens a file might cause file descriptor 34 to be re-used, so that +corruption could manifest itself in a strange way. + +@cindex fdes finalizers +@cindex file descriptor finalizers +@cindex finalizers, file descriptor +However when working with file descriptors, it's common to want to +associate information with the file descriptor, perhaps in a side table. +To support this use case and to allow user code to remove an association +when a file descriptor is closed, Guile offers @dfn{fdes finalizers}. + +As the name indicates, fdes finalizers are finalizers -- they can run in +response to garbage collection, and they can also run in response to +explicit calls to @code{close-port}, @code{close-fdes}, or the like. As +such they inherit many of the pitfalls of finalizers: they may be +invoked from concurrent threads, or not at all. @xref{Foreign Object +Memory Management}, for more on finalizers. + +To use fdes finalizers, import their module; + +@example +(use-modules (ice-9 fdes-finalizers)) +@end example + +@deffn {Scheme Procedure} add-fdes-finalizer! fdes finalizer +@deffnx {Scheme Procedure} remove-fdes-finalizer! fdes finalizer +Add or remove a finalizer for @var{fdes}. A finalizer is a procedure +that is called by Guile when a file descriptor is closed. The file +descriptor being closed is passed as the one argument to the finalizer. +If a finalizer has been added multiple times to a file descriptor, to +remove it would require that number of calls to +@code{remove-fdes-finalizer!}. + +The finalizers added to a file descriptor are called by Guile in an +unspecified order, and their return values are ignored. +@end deffn + + +@node File System +@subsection File System +@cindex file system + +These procedures allow querying and setting file system attributes +(such as owner, +permissions, sizes and types of files); deleting, copying, renaming and +linking files; creating and removing directories and querying their +contents; syncing the file system and creating special files. + +@deffn {Scheme Procedure} access? path how +@deffnx {C Function} scm_access (path, how) +Test accessibility of a file under the real UID and GID of the calling +process. The return is @code{#t} if @var{path} exists and the +permissions requested by @var{how} are all allowed, or @code{#f} if +not. + +@var{how} is an integer which is one of the following values, or a +bitwise-OR (@code{logior}) of multiple values. + +@defvar R_OK +Test for read permission. +@end defvar +@defvar W_OK +Test for write permission. +@end defvar +@defvar X_OK +Test for execute permission. +@end defvar +@defvar F_OK +Test for existence of the file. This is implied by each of the other +tests, so there's no need to combine it with them. +@end defvar + +It's important to note that @code{access?} does not simply indicate +what will happen on attempting to read or write a file. In normal +circumstances it does, but in a set-UID or set-GID program it doesn't +because @code{access?} tests the real ID, whereas an open or execute +attempt uses the effective ID. + +A program which will never run set-UID/GID can ignore the difference +between real and effective IDs, but for maximum generality, especially +in library functions, it's best not to use @code{access?} to predict +the result of an open or execute, instead simply attempt that and +catch any exception. + +The main use for @code{access?} is to let a set-UID/GID program +determine what the invoking user would have been allowed to do, +without the greater (or perhaps lesser) privileges afforded by the +effective ID. For more on this, see @ref{Testing File Access,,, libc, +The GNU C Library Reference Manual}. +@end deffn + +@findex fstat +@deffn {Scheme Procedure} stat object +@deffnx {C Function} scm_stat (object) +Return an object containing various information about the file +determined by @var{object}. @var{object} can be a string containing +a file name or a port or integer file descriptor which is open +on a file (in which case @code{fstat} is used as the underlying +system call). + +The object returned by @code{stat} can be passed as a single +parameter to the following procedures, all of which return +integers: + +@deffn {Scheme Procedure} stat:dev st +The device number containing the file. +@end deffn +@deffn {Scheme Procedure} stat:ino st +The file serial number, which distinguishes this file from all +other files on the same device. +@end deffn +@deffn {Scheme Procedure} stat:mode st +The mode of the file. This is an integer which incorporates file type +information and file permission bits. See also @code{stat:type} and +@code{stat:perms} below. +@end deffn +@deffn {Scheme Procedure} stat:nlink st +The number of hard links to the file. +@end deffn +@deffn {Scheme Procedure} stat:uid st +The user ID of the file's owner. +@end deffn +@deffn {Scheme Procedure} stat:gid st +The group ID of the file. +@end deffn +@deffn {Scheme Procedure} stat:rdev st +Device ID; this entry is defined only for character or block special +files. On some systems this field is not available at all, in which +case @code{stat:rdev} returns @code{#f}. +@end deffn +@deffn {Scheme Procedure} stat:size st +The size of a regular file in bytes. +@end deffn +@deffn {Scheme Procedure} stat:atime st +The last access time for the file, in seconds. +@end deffn +@deffn {Scheme Procedure} stat:mtime st +The last modification time for the file, in seconds. +@end deffn +@deffn {Scheme Procedure} stat:ctime st +The last modification time for the attributes of the file, in seconds. +@end deffn +@deffn {Scheme Procedure} stat:atimensec st +@deffnx {Scheme Procedure} stat:mtimensec st +@deffnx {Scheme Procedure} stat:ctimensec st +The fractional part of a file's access, modification, or attribute modification +time, in nanoseconds. Nanosecond timestamps are only available on some operating +systems and file systems. If Guile cannot retrieve nanosecond-level timestamps +for a file, these fields will be set to 0. +@end deffn +@deffn {Scheme Procedure} stat:blksize st +The optimal block size for reading or writing the file, in bytes. On +some systems this field is not available, in which case +@code{stat:blksize} returns a sensible suggested block size. +@end deffn +@deffn {Scheme Procedure} stat:blocks st +The amount of disk space that the file occupies measured in units of +512 byte blocks. On some systems this field is not available, in +which case @code{stat:blocks} returns @code{#f}. +@end deffn + +In addition, the following procedures return the information +from @code{stat:mode} in a more convenient form: + +@deffn {Scheme Procedure} stat:type st +A symbol representing the type of file. Possible values are +@samp{regular}, @samp{directory}, @samp{symlink}, +@samp{block-special}, @samp{char-special}, @samp{fifo}, @samp{socket}, +and @samp{unknown}. +@end deffn +@deffn {Scheme Procedure} stat:perms st +An integer representing the access permission bits. +@end deffn +@end deffn + +@deffn {Scheme Procedure} lstat path +@deffnx {C Function} scm_lstat (path) +Similar to @code{stat}, but does not follow symbolic links, i.e., +it will return information about a symbolic link itself, not the +file it points to. @var{path} must be a string. +@end deffn + +@deffn {Scheme Procedure} readlink path +@deffnx {C Function} scm_readlink (path) +Return the value of the symbolic link named by @var{path} (a +string), i.e., the file that the link points to. +@end deffn + +@findex fchown +@findex lchown +@deffn {Scheme Procedure} chown object owner group +@deffnx {C Function} scm_chown (object, owner, group) +Change the ownership and group of the file referred to by @var{object} +to the integer values @var{owner} and @var{group}. @var{object} can +be a string containing a file name or, if the platform supports +@code{fchown} (@pxref{File Owner,,,libc,The GNU C Library Reference +Manual}), a port or integer file descriptor which is open on the file. +The return value is unspecified. + +If @var{object} is a symbolic link, either the +ownership of the link or the ownership of the referenced file will be +changed depending on the operating system (lchown is +unsupported at present). If @var{owner} or @var{group} is specified +as @code{-1}, then that ID is not changed. +@end deffn + +@findex fchmod +@deffn {Scheme Procedure} chmod object mode +@deffnx {C Function} scm_chmod (object, mode) +Changes the permissions of the file referred to by @var{object}. +@var{object} can be a string containing a file name or a port or integer file +descriptor which is open on a file (in which case @code{fchmod} is used +as the underlying system call). +@var{mode} specifies +the new permissions as a decimal number, e.g., @code{(chmod "foo" #o755)}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} utime pathname [actime [modtime [actimens [modtimens [flags]]]]] +@deffnx {C Function} scm_utime (pathname, actime, modtime, actimens, modtimens, flags) +@code{utime} sets the access and modification times for the +file named by @var{pathname}. If @var{actime} or @var{modtime} is +not supplied, then the current time is used. @var{actime} and +@var{modtime} must be integer time values as returned by the +@code{current-time} procedure. + +The optional @var{actimens} and @var{modtimens} are nanoseconds +to add @var{actime} and @var{modtime}. Nanosecond precision is +only supported on some combinations of file systems and operating +systems. +@lisp +(utime "foo" (- (current-time) 3600)) +@end lisp +will set the access time to one hour in the past and the +modification time to the current time. +@end deffn + +@findex unlink +@deffn {Scheme Procedure} delete-file str +@deffnx {C Function} scm_delete_file (str) +Deletes (or ``unlinks'') the file whose path is specified by +@var{str}. +@end deffn + +@deffn {Scheme Procedure} copy-file oldfile newfile +@deffnx {C Function} scm_copy_file (oldfile, newfile) +Copy the file specified by @var{oldfile} to @var{newfile}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} sendfile out in count [offset] +@deffnx {C Function} scm_sendfile (out, in, count, offset) +Send @var{count} bytes from @var{in} to @var{out}, both of which +must be either open file ports or file descriptors. When +@var{offset} is omitted, start reading from @var{in}'s current +position; otherwise, start reading at @var{offset}. Return +the number of bytes actually sent. + +When @var{in} is a port, it is often preferable to specify @var{offset}, +because @var{in}'s offset as a port may be different from the offset of +its underlying file descriptor. + +On systems that support it, such as GNU/Linux, this procedure uses the +@code{sendfile} libc function, which usually corresponds to a system +call. This is faster than doing a series of @code{read} and +@code{write} system calls. A typical application is to send a file over +a socket. + +In some cases, the @code{sendfile} libc function may return +@code{EINVAL} or @code{ENOSYS}. In that case, Guile's @code{sendfile} +procedure automatically falls back to doing a series of @code{read} and +@code{write} calls. + +In other cases, the libc function may send fewer bytes than +@var{count}---for instance because @var{out} is a slow or limited +device, such as a pipe. When that happens, Guile's @code{sendfile} +automatically retries until exactly @var{count} bytes were sent or an +error occurs. +@end deffn + +@findex rename +@deffn {Scheme Procedure} rename-file oldname newname +@deffnx {C Function} scm_rename (oldname, newname) +Renames the file specified by @var{oldname} to @var{newname}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} link oldpath newpath +@deffnx {C Function} scm_link (oldpath, newpath) +Creates a new name @var{newpath} in the file system for the +file named by @var{oldpath}. If @var{oldpath} is a symbolic +link, the link may or may not be followed depending on the +system. +@end deffn + +@deffn {Scheme Procedure} symlink oldpath newpath +@deffnx {C Function} scm_symlink (oldpath, newpath) +Create a symbolic link named @var{newpath} with the value (i.e., pointing to) +@var{oldpath}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} mkdir path [mode] +@deffnx {C Function} scm_mkdir (path, mode) +Create a new directory named by @var{path}. If @var{mode} is omitted +then the permissions of the directory are set to @code{#o777} +masked with the current umask (@pxref{Processes, @code{umask}}). +Otherwise they are set to the value specified with @var{mode}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} rmdir path +@deffnx {C Function} scm_rmdir (path) +Remove the existing directory named by @var{path}. The directory must +be empty for this to succeed. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} opendir dirname +@deffnx {C Function} scm_opendir (dirname) +@cindex directory contents +Open the directory specified by @var{dirname} and return a directory +stream. + +Before using this and the procedures below, make sure to see the +higher-level procedures for directory traversal that are available +(@pxref{File Tree Walk}). +@end deffn + +@deffn {Scheme Procedure} directory-stream? object +@deffnx {C Function} scm_directory_stream_p (object) +Return a boolean indicating whether @var{object} is a directory +stream as returned by @code{opendir}. +@end deffn + +@deffn {Scheme Procedure} readdir stream +@deffnx {C Function} scm_readdir (stream) +Return (as a string) the next directory entry from the directory stream +@var{stream}. If there is no remaining entry to be read then the +end of file object is returned. +@end deffn + +@deffn {Scheme Procedure} rewinddir stream +@deffnx {C Function} scm_rewinddir (stream) +Reset the directory port @var{stream} so that the next call to +@code{readdir} will return the first directory entry. +@end deffn + +@deffn {Scheme Procedure} closedir stream +@deffnx {C Function} scm_closedir (stream) +Close the directory stream @var{stream}. +The return value is unspecified. +@end deffn + +Here is an example showing how to display all the entries in a +directory: + +@lisp +(define dir (opendir "/usr/lib")) +(do ((entry (readdir dir) (readdir dir))) + ((eof-object? entry)) + (display entry)(newline)) +(closedir dir) +@end lisp + +@deffn {Scheme Procedure} sync +@deffnx {C Function} scm_sync () +Flush the operating system disk buffers. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} mknod path type perms dev +@deffnx {C Function} scm_mknod (path, type, perms, dev) +@cindex device file +Creates a new special file, such as a file corresponding to a device. +@var{path} specifies the name of the file. @var{type} should be one +of the following symbols: @samp{regular}, @samp{directory}, +@samp{symlink}, @samp{block-special}, @samp{char-special}, +@samp{fifo}, or @samp{socket}. @var{perms} (an integer) specifies the +file permissions. @var{dev} (an integer) specifies which device the +special file refers to. Its exact interpretation depends on the kind +of special file being created. + +E.g., +@lisp +(mknod "/dev/fd0" 'block-special #o660 (+ (* 2 256) 2)) +@end lisp + +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} tmpnam +@deffnx {C Function} scm_tmpnam () +@cindex temporary file +Return an auto-generated name of a temporary file, a file which +doesn't already exist. The name includes a path, it's usually in +@file{/tmp} but that's system dependent. + +Care must be taken when using @code{tmpnam}. In between choosing the +name and creating the file another program might use that name, or an +attacker might even make it a symlink pointing at something important +and causing you to overwrite that. + +The safe way is to create the file using @code{open} with +@code{O_EXCL} to avoid any overwriting. A loop can try again with +another name if the file exists (error @code{EEXIST}). +@code{mkstemp!} below does that. +@end deffn + +@deffn {Scheme Procedure} mkstemp! tmpl [mode] +@deffnx {C Function} scm_mkstemp (tmpl) +@cindex temporary file +Create a new unique file in the file system and return a new buffered +port open for reading and writing to the file. + +@var{tmpl} is a string specifying where the file should be created: it +must end with @samp{XXXXXX} and those @samp{X}s will be changed in the +string to return the name of the file. (@code{port-filename} on the +port also gives the name.) + +POSIX doesn't specify the permissions mode of the file, on GNU and +most systems it's @code{#o600}. An application can use @code{chmod} +to relax that if desired. For example @code{#o666} less @code{umask}, +which is usual for ordinary file creation, + +@example +(let ((port (mkstemp! (string-copy "/tmp/myfile-XXXXXX")))) + (chmod port (logand #o666 (lognot (umask)))) + ...) +@end example + +The optional @var{mode} argument specifies a mode with which to open the +new file, as a string in the same format that @code{open-file} takes. +It defaults to @code{"w+"}. +@end deffn + +@deffn {Scheme Procedure} tmpfile +@deffnx {C Function} scm_tmpfile () +Return an input/output port to a unique temporary file +named using the path prefix @code{P_tmpdir} defined in +@file{stdio.h}. +The file is automatically deleted when the port is closed +or the program terminates. +@end deffn + +@deffn {Scheme Procedure} dirname filename +@deffnx {C Function} scm_dirname (filename) +Return the directory name component of the file name +@var{filename}. If @var{filename} does not contain a directory +component, @code{.} is returned. +@end deffn + +@deffn {Scheme Procedure} basename filename [suffix] +@deffnx {C Function} scm_basename (filename, suffix) +Return the base name of the file name @var{filename}. The +base name is the file name without any directory components. +If @var{suffix} is provided, and is equal to the end of +@var{basename}, it is removed also. + +@lisp +(basename "/tmp/test.xml" ".xml") +@result{} "test" +@end lisp +@end deffn + +@deffn {Scheme Procedure} file-exists? filename +Return @code{#t} if the file named @var{filename} exists, @code{#f} if +not. +@end deffn + +@cindex file name separator +@cindex absolute file name + +Many operating systems, such as GNU, use @code{/} (forward slash) to +separate the components of a file name; any file name starting with +@code{/} is considered an @dfn{absolute file name}. These conventions +are specified by the POSIX Base Definitions, which refer to conforming +file names as ``pathnames''. Some operating systems use a different +convention; in particular, Windows uses @code{\} (backslash) as the file +name separator, and also has the notion of @dfn{volume names} like +@code{C:\} for absolute file names. The following procedures and +variables provide support for portable file name manipulations. + +@deffn {Scheme Procedure} system-file-name-convention +Return either @code{posix} or @code{windows}, depending on +what kind of system this Guile is running on. +@end deffn + +@deffn {Scheme Procedure} file-name-separator? c +Return true if character @var{c} is a file name separator on the host +platform. +@end deffn + +@deffn {Scheme Procedure} absolute-file-name? file-name +Return true if @var{file-name} denotes an absolute file name on the host +platform. +@end deffn + +@defvr {Scheme Variable} file-name-separator-string +The preferred file name separator. + +Note that on MinGW builds for Windows, both @code{/} and @code{\} are +valid separators. Thus, programs should not assume that +@code{file-name-separator-string} is the @emph{only} file name +separator---e.g., when extracting the components of a file name. +@end defvr + + +@node User Information +@subsection User Information +@cindex user information +@cindex password file +@cindex group file + +The facilities in this section provide an interface to the user and +group database. +They should be used with care since they are not reentrant. + +The following functions accept an object representing user information +and return a selected component: + +@deffn {Scheme Procedure} passwd:name pw +The name of the userid. +@end deffn +@deffn {Scheme Procedure} passwd:passwd pw +The encrypted passwd. +@end deffn +@deffn {Scheme Procedure} passwd:uid pw +The user id number. +@end deffn +@deffn {Scheme Procedure} passwd:gid pw +The group id number. +@end deffn +@deffn {Scheme Procedure} passwd:gecos pw +The full name. +@end deffn +@deffn {Scheme Procedure} passwd:dir pw +The home directory. +@end deffn +@deffn {Scheme Procedure} passwd:shell pw +The login shell. +@end deffn +@sp 1 + +@deffn {Scheme Procedure} getpwuid uid +Look up an integer userid in the user database. +@end deffn + +@deffn {Scheme Procedure} getpwnam name +Look up a user name string in the user database. +@end deffn + +@deffn {Scheme Procedure} setpwent +Initializes a stream used by @code{getpwent} to read from the user database. +The next use of @code{getpwent} will return the first entry. The +return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} getpwent +Read the next entry in the user database stream. The return is a +passwd user object as above, or @code{#f} when no more entries. +@end deffn + +@deffn {Scheme Procedure} endpwent +Closes the stream used by @code{getpwent}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setpw [arg] +@deffnx {C Function} scm_setpwent (arg) +If called with a true argument, initialize or reset the password data +stream. Otherwise, close the stream. The @code{setpwent} and +@code{endpwent} procedures are implemented on top of this. +@end deffn + +@deffn {Scheme Procedure} getpw [user] +@deffnx {C Function} scm_getpwuid (user) +Look up an entry in the user database. @var{user} can be an integer, +a string, or omitted, giving the behaviour of getpwuid, getpwnam +or getpwent respectively. +@end deffn + +The following functions accept an object representing group information +and return a selected component: + +@deffn {Scheme Procedure} group:name gr +The group name. +@end deffn +@deffn {Scheme Procedure} group:passwd gr +The encrypted group password. +@end deffn +@deffn {Scheme Procedure} group:gid gr +The group id number. +@end deffn +@deffn {Scheme Procedure} group:mem gr +A list of userids which have this group as a supplementary group. +@end deffn +@sp 1 + +@deffn {Scheme Procedure} getgrgid gid +Look up an integer group id in the group database. +@end deffn + +@deffn {Scheme Procedure} getgrnam name +Look up a group name in the group database. +@end deffn + +@deffn {Scheme Procedure} setgrent +Initializes a stream used by @code{getgrent} to read from the group database. +The next use of @code{getgrent} will return the first entry. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} getgrent +Return the next entry in the group database, using the stream set by +@code{setgrent}. +@end deffn + +@deffn {Scheme Procedure} endgrent +Closes the stream used by @code{getgrent}. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setgr [arg] +@deffnx {C Function} scm_setgrent (arg) +If called with a true argument, initialize or reset the group data +stream. Otherwise, close the stream. The @code{setgrent} and +@code{endgrent} procedures are implemented on top of this. +@end deffn + +@deffn {Scheme Procedure} getgr [group] +@deffnx {C Function} scm_getgrgid (group) +Look up an entry in the group database. @var{group} can be an integer, +a string, or omitted, giving the behaviour of getgrgid, getgrnam +or getgrent respectively. +@end deffn + +In addition to the accessor procedures for the user database, the +following shortcut procedure is also available. + +@deffn {Scheme Procedure} getlogin +@deffnx {C Function} scm_getlogin () +Return a string containing the name of the user logged in on +the controlling terminal of the process, or @code{#f} if this +information cannot be obtained. +@end deffn + + +@node Time +@subsection Time +@cindex time + +@deffn {Scheme Procedure} current-time +@deffnx {C Function} scm_current_time () +Return the number of seconds since 1970-01-01 00:00:00 @acronym{UTC}, +excluding leap seconds. +@end deffn + +@deffn {Scheme Procedure} gettimeofday +@deffnx {C Function} scm_gettimeofday () +Return a pair containing the number of seconds and microseconds +since 1970-01-01 00:00:00 @acronym{UTC}, excluding leap seconds. Note: +whether true microsecond resolution is available depends on the +operating system. +@end deffn + +The following procedures either accept an object representing a broken down +time and return a selected component, or accept an object representing +a broken down time and a value and set the component to the value. +The numbers in parentheses give the usual range. + +@deffn {Scheme Procedure} tm:sec tm +@deffnx {Scheme Procedure} set-tm:sec tm val +Seconds (0-59). +@end deffn +@deffn {Scheme Procedure} tm:min tm +@deffnx {Scheme Procedure} set-tm:min tm val +Minutes (0-59). +@end deffn +@deffn {Scheme Procedure} tm:hour tm +@deffnx {Scheme Procedure} set-tm:hour tm val +Hours (0-23). +@end deffn +@deffn {Scheme Procedure} tm:mday tm +@deffnx {Scheme Procedure} set-tm:mday tm val +Day of the month (1-31). +@end deffn +@deffn {Scheme Procedure} tm:mon tm +@deffnx {Scheme Procedure} set-tm:mon tm val +Month (0-11). +@end deffn +@deffn {Scheme Procedure} tm:year tm +@deffnx {Scheme Procedure} set-tm:year tm val +Year (70-), the year minus 1900. +@end deffn +@deffn {Scheme Procedure} tm:wday tm +@deffnx {Scheme Procedure} set-tm:wday tm val +Day of the week (0-6) with Sunday represented as 0. +@end deffn +@deffn {Scheme Procedure} tm:yday tm +@deffnx {Scheme Procedure} set-tm:yday tm val +Day of the year (0-364, 365 in leap years). +@end deffn +@deffn {Scheme Procedure} tm:isdst tm +@deffnx {Scheme Procedure} set-tm:isdst tm val +Daylight saving indicator (0 for ``no'', greater than 0 for ``yes'', less than +0 for ``unknown''). +@end deffn +@deffn {Scheme Procedure} tm:gmtoff tm +@deffnx {Scheme Procedure} set-tm:gmtoff tm val +Time zone offset in seconds west of @acronym{UTC} (-46800 to 43200). +For example on East coast USA (zone @samp{EST+5}) this would be 18000 +(ie.@: @m{5\times60\times60,5*60*60}) in winter, or 14400 +(ie.@: @m{4\times60\times60,4*60*60}) during daylight savings. + +Note @code{tm:gmtoff} is not the same as @code{tm_gmtoff} in the C +@code{tm} structure. @code{tm_gmtoff} is seconds east and hence the +negative of the value here. +@end deffn +@deffn {Scheme Procedure} tm:zone tm +@deffnx {Scheme Procedure} set-tm:zone tm val +Time zone label (a string), not necessarily unique. +@end deffn +@sp 1 + +@deffn {Scheme Procedure} localtime time [zone] +@deffnx {C Function} scm_localtime (time, zone) +@cindex local time +Return an object representing the broken down components of +@var{time}, an integer like the one returned by +@code{current-time}. The time zone for the calculation is +optionally specified by @var{zone} (a string), otherwise the +@env{TZ} environment variable or the system default is used. +@end deffn + +@deffn {Scheme Procedure} gmtime time +@deffnx {C Function} scm_gmtime (time) +Return an object representing the broken down components of +@var{time}, an integer like the one returned by +@code{current-time}. The values are calculated for @acronym{UTC}. +@end deffn + +@deffn {Scheme Procedure} mktime sbd-time [zone] +@deffnx {C Function} scm_mktime (sbd_time, zone) +For a broken down time object @var{sbd-time}, return a pair the +@code{car} of which is an integer time like @code{current-time}, and +the @code{cdr} of which is a new broken down time with normalized +fields. + +@var{zone} is a timezone string, or the default is the @env{TZ} +environment variable or the system default (@pxref{TZ Variable,, +Specifying the Time Zone with @env{TZ}, libc, GNU C Library Reference +Manual}). @var{sbd-time} is taken to be in that @var{zone}. + +The following fields of @var{sbd-time} are used: @code{tm:year}, +@code{tm:mon}, @code{tm:mday}, @code{tm:hour}, @code{tm:min}, +@code{tm:sec}, @code{tm:isdst}. The values can be outside their usual +ranges. For example @code{tm:hour} normally goes up to 23, but a +value say 33 would mean 9 the following day. + +@code{tm:isdst} in @var{sbd-time} says whether the time given is with +daylight savings or not. This is ignored if @var{zone} doesn't have +any daylight savings adjustment amount. + +The broken down time in the return normalizes the values of +@var{sbd-time} by bringing them into their usual ranges, and using the +actual daylight savings rule for that time in @var{zone} (which may +differ from what @var{sbd-time} had). The easiest way to think of +this is that @var{sbd-time} plus @var{zone} converts to the integer +UTC time, then a @code{localtime} is applied to get the normal +presentation of that time, in @var{zone}. +@end deffn + +@deffn {Scheme Procedure} tzset +@deffnx {C Function} scm_tzset () +Initialize the timezone from the @env{TZ} environment variable +or the system default. It's not usually necessary to call this procedure +since it's done automatically by other procedures that depend on the +timezone. +@end deffn + +@deffn {Scheme Procedure} strftime format tm +@deffnx {C Function} scm_strftime (format, tm) +@cindex time formatting +Return a string which is broken-down time structure @var{tm} formatted +according to the given @var{format} string. + +@var{format} contains field specifications introduced by a @samp{%} +character. See @ref{Formatting Calendar Time,,, libc, The GNU C +Library Reference Manual}, or @samp{man 3 strftime}, for the available +formatting. + +@lisp +(strftime "%c" (localtime (current-time))) +@result{} "Mon Mar 11 20:17:43 2002" +@end lisp + +If @code{setlocale} has been called (@pxref{Locales}), month and day +names are from the current locale and in the locale character set. +@end deffn + +@deffn {Scheme Procedure} strptime format string +@deffnx {C Function} scm_strptime (format, string) +@cindex time parsing +Performs the reverse action to @code{strftime}, parsing +@var{string} according to the specification supplied in +@var{format}. The interpretation of month and day names is +dependent on the current locale. The value returned is a pair. +The @acronym{CAR} has an object with time components +in the form returned by @code{localtime} or @code{gmtime}, +but the time zone components +are not usefully set. +The @acronym{CDR} reports the number of characters from @var{string} +which were used for the conversion. +@end deffn + +@defvar internal-time-units-per-second +The value of this variable is the number of time units per second +reported by the following procedures. +@end defvar + +@deffn {Scheme Procedure} times +@deffnx {C Function} scm_times () +Return an object with information about real and processor +time. The following procedures accept such an object as an +argument and return a selected component: + +@deffn {Scheme Procedure} tms:clock tms +The current real time, expressed as time units relative to an +arbitrary base. +@end deffn +@deffn {Scheme Procedure} tms:utime tms +The CPU time units used by the calling process. +@end deffn +@deffn {Scheme Procedure} tms:stime tms +The CPU time units used by the system on behalf of the calling +process. +@end deffn +@deffn {Scheme Procedure} tms:cutime tms +The CPU time units used by terminated child processes of the +calling process, whose status has been collected (e.g., using +@code{waitpid}). +@end deffn +@deffn {Scheme Procedure} tms:cstime tms +Similarly, the CPU times units used by the system on behalf of +terminated child processes. +@end deffn +@end deffn + +@deffn {Scheme Procedure} get-internal-real-time +@deffnx {C Function} scm_get_internal_real_time () +Return the number of time units since the interpreter was +started. +@end deffn + +@deffn {Scheme Procedure} get-internal-run-time +@deffnx {C Function} scm_get_internal_run_time () +Return the number of time units of processor time used by the +interpreter. Both @emph{system} and @emph{user} time are +included but subprocesses are not. +@end deffn + +@node Runtime Environment +@subsection Runtime Environment + +@deffn {Scheme Procedure} program-arguments +@deffnx {Scheme Procedure} command-line +@deffnx {Scheme Procedure} set-program-arguments +@deffnx {C Function} scm_program_arguments () +@deffnx {C Function} scm_set_program_arguments_scm (lst) +@cindex command line +@cindex program arguments +Get the command line arguments passed to Guile, or set new arguments. + +The arguments are a list of strings, the first of which is the invoked +program name. This is just @nicode{"guile"} (or the executable path) +when run interactively, or it's the script name when running a script +with @option{-s} (@pxref{Invoking Guile}). + +@example +guile -L /my/extra/dir -s foo.scm abc def + +(program-arguments) @result{} ("foo.scm" "abc" "def") +@end example + +@code{set-program-arguments} allows a library module or similar to +modify the arguments, for example to strip options it recognises, +leaving the rest for the mainline. + +The argument list is held in a fluid, which means it's separate for +each thread. Neither the list nor the strings within it are copied at +any point and normally should not be mutated. + +The two names @code{program-arguments} and @code{command-line} are an +historical accident, they both do exactly the same thing. The name +@code{scm_set_program_arguments_scm} has an extra @code{_scm} on the +end to avoid clashing with the C function below. +@end deffn + +@deftypefn {C Function} void scm_set_program_arguments (int argc, char **argv, char *first) +@cindex command line +@cindex program arguments +Set the list of command line arguments for @code{program-arguments} +and @code{command-line} above. + +@var{argv} is an array of null-terminated strings, as in a C +@code{main} function. @var{argc} is the number of strings in +@var{argv}, or if it's negative then a @code{NULL} in @var{argv} marks +its end. + +@var{first} is an extra string put at the start of the arguments, or +@code{NULL} for no such extra. This is a convenient way to pass the +program name after advancing @var{argv} to strip option arguments. +Eg.@: + +@example +@{ + char *progname = argv[0]; + for (argv++; argv[0] != NULL && argv[0][0] == '-'; argv++) + @{ + /* munch option ... */ + @} + /* remaining args for scheme level use */ + scm_set_program_arguments (-1, argv, progname); +@} +@end example + +This sort of thing is often done at startup under +@code{scm_boot_guile} with options handled at the C level removed. +The given strings are all copied, so the C data is not accessed again +once @code{scm_set_program_arguments} returns. +@end deftypefn + +@deffn {Scheme Procedure} getenv name +@deffnx {C Function} scm_getenv (name) +@cindex environment +Looks up the string @var{name} in the current environment. The return +value is @code{#f} unless a string of the form @code{NAME=VALUE} is +found, in which case the string @code{VALUE} is returned. +@end deffn + +@deffn {Scheme Procedure} setenv name value +Modifies the environment of the current process, which is +also the default environment inherited by child processes. + +If @var{value} is @code{#f}, then @var{name} is removed from the +environment. Otherwise, the string @var{name}=@var{value} is added +to the environment, replacing any existing string with name matching +@var{name}. + +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} unsetenv name +Remove variable @var{name} from the environment. The +name can not contain a @samp{=} character. +@end deffn + +@deffn {Scheme Procedure} environ [env] +@deffnx {C Function} scm_environ (env) +If @var{env} is omitted, return the current environment (in the +Unix sense) as a list of strings. Otherwise set the current +environment, which is also the default environment for child +processes, to the supplied list of strings. Each member of +@var{env} should be of the form @var{name}=@var{value} and values of +@var{name} should not be duplicated. If @var{env} is supplied +then the return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} putenv str +@deffnx {C Function} scm_putenv (str) +Modifies the environment of the current process, which is +also the default environment inherited by child processes. + +If @var{str} is of the form @code{NAME=VALUE} then it will be written +directly into the environment, replacing any existing environment string +with +name matching @code{NAME}. If @var{str} does not contain an equal +sign, then any existing string with name matching @var{str} will +be removed. + +The return value is unspecified. +@end deffn + + +@node Processes +@subsection Processes +@cindex processes +@cindex child processes + +@findex cd +@deffn {Scheme Procedure} chdir str +@deffnx {C Function} scm_chdir (str) +@cindex current directory +Change the current working directory to @var{str}. +The return value is unspecified. +@end deffn + +@findex pwd +@deffn {Scheme Procedure} getcwd +@deffnx {C Function} scm_getcwd () +Return the name of the current working directory. +@end deffn + +@deffn {Scheme Procedure} umask [mode] +@deffnx {C Function} scm_umask (mode) +If @var{mode} is omitted, returns a decimal number representing the +current file creation mask. Otherwise the file creation mask is set +to @var{mode} and the previous value is returned. @xref{Setting +Permissions,,Assigning File Permissions,libc,The GNU C Library +Reference Manual}, for more on how to use umasks. + +E.g., @code{(umask #o022)} sets the mask to octal 22/decimal 18. +@end deffn + +@deffn {Scheme Procedure} chroot path +@deffnx {C Function} scm_chroot (path) +Change the root directory to that specified in @var{path}. +This directory will be used for path names beginning with +@file{/}. The root directory is inherited by all children +of the current process. Only the superuser may change the +root directory. +@end deffn + +@deffn {Scheme Procedure} getpid +@deffnx {C Function} scm_getpid () +Return an integer representing the current process ID. +@end deffn + +@deffn {Scheme Procedure} getgroups +@deffnx {C Function} scm_getgroups () +Return a vector of integers representing the current +supplementary group IDs. +@end deffn + +@deffn {Scheme Procedure} getppid +@deffnx {C Function} scm_getppid () +Return an integer representing the process ID of the parent +process. +@end deffn + +@deffn {Scheme Procedure} getuid +@deffnx {C Function} scm_getuid () +Return an integer representing the current real user ID. +@end deffn + +@deffn {Scheme Procedure} getgid +@deffnx {C Function} scm_getgid () +Return an integer representing the current real group ID. +@end deffn + +@deffn {Scheme Procedure} geteuid +@deffnx {C Function} scm_geteuid () +Return an integer representing the current effective user ID. +If the system does not support effective IDs, then the real ID +is returned. @code{(provided? 'EIDs)} reports whether the +system supports effective IDs. +@end deffn + +@deffn {Scheme Procedure} getegid +@deffnx {C Function} scm_getegid () +Return an integer representing the current effective group ID. +If the system does not support effective IDs, then the real ID +is returned. @code{(provided? 'EIDs)} reports whether the +system supports effective IDs. +@end deffn + +@deffn {Scheme Procedure} setgroups vec +@deffnx {C Function} scm_setgroups (vec) +Set the current set of supplementary group IDs to the integers in the +given vector @var{vec}. The return value is unspecified. + +Generally only the superuser can set the process group IDs +(@pxref{Setting Groups, Setting the Group IDs,, libc, The GNU C +Library Reference Manual}). +@end deffn + +@deffn {Scheme Procedure} setuid id +@deffnx {C Function} scm_setuid (id) +Sets both the real and effective user IDs to the integer @var{id}, provided +the process has appropriate privileges. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setgid id +@deffnx {C Function} scm_setgid (id) +Sets both the real and effective group IDs to the integer @var{id}, provided +the process has appropriate privileges. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} seteuid id +@deffnx {C Function} scm_seteuid (id) +Sets the effective user ID to the integer @var{id}, provided the process +has appropriate privileges. If effective IDs are not supported, the +real ID is set instead---@code{(provided? 'EIDs)} reports whether the +system supports effective IDs. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setegid id +@deffnx {C Function} scm_setegid (id) +Sets the effective group ID to the integer @var{id}, provided the process +has appropriate privileges. If effective IDs are not supported, the +real ID is set instead---@code{(provided? 'EIDs)} reports whether the +system supports effective IDs. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} getpgrp +@deffnx {C Function} scm_getpgrp () +Return an integer representing the current process group ID. +This is the @acronym{POSIX} definition, not @acronym{BSD}. +@end deffn + +@deffn {Scheme Procedure} setpgid pid pgid +@deffnx {C Function} scm_setpgid (pid, pgid) +Move the process @var{pid} into the process group @var{pgid}. @var{pid} or +@var{pgid} must be integers: they can be zero to indicate the ID of the +current process. +Fails on systems that do not support job control. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setsid +@deffnx {C Function} scm_setsid () +Creates a new session. The current process becomes the session leader +and is put in a new process group. The process will be detached +from its controlling terminal if it has one. +The return value is an integer representing the new process group ID. +@end deffn + +@deffn {Scheme Procedure} getsid pid +@deffnx {C Function} scm_getsid (pid) +Returns the session ID of process @var{pid}. (The session +ID of a process is the process group ID of its session leader.) +@end deffn + +@deffn {Scheme Procedure} waitpid pid [options] +@deffnx {C Function} scm_waitpid (pid, options) +This procedure collects status information from a child process which +has terminated or (optionally) stopped. Normally it will +suspend the calling process until this can be done. If more than one +child process is eligible then one will be chosen by the operating system. + +The value of @var{pid} determines the behaviour: + +@table @asis +@item @var{pid} greater than 0 +Request status information from the specified child process. +@item @var{pid} equal to -1 or @code{WAIT_ANY} +@vindex WAIT_ANY +Request status information for any child process. +@item @var{pid} equal to 0 or @code{WAIT_MYPGRP} +@vindex WAIT_MYPGRP +Request status information for any child process in the current process +group. +@item @var{pid} less than -1 +Request status information for any child process whose process group ID +is @minus{}@var{pid}. +@end table + +The @var{options} argument, if supplied, should be the bitwise OR of the +values of zero or more of the following variables: + +@defvar WNOHANG +Return immediately even if there are no child processes to be collected. +@end defvar + +@defvar WUNTRACED +Report status information for stopped processes as well as terminated +processes. +@end defvar + +The return value is a pair containing: + +@enumerate +@item +The process ID of the child process, or 0 if @code{WNOHANG} was +specified and no process was collected. +@item +The integer status value. +@end enumerate +@end deffn + +The following three +functions can be used to decode the process status code returned +by @code{waitpid}. + +@deffn {Scheme Procedure} status:exit-val status +@deffnx {C Function} scm_status_exit_val (status) +Return the exit status value, as would be set if a process +ended normally through a call to @code{exit} or @code{_exit}, +if any, otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} status:term-sig status +@deffnx {C Function} scm_status_term_sig (status) +Return the signal number which terminated the process, if any, +otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} status:stop-sig status +@deffnx {C Function} scm_status_stop_sig (status) +Return the signal number which stopped the process, if any, +otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} system [cmd] +@deffnx {C Function} scm_system (cmd) +Execute @var{cmd} using the operating system's ``command +processor''. Under Unix this is usually the default shell +@code{sh}. The value returned is @var{cmd}'s exit status as +returned by @code{waitpid}, which can be interpreted using the +functions above. + +If @code{system} is called without arguments, return a boolean +indicating whether the command processor is available. +@end deffn + +@deffn {Scheme Procedure} system* arg1 arg2 @dots{} +@deffnx {C Function} scm_system_star (args) +Execute the command indicated by @var{arg1} @var{arg2} @enddots{}. The +first element must be a string indicating the command to be executed, +and the remaining items must be strings representing each of the +arguments to that command. + +This function returns the exit status of the command as provided by +@code{waitpid}. This value can be handled with @code{status:exit-val} +and the related functions. + +@code{system*} is similar to @code{system}, but accepts only one +string per-argument, and performs no shell interpretation. The +command is executed using fork and execlp. Accordingly this function +may be safer than @code{system} in situations where shell +interpretation is not required. + +Example: (system* "echo" "foo" "bar") +@end deffn + +@deffn {Scheme Procedure} quit [status] +@deffnx {Scheme Procedure} exit [status] +Terminate the current process with proper unwinding of the Scheme stack. +The exit status zero if @var{status} is not supplied. If @var{status} +is supplied, and it is an integer, that integer is used as the exit +status. If @var{status} is @code{#t} or @code{#f}, the exit status is +@var{EXIT_SUCCESS} or @var{EXIT_FAILURE}, respectively. + +The procedure @code{exit} is an alias of @code{quit}. They have the +same functionality. +@end deffn + +@defvr {Scheme Variable} EXIT_SUCCESS +@defvrx {Scheme Variable} EXIT_FAILURE +These constants represent the standard exit codes for success (zero) or +failure (one.) +@end defvr + +@deffn {Scheme Procedure} primitive-exit [status] +@deffnx {Scheme Procedure} primitive-_exit [status] +@deffnx {C Function} scm_primitive_exit (status) +@deffnx {C Function} scm_primitive__exit (status) +Terminate the current process without unwinding the Scheme stack. The +exit status is @var{status} if supplied, otherwise zero. + +@code{primitive-exit} uses the C @code{exit} function and hence runs +usual C level cleanups (flush output streams, call @code{atexit} +functions, etc, see @ref{Normal Termination,,, libc, The GNU C Library +Reference Manual})). + +@code{primitive-_exit} is the @code{_exit} system call +(@pxref{Termination Internals,,, libc, The GNU C Library Reference +Manual}). This terminates the program immediately, with neither +Scheme-level nor C-level cleanups. + +The typical use for @code{primitive-_exit} is from a child process +created with @code{primitive-fork}. For example in a Gdk program the +child process inherits the X server connection and a C-level +@code{atexit} cleanup which will close that connection. But closing +in the child would upset the protocol in the parent, so +@code{primitive-_exit} should be used to exit without that. +@end deffn + +@deffn {Scheme Procedure} execl filename arg @dots{} +@deffnx {C Function} scm_execl (filename, args) +Executes the file named by @var{filename} as a new process image. +The remaining arguments are supplied to the process; from a C program +they are accessible as the @code{argv} argument to @code{main}. +Conventionally the first @var{arg} is the same as @var{filename}. +All arguments must be strings. + +If @var{arg} is missing, @var{filename} is executed with a null +argument list, which may have system-dependent side-effects. + +This procedure is currently implemented using the @code{execv} system +call, but we call it @code{execl} because of its Scheme calling interface. +@end deffn + +@deffn {Scheme Procedure} execlp filename arg @dots{} +@deffnx {C Function} scm_execlp (filename, args) +Similar to @code{execl}, however if +@var{filename} does not contain a slash +then the file to execute will be located by searching the +directories listed in the @code{PATH} environment variable. + +This procedure is currently implemented using the @code{execvp} system +call, but we call it @code{execlp} because of its Scheme calling interface. +@end deffn + +@deffn {Scheme Procedure} execle filename env arg @dots{} +@deffnx {C Function} scm_execle (filename, env, args) +Similar to @code{execl}, but the environment of the new process is +specified by @var{env}, which must be a list of strings as returned by the +@code{environ} procedure. + +This procedure is currently implemented using the @code{execve} system +call, but we call it @code{execle} because of its Scheme calling interface. +@end deffn + +@deffn {Scheme Procedure} primitive-fork +@deffnx {C Function} scm_fork () +Creates a new ``child'' process by duplicating the current ``parent'' process. +In the child the return value is 0. In the parent the return value is +the integer process ID of the child. + +Note that it is unsafe to fork a process that has multiple threads +running, as only the thread that calls @code{primitive-fork} will +persist in the child. Any resources that other threads held, such as +locked mutexes or open file descriptors, are lost. Indeed, +@acronym{POSIX} specifies that only async-signal-safe procedures are +safe to call after a multithreaded fork, which is a very limited set. +Guile issues a warning if it detects a fork from a multi-threaded +program. + +If you are going to @code{exec} soon after forking, the procedures in +@code{(ice-9 popen)} may be useful to you, as they fork and exec within +an async-signal-safe function carefully written to ensure robust program +behavior, even in the presence of threads. @xref{Pipes}, for more. + +This procedure has been renamed from @code{fork} to avoid a naming conflict +with the scsh fork. +@end deffn + +@deffn {Scheme Procedure} nice incr +@deffnx {C Function} scm_nice (incr) +@cindex process priority +Increment the priority of the current process by @var{incr}. A higher +priority value means that the process runs less often. +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setpriority which who prio +@deffnx {C Function} scm_setpriority (which, who, prio) +@vindex PRIO_PROCESS +@vindex PRIO_PGRP +@vindex PRIO_USER +Set the scheduling priority of the process, process group +or user, as indicated by @var{which} and @var{who}. @var{which} +is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP} +or @code{PRIO_USER}, and @var{who} is interpreted relative to +@var{which} (a process identifier for @code{PRIO_PROCESS}, +process group identifier for @code{PRIO_PGRP}, and a user +identifier for @code{PRIO_USER}. A zero value of @var{who} +denotes the current process, process group, or user. +@var{prio} is a value in the range [@minus{}20,20]. The default +priority is 0; lower priorities (in numerical terms) cause more +favorable scheduling. Sets the priority of all of the specified +processes. Only the super-user may lower priorities. The return +value is not specified. +@end deffn + +@deffn {Scheme Procedure} getpriority which who +@deffnx {C Function} scm_getpriority (which, who) +@vindex PRIO_PROCESS +@vindex PRIO_PGRP +@vindex PRIO_USER +Return the scheduling priority of the process, process group +or user, as indicated by @var{which} and @var{who}. @var{which} +is one of the variables @code{PRIO_PROCESS}, @code{PRIO_PGRP} +or @code{PRIO_USER}, and @var{who} should be interpreted depending on +@var{which} (a process identifier for @code{PRIO_PROCESS}, +process group identifier for @code{PRIO_PGRP}, and a user +identifier for @code{PRIO_USER}). A zero value of @var{who} +denotes the current process, process group, or user. Return +the highest priority (lowest numerical value) of any of the +specified processes. +@end deffn + +@cindex affinity, CPU + +@deffn {Scheme Procedure} getaffinity pid +@deffnx {C Function} scm_getaffinity (pid) +Return a bitvector representing the CPU affinity mask for +process @var{pid}. Each CPU the process has affinity with +has its corresponding bit set in the returned bitvector. +The number of bits set is a good estimate of how many CPUs +Guile can use without stepping on other processes' toes. + +Currently this procedure is only defined on GNU variants +(@pxref{CPU Affinity, @code{sched_getaffinity},, libc, The +GNU C Library Reference Manual}). +@end deffn + +@deffn {Scheme Procedure} setaffinity pid mask +@deffnx {C Function} scm_setaffinity (pid, mask) +Install the CPU affinity mask @var{mask}, a bitvector, for +the process or thread with ID @var{pid}. The return value +is unspecified. + +Currently this procedure is only defined on GNU variants +(@pxref{CPU Affinity, @code{sched_setaffinity},, libc, The +GNU C Library Reference Manual}). +@end deffn + +@xref{Threads}, for information on how get the number of processors +available on a system. + + +@node Signals +@subsection Signals +@cindex signal + +The following procedures raise, handle and wait for signals. + +Scheme code signal handlers are run via an async (@pxref{Asyncs}), so +they're called in the handler's thread at the next safe opportunity. +Generally this is after any currently executing primitive procedure +finishes (which could be a long time for primitives that wait for an +external event). + +@deffn {Scheme Procedure} kill pid sig +@deffnx {C Function} scm_kill (pid, sig) +Sends a signal to the specified process or group of processes. + +@var{pid} specifies the processes to which the signal is sent: + +@table @asis +@item @var{pid} greater than 0 +The process whose identifier is @var{pid}. +@item @var{pid} equal to 0 +All processes in the current process group. +@item @var{pid} less than -1 +The process group whose identifier is -@var{pid} +@item @var{pid} equal to -1 +If the process is privileged, all processes except for some special +system processes. Otherwise, all processes with the current effective +user ID. +@end table + +@var{sig} should be specified using a variable corresponding to +the Unix symbolic name, e.g., + +@defvar SIGHUP +Hang-up signal. +@end defvar + +@defvar SIGINT +Interrupt signal. +@end defvar + +A full list of signals on the GNU system may be found in @ref{Standard +Signals,,,libc,The GNU C Library Reference Manual}. +@end deffn + +@deffn {Scheme Procedure} raise sig +@deffnx {C Function} scm_raise (sig) +Sends a specified signal @var{sig} to the current process, where +@var{sig} is as described for the @code{kill} procedure. +@end deffn + +@deffn {Scheme Procedure} sigaction signum [handler [flags [thread]]] +@deffnx {C Function} scm_sigaction (signum, handler, flags) +@deffnx {C Function} scm_sigaction_for_thread (signum, handler, flags, thread) +Install or report the signal handler for a specified signal. + +@var{signum} is the signal number, which can be specified using the value +of variables such as @code{SIGINT}. + +If @var{handler} is omitted, @code{sigaction} returns a pair: the +@acronym{CAR} is the current signal hander, which will be either an +integer with the value @code{SIG_DFL} (default action) or +@code{SIG_IGN} (ignore), or the Scheme procedure which handles the +signal, or @code{#f} if a non-Scheme procedure handles the signal. +The @acronym{CDR} contains the current @code{sigaction} flags for the +handler. + +If @var{handler} is provided, it is installed as the new handler for +@var{signum}. @var{handler} can be a Scheme procedure taking one +argument, or the value of @code{SIG_DFL} (default action) or +@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler +was installed before @code{sigaction} was first used. When a scheme +procedure has been specified, that procedure will run in the given +@var{thread}. When no thread has been given, the thread that made this +call to @code{sigaction} is used. + +@var{flags} is a @code{logior} (@pxref{Bitwise Operations}) of the +following (where provided by the system), or @code{0} for none. + +@defvar SA_NOCLDSTOP +By default, @code{SIGCHLD} is signalled when a child process stops +(ie.@: receives @code{SIGSTOP}), and when a child process terminates. +With the @code{SA_NOCLDSTOP} flag, @code{SIGCHLD} is only signalled +for termination, not stopping. + +@code{SA_NOCLDSTOP} has no effect on signals other than +@code{SIGCHLD}. +@end defvar + +@defvar SA_RESTART +If a signal occurs while in a system call, deliver the signal then +restart the system call (as opposed to returning an @code{EINTR} error +from that call). +@end defvar + +Guile handles signals asynchronously. When it receives a signal, the +synchronous signal handler just records the fact that a signal was +received and sets a flag to tell the relevant Guile thread that it has a +pending signal. When the Guile thread checks the pending-interrupt +flag, it will arrange to run the asynchronous part of the signal +handler, which is the handler attached by @code{sigaction}. + +This strategy has some perhaps-unexpected interactions with the +@code{SA_RESTART} flag, though: because the synchronous handler doesn't +do very much, and notably it doesn't run the Guile handler, it's +impossible to interrupt a thread stuck in a long-running system call via +a signal handler that is installed with @code{SA_RESTART}: the +synchronous handler just records the pending interrupt, but then the +system call resumes and Guile doesn't have a chance to actually check +the flag and run the asynchronous handler. That's just how it is. + +The return value is a pair with information about the old handler as +described above. + +This interface does not provide access to the ``signal blocking'' +facility. Maybe this is not needed, since the thread support may +provide solutions to the problem of consistent access to data +structures. +@end deffn + +@deffn {Scheme Procedure} restore-signals +@deffnx {C Function} scm_restore_signals () +Return all signal handlers to the values they had before any call to +@code{sigaction} was made. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} alarm i +@deffnx {C Function} scm_alarm (i) +Set a timer to raise a @code{SIGALRM} signal after the specified +number of seconds (an integer). It's advisable to install a signal +handler for +@code{SIGALRM} beforehand, since the default action is to terminate +the process. + +The return value indicates the time remaining for the previous alarm, +if any. The new value replaces the previous alarm. If there was +no previous alarm, the return value is zero. +@end deffn + +@deffn {Scheme Procedure} pause +@deffnx {C Function} scm_pause () +Pause the current process (thread?) until a signal arrives whose +action is to either terminate the current process or invoke a +handler procedure. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} sleep secs +@deffnx {Scheme Procedure} usleep usecs +@deffnx {C Function} scm_sleep (secs) +@deffnx {C Function} scm_usleep (usecs) +Wait the given period @var{secs} seconds or @var{usecs} microseconds +(both integers). If a signal arrives the wait stops and the return +value is the time remaining, in seconds or microseconds respectively. +If the period elapses with no signal the return is zero. + +On most systems the process scheduler is not microsecond accurate and +the actual period slept by @code{usleep} might be rounded to a system +clock tick boundary, which might be 10 milliseconds for instance. + +See @code{scm_std_sleep} and @code{scm_std_usleep} for equivalents at +the C level (@pxref{Blocking}). +@end deffn + +@deffn {Scheme Procedure} getitimer which_timer +@deffnx {Scheme Procedure} setitimer which_timer interval_seconds interval_microseconds value_seconds value_microseconds +@deffnx {C Function} scm_getitimer (which_timer) +@deffnx {C Function} scm_setitimer (which_timer, interval_seconds, interval_microseconds, value_seconds, value_microseconds) +Get or set the periods programmed in certain system timers. + +These timers have two settings. The first setting, the interval, is the +value at which the timer will be reset when the current timer expires. +The second is the current value of the timer, indicating when the next +expiry will be signalled. + +@var{which_timer} is one of the following values: + +@defvar ITIMER_REAL +A real-time timer, counting down elapsed real time. At zero it raises +@code{SIGALRM}. This is like @code{alarm} above, but with a higher +resolution period. +@end defvar + +@defvar ITIMER_VIRTUAL +A virtual-time timer, counting down while the current process is +actually using CPU. At zero it raises @code{SIGVTALRM}. +@end defvar + +@defvar ITIMER_PROF +A profiling timer, counting down while the process is running (like +@code{ITIMER_VIRTUAL}) and also while system calls are running on the +process's behalf. At zero it raises a @code{SIGPROF}. + +This timer is intended for profiling where a program is spending its +time (by looking where it is when the timer goes off). +@end defvar + +@code{getitimer} returns the restart timer value and its current value, +as a list containing two pairs. Each pair is a time in seconds and +microseconds: @code{((@var{interval_secs} . @var{interval_usecs}) +(@var{value_secs} . @var{value_usecs}))}. + +@code{setitimer} sets the timer values similarly, in seconds and +microseconds (which must be integers). The interval value can be zero +to have the timer run down just once. The return value is the timer's +previous setting, in the same form as @code{getitimer} returns. + +@example +(setitimer ITIMER_REAL + 5 500000 ;; Raise SIGALRM every 5.5 seconds + 2 0) ;; with the first SIGALRM in 2 seconds +@end example + +Although the timers are programmed in microseconds, the actual +accuracy might not be that high. + +Note that @code{ITIMER_PROF} and @code{ITIMER_VIRTUAL} are not +functional on all platforms and may always error when called. +@code{(provided? 'ITIMER_PROF)} and @code{(provided? 'ITIMER_VIRTUAL)} +can be used to test if the those itimers are supported on the given +host. @code{ITIMER_REAL} is supported on all platforms that support +@code{setitimer}. +@end deffn + + +@node Terminals and Ptys +@subsection Terminals and Ptys + +@deffn {Scheme Procedure} isatty? port +@deffnx {C Function} scm_isatty_p (port) +@cindex terminal +Return @code{#t} if @var{port} is using a serial non--file +device, otherwise @code{#f}. +@end deffn + +@deffn {Scheme Procedure} ttyname port +@deffnx {C Function} scm_ttyname (port) +@cindex terminal +Return a string with the name of the serial terminal device +underlying @var{port}. +@end deffn + +@deffn {Scheme Procedure} ctermid +@deffnx {C Function} scm_ctermid () +@cindex terminal +Return a string containing the file name of the controlling +terminal for the current process. +@end deffn + +@deffn {Scheme Procedure} tcgetpgrp port +@deffnx {C Function} scm_tcgetpgrp (port) +@cindex process group +Return the process group ID of the foreground process group +associated with the terminal open on the file descriptor +underlying @var{port}. + +If there is no foreground process group, the return value is a +number greater than 1 that does not match the process group ID +of any existing process group. This can happen if all of the +processes in the job that was formerly the foreground job have +terminated, and no other job has yet been moved into the +foreground. +@end deffn + +@deffn {Scheme Procedure} tcsetpgrp port pgid +@deffnx {C Function} scm_tcsetpgrp (port, pgid) +@cindex process group +Set the foreground process group ID for the terminal used by the file +descriptor underlying @var{port} to the integer @var{pgid}. +The calling process +must be a member of the same session as @var{pgid} and must have the same +controlling terminal. The return value is unspecified. +@end deffn + +@node Pipes +@subsection Pipes +@cindex pipe + +The following procedures are similar to the @code{popen} and +@code{pclose} system routines. The code is in a separate ``popen'' +module@footnote{This module is only available on systems where the +@code{popen} feature is provided (@pxref{Common Feature Symbols}).}: + +@lisp +(use-modules (ice-9 popen)) +@end lisp + +@findex popen +@deffn {Scheme Procedure} open-pipe command mode +@deffnx {Scheme Procedure} open-pipe* mode prog [args...] +Execute a command in a subprocess, with a pipe to it or from it, or +with pipes in both directions. + +@code{open-pipe} runs the shell @var{command} using @samp{/bin/sh -c}. +@code{open-pipe*} executes @var{prog} directly, with the optional +@var{args} arguments (all strings). + +@var{mode} should be one of the following values. @code{OPEN_READ} is +an input pipe, ie.@: to read from the subprocess. @code{OPEN_WRITE} +is an output pipe, ie.@: to write to it. + +@defvar OPEN_READ +@defvarx OPEN_WRITE +@defvarx OPEN_BOTH +@end defvar + +For an input pipe, the child's standard output is the pipe and +standard input is inherited from @code{current-input-port}. For an +output pipe, the child's standard input is the pipe and standard +output is inherited from @code{current-output-port}. In all cases +the child's standard error is inherited from +@code{current-error-port} (@pxref{Default Ports}). + +If those @code{current-X-ports} are not files of some kind, and hence +don't have file descriptors for the child, then @file{/dev/null} is +used instead. + +Care should be taken with @code{OPEN_BOTH}, a deadlock will occur if +both parent and child are writing, and waiting until the write completes +before doing any reading. Each direction has @code{PIPE_BUF} bytes of +buffering (@pxref{Buffering}), which will be enough for small writes, +but not for say putting a big file through a filter. +@end deffn + +@deffn {Scheme Procedure} open-input-pipe command +Equivalent to @code{open-pipe} with mode @code{OPEN_READ}. + +@lisp +(let* ((port (open-input-pipe "date --utc")) + (str (read-line port))) + (close-pipe port) + str) +@result{} "Mon Mar 11 20:10:44 UTC 2002" +@end lisp +@end deffn + +@deffn {Scheme Procedure} open-output-pipe command +Equivalent to @code{open-pipe} with mode @code{OPEN_WRITE}. + +@lisp +(let ((port (open-output-pipe "lpr"))) + (display "Something for the line printer.\n" port) + (if (not (eqv? 0 (status:exit-val (close-pipe port)))) + (error "Cannot print"))) +@end lisp +@end deffn + +@deffn {Scheme Procedure} open-input-output-pipe command +Equivalent to @code{open-pipe} with mode @code{OPEN_BOTH}. +@end deffn + +@findex pclose +@deffn {Scheme Procedure} close-pipe port +Close a pipe created by @code{open-pipe}, wait for the process to +terminate, and return the wait status code. The status is as per +@code{waitpid} and can be decoded with @code{status:exit-val} etc +(@pxref{Processes}) +@end deffn + +@sp 1 +@code{waitpid WAIT_ANY} should not be used when pipes are open, since +it can reap a pipe's child process, causing an error from a subsequent +@code{close-pipe}. + +@code{close-port} (@pxref{Ports}) can close a pipe, but it doesn't reap +the child process. + +The garbage collector will close a pipe no longer in use, and reap the +child process with @code{waitpid}. If the child hasn't yet terminated +the garbage collector doesn't block, but instead checks again in the +next GC. + +Many systems have per-user and system-wide limits on the number of +processes, and a system-wide limit on the number of pipes, so pipes +should be closed explicitly when no longer needed, rather than letting +the garbage collector pick them up at some later time. + + +@node Networking +@subsection Networking +@cindex network + +@menu +* Network Address Conversion:: +* Network Databases:: +* Network Socket Address:: +* Network Sockets and Communication:: +* Internet Socket Examples:: +@end menu + +@node Network Address Conversion +@subsubsection Network Address Conversion +@cindex network address + +This section describes procedures which convert internet addresses +between numeric and string formats. + +@subsubheading IPv4 Address Conversion +@cindex IPv4 + +An IPv4 Internet address is a 4-byte value, represented in Guile as an +integer in host byte order, so that say ``0.0.0.1'' is 1, or +``1.0.0.0'' is 16777216. + +Some underlying C functions use network byte order for addresses, +Guile converts as necessary so that at the Scheme level its host byte +order everywhere. + +@defvar INADDR_ANY +For a server, this can be used with @code{bind} (@pxref{Network +Sockets and Communication}) to allow connections from any interface on +the machine. +@end defvar + +@defvar INADDR_BROADCAST +The broadcast address on the local network. +@end defvar + +@defvar INADDR_LOOPBACK +The address of the local host using the loopback device, ie.@: +@samp{127.0.0.1}. +@end defvar + +@c INADDR_NONE is defined in the code, but serves no purpose. +@c inet_addr() returns it as an error indication, but that function +@c isn't provided, for the good reason that inet_aton() does the same +@c job and gives an unambiguous error indication. (INADDR_NONE is a +@c valid 4-byte value, in glibc it's the same as INADDR_BROADCAST.) +@c +@c @defvar INADDR_NONE +@c No address. +@c @end defvar + +@deffn {Scheme Procedure} inet-aton address +@deffnx {C Function} scm_inet_aton (address) +This function is deprecated in favor of @code{inet-pton}. + +Convert an IPv4 Internet address from printable string +(dotted decimal notation) to an integer. E.g., + +@lisp +(inet-aton "127.0.0.1") @result{} 2130706433 +@end lisp +@end deffn + +@deffn {Scheme Procedure} inet-ntoa inetid +@deffnx {C Function} scm_inet_ntoa (inetid) +This function is deprecated in favor of @code{inet-ntop}. + +Convert an IPv4 Internet address to a printable +(dotted decimal notation) string. E.g., + +@lisp +(inet-ntoa 2130706433) @result{} "127.0.0.1" +@end lisp +@end deffn + +@deffn {Scheme Procedure} inet-netof address +@deffnx {C Function} scm_inet_netof (address) +Return the network number part of the given IPv4 +Internet address. E.g., + +@lisp +(inet-netof 2130706433) @result{} 127 +@end lisp +@end deffn + +@deffn {Scheme Procedure} inet-lnaof address +@deffnx {C Function} scm_lnaof (address) +Return the local-address-with-network part of the given +IPv4 Internet address, using the obsolete class A/B/C system. +E.g., + +@lisp +(inet-lnaof 2130706433) @result{} 1 +@end lisp +@end deffn + +@deffn {Scheme Procedure} inet-makeaddr net lna +@deffnx {C Function} scm_inet_makeaddr (net, lna) +Make an IPv4 Internet address by combining the network number +@var{net} with the local-address-within-network number +@var{lna}. E.g., + +@lisp +(inet-makeaddr 127 1) @result{} 2130706433 +@end lisp +@end deffn + +@subsubheading IPv6 Address Conversion +@cindex IPv6 + +An IPv6 Internet address is a 16-byte value, represented in Guile as +an integer in host byte order, so that say ``::1'' is 1. + +@deffn {Scheme Procedure} inet-ntop family address +@deffnx {C Function} scm_inet_ntop (family, address) +Convert a network address from an integer to a printable string. +@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g., + +@lisp +(inet-ntop AF_INET 2130706433) @result{} "127.0.0.1" +(inet-ntop AF_INET6 (- (expt 2 128) 1)) + @result{} "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" +@end lisp +@end deffn + +@deffn {Scheme Procedure} inet-pton family address +@deffnx {C Function} scm_inet_pton (family, address) +Convert a string containing a printable network address to an integer +address. @var{family} can be @code{AF_INET} or @code{AF_INET6}. +E.g., + +@lisp +(inet-pton AF_INET "127.0.0.1") @result{} 2130706433 +(inet-pton AF_INET6 "::1") @result{} 1 +@end lisp +@end deffn + + +@node Network Databases +@subsubsection Network Databases +@cindex network database + +This section describes procedures which query various network databases. +Care should be taken when using the database routines since they are not +reentrant. + +@subsubheading @code{getaddrinfo} + +@cindex @code{addrinfo} object type +@cindex host name lookup +@cindex service name lookup + +The @code{getaddrinfo} procedure maps host and service names to socket addresses +and associated information in a protocol-independent way. + +@deffn {Scheme Procedure} getaddrinfo name service [hint_flags [hint_family [hint_socktype [hint_protocol]]]] +@deffnx {C Function} scm_getaddrinfo (name, service, hint_flags, hint_family, hint_socktype, hint_protocol) +Return a list of @code{addrinfo} structures containing +a socket address and associated information for host @var{name} +and/or @var{service} to be used in creating a socket with +which to address the specified service. + +@example +(let* ((ai (car (getaddrinfo "www.gnu.org" "http"))) + (s (socket (addrinfo:fam ai) (addrinfo:socktype ai) + (addrinfo:protocol ai)))) + (connect s (addrinfo:addr ai)) + s) +@end example + +When @var{service} is omitted or is @code{#f}, return +network-level addresses for @var{name}. When @var{name} +is @code{#f} @var{service} must be provided and service +locations local to the caller are returned. + +Additional hints can be provided. When specified, +@var{hint_flags} should be a bitwise-or of zero or more +constants among the following: + +@table @code +@item AI_PASSIVE +Socket address is intended for @code{bind}. + +@item AI_CANONNAME +Request for canonical host name, available via +@code{addrinfo:canonname}. This makes sense mainly when +DNS lookups are involved. + +@item AI_NUMERICHOST +Specifies that @var{name} is a numeric host address string +(e.g., @code{"127.0.0.1"}), meaning that name resolution +will not be used. + +@item AI_NUMERICSERV +Likewise, specifies that @var{service} is a numeric port +string (e.g., @code{"80"}). + +@item AI_ADDRCONFIG +Return only addresses configured on the local system It is +highly recommended to provide this flag when the returned +socket addresses are to be used to make connections; +otherwise, some of the returned addresses could be unreachable +or use a protocol that is not supported. + +@item AI_V4MAPPED +When looking up IPv6 addresses, return mapped IPv4 addresses if +there is no IPv6 address available at all. + +@item AI_ALL +If this flag is set along with @code{AI_V4MAPPED} when looking up IPv6 +addresses, return all IPv6 addresses as well as all IPv4 addresses, the latter +mapped to IPv6 format. +@end table + +When given, @var{hint_family} should specify the requested +address family, e.g., @code{AF_INET6}. Similarly, +@var{hint_socktype} should specify the requested socket type +(e.g., @code{SOCK_DGRAM}), and @var{hint_protocol} should +specify the requested protocol (its value is interpreted +as in calls to @code{socket}). + +On error, an exception with key @code{getaddrinfo-error} is +thrown, with an error code (an integer) as its argument: + +@example +(catch 'getaddrinfo-error + (lambda () + (getaddrinfo "www.gnu.org" "gopher")) + (lambda (key errcode) + (cond ((= errcode EAI_SERVICE) + (display "doesn't know about Gopher!\n")) + ((= errcode EAI_NONAME) + (display "www.gnu.org not found\\n")) + (else + (format #t "something wrong: ~a\n" + (gai-strerror errcode)))))) +@end example + +Error codes are: + +@table @code +@item EAI_AGAIN +The name or service could not be resolved at this time. Future +attempts may succeed. + +@item EAI_BADFLAGS +@var{hint_flags} contains an invalid value. + +@item EAI_FAIL +A non-recoverable error occurred when attempting to +resolve the name. + +@item EAI_FAMILY +@var{hint_family} was not recognized. + +@item EAI_NONAME +Either @var{name} does not resolve for the supplied parameters, +or neither @var{name} nor @var{service} were supplied. + +@item EAI_NODATA +This non-POSIX error code can be returned on some systems (GNU +and Darwin, at least), for example when @var{name} is known +but requests that were made turned out no data. Error handling +code should be prepared to handle it when it is defined. + +@item EAI_SERVICE +@var{service} was not recognized for the specified socket type. + +@item EAI_SOCKTYPE +@var{hint_socktype} was not recognized. + +@item EAI_SYSTEM +A system error occurred. In C, the error code can be found in +@code{errno}; this value is not accessible from Scheme, but in +practice it provides little information about the actual error +cause. +@c See <http://bugs.gnu.org/13958>. +@end table + +Users are encouraged to read the +@url{http://www.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html, +"POSIX specification} for more details. +@end deffn + +The following procedures take an @code{addrinfo} object as returned by +@code{getaddrinfo}: + +@deffn {Scheme Procedure} addrinfo:flags ai +Return flags for @var{ai} as a bitwise or of @code{AI_} values (see above). +@end deffn + +@deffn {Scheme Procedure} addrinfo:fam ai +Return the address family of @var{ai} (a @code{AF_} value). +@end deffn + +@deffn {Scheme Procedure} addrinfo:socktype ai +Return the socket type for @var{ai} (a @code{SOCK_} value). +@end deffn + +@deffn {Scheme Procedure} addrinfo:protocol ai +Return the protocol of @var{ai}. +@end deffn + +@deffn {Scheme Procedure} addrinfo:addr ai +Return the socket address associated with @var{ai} as a @code{sockaddr} +object (@pxref{Network Socket Address}). +@end deffn + +@deffn {Scheme Procedure} addrinfo:canonname ai +Return a string for the canonical name associated with @var{ai} if +the @code{AI_CANONNAME} flag was supplied. +@end deffn + +@subsubheading The Host Database +@cindex @file{/etc/hosts} +@cindex network database + +A @dfn{host object} is a structure that represents what is known about a +network host, and is the usual way of representing a system's network +identity inside software. + +The following functions accept a host object and return a selected +component: + +@deffn {Scheme Procedure} hostent:name host +The ``official'' hostname for @var{host}. +@end deffn +@deffn {Scheme Procedure} hostent:aliases host +A list of aliases for @var{host}. +@end deffn +@deffn {Scheme Procedure} hostent:addrtype host +The host address type, one of the @code{AF} constants, such as +@code{AF_INET} or @code{AF_INET6}. +@end deffn +@deffn {Scheme Procedure} hostent:length host +The length of each address for @var{host}, in bytes. +@end deffn +@deffn {Scheme Procedure} hostent:addr-list host +The list of network addresses associated with @var{host}. For +@code{AF_INET} these are integer IPv4 address (@pxref{Network Address +Conversion}). +@end deffn + +The following procedures can be used to search the host database. However, +@code{getaddrinfo} should be preferred over them since it's more generic and +thread-safe. + +@deffn {Scheme Procedure} gethost [host] +@deffnx {Scheme Procedure} gethostbyname hostname +@deffnx {Scheme Procedure} gethostbyaddr address +@deffnx {C Function} scm_gethost (host) +Look up a host by name or address, returning a host object. The +@code{gethost} procedure will accept either a string name or an integer +address; if given no arguments, it behaves like @code{gethostent} (see +below). If a name or address is supplied but the address can not be +found, an error will be thrown to one of the keys: +@code{host-not-found}, @code{try-again}, @code{no-recovery} or +@code{no-data}, corresponding to the equivalent @code{h_error} values. +Unusual conditions may result in errors thrown to the +@code{system-error} or @code{misc_error} keys. + +@lisp +(gethost "www.gnu.org") +@result{} #("www.gnu.org" () 2 4 (3353880842)) + +(gethostbyname "www.emacs.org") +@result{} #("emacs.org" ("www.emacs.org") 2 4 (1073448978)) +@end lisp +@end deffn + +The following procedures may be used to step through the host +database from beginning to end. + +@deffn {Scheme Procedure} sethostent [stayopen] +Initialize an internal stream from which host objects may be read. This +procedure must be called before any calls to @code{gethostent}, and may +also be called afterward to reset the host entry stream. If +@var{stayopen} is supplied and is not @code{#f}, the database is not +closed by subsequent @code{gethostbyname} or @code{gethostbyaddr} calls, +possibly giving an efficiency gain. +@end deffn + +@deffn {Scheme Procedure} gethostent +Return the next host object from the host database, or @code{#f} if +there are no more hosts to be found (or an error has been encountered). +This procedure may not be used before @code{sethostent} has been called. +@end deffn + +@deffn {Scheme Procedure} endhostent +Close the stream used by @code{gethostent}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} sethost [stayopen] +@deffnx {C Function} scm_sethost (stayopen) +If @var{stayopen} is omitted, this is equivalent to @code{endhostent}. +Otherwise it is equivalent to @code{sethostent stayopen}. +@end deffn + +@subsubheading The Network Database +@cindex network database + +The following functions accept an object representing a network +and return a selected component: + +@deffn {Scheme Procedure} netent:name net +The ``official'' network name. +@end deffn +@deffn {Scheme Procedure} netent:aliases net +A list of aliases for the network. +@end deffn +@deffn {Scheme Procedure} netent:addrtype net +The type of the network number. Currently, this returns only +@code{AF_INET}. +@end deffn +@deffn {Scheme Procedure} netent:net net +The network number. +@end deffn + +The following procedures are used to search the network database: + +@deffn {Scheme Procedure} getnet [net] +@deffnx {Scheme Procedure} getnetbyname net-name +@deffnx {Scheme Procedure} getnetbyaddr net-number +@deffnx {C Function} scm_getnet (net) +Look up a network by name or net number in the network database. The +@var{net-name} argument must be a string, and the @var{net-number} +argument must be an integer. @code{getnet} will accept either type of +argument, behaving like @code{getnetent} (see below) if no arguments are +given. +@end deffn + +The following procedures may be used to step through the network +database from beginning to end. + +@deffn {Scheme Procedure} setnetent [stayopen] +Initialize an internal stream from which network objects may be read. This +procedure must be called before any calls to @code{getnetent}, and may +also be called afterward to reset the net entry stream. If +@var{stayopen} is supplied and is not @code{#f}, the database is not +closed by subsequent @code{getnetbyname} or @code{getnetbyaddr} calls, +possibly giving an efficiency gain. +@end deffn + +@deffn {Scheme Procedure} getnetent +Return the next entry from the network database. +@end deffn + +@deffn {Scheme Procedure} endnetent +Close the stream used by @code{getnetent}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setnet [stayopen] +@deffnx {C Function} scm_setnet (stayopen) +If @var{stayopen} is omitted, this is equivalent to @code{endnetent}. +Otherwise it is equivalent to @code{setnetent stayopen}. +@end deffn + +@subsubheading The Protocol Database +@cindex @file{/etc/protocols} +@cindex protocols +@cindex network protocols + +The following functions accept an object representing a protocol +and return a selected component: + +@deffn {Scheme Procedure} protoent:name protocol +The ``official'' protocol name. +@end deffn +@deffn {Scheme Procedure} protoent:aliases protocol +A list of aliases for the protocol. +@end deffn +@deffn {Scheme Procedure} protoent:proto protocol +The protocol number. +@end deffn + +The following procedures are used to search the protocol database: + +@deffn {Scheme Procedure} getproto [protocol] +@deffnx {Scheme Procedure} getprotobyname name +@deffnx {Scheme Procedure} getprotobynumber number +@deffnx {C Function} scm_getproto (protocol) +Look up a network protocol by name or by number. @code{getprotobyname} +takes a string argument, and @code{getprotobynumber} takes an integer +argument. @code{getproto} will accept either type, behaving like +@code{getprotoent} (see below) if no arguments are supplied. +@end deffn + +The following procedures may be used to step through the protocol +database from beginning to end. + +@deffn {Scheme Procedure} setprotoent [stayopen] +Initialize an internal stream from which protocol objects may be read. This +procedure must be called before any calls to @code{getprotoent}, and may +also be called afterward to reset the protocol entry stream. If +@var{stayopen} is supplied and is not @code{#f}, the database is not +closed by subsequent @code{getprotobyname} or @code{getprotobynumber} calls, +possibly giving an efficiency gain. +@end deffn + +@deffn {Scheme Procedure} getprotoent +Return the next entry from the protocol database. +@end deffn + +@deffn {Scheme Procedure} endprotoent +Close the stream used by @code{getprotoent}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setproto [stayopen] +@deffnx {C Function} scm_setproto (stayopen) +If @var{stayopen} is omitted, this is equivalent to @code{endprotoent}. +Otherwise it is equivalent to @code{setprotoent stayopen}. +@end deffn + +@subsubheading The Service Database +@cindex @file{/etc/services} +@cindex services +@cindex network services + +The following functions accept an object representing a service +and return a selected component: + +@deffn {Scheme Procedure} servent:name serv +The ``official'' name of the network service. +@end deffn +@deffn {Scheme Procedure} servent:aliases serv +A list of aliases for the network service. +@end deffn +@deffn {Scheme Procedure} servent:port serv +The Internet port used by the service. +@end deffn +@deffn {Scheme Procedure} servent:proto serv +The protocol used by the service. A service may be listed many times +in the database under different protocol names. +@end deffn + +The following procedures are used to search the service database: + +@deffn {Scheme Procedure} getserv [name [protocol]] +@deffnx {Scheme Procedure} getservbyname name protocol +@deffnx {Scheme Procedure} getservbyport port protocol +@deffnx {C Function} scm_getserv (name, protocol) +Look up a network service by name or by service number, and return a +network service object. The @var{protocol} argument specifies the name +of the desired protocol; if the protocol found in the network service +database does not match this name, a system error is signalled. + +The @code{getserv} procedure will take either a service name or number +as its first argument; if given no arguments, it behaves like +@code{getservent} (see below). + +@lisp +(getserv "imap" "tcp") +@result{} #("imap2" ("imap") 143 "tcp") + +(getservbyport 88 "udp") +@result{} #("kerberos" ("kerberos5" "krb5") 88 "udp") +@end lisp +@end deffn + +The following procedures may be used to step through the service +database from beginning to end. + +@deffn {Scheme Procedure} setservent [stayopen] +Initialize an internal stream from which service objects may be read. This +procedure must be called before any calls to @code{getservent}, and may +also be called afterward to reset the service entry stream. If +@var{stayopen} is supplied and is not @code{#f}, the database is not +closed by subsequent @code{getservbyname} or @code{getservbyport} calls, +possibly giving an efficiency gain. +@end deffn + +@deffn {Scheme Procedure} getservent +Return the next entry from the services database. +@end deffn + +@deffn {Scheme Procedure} endservent +Close the stream used by @code{getservent}. The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} setserv [stayopen] +@deffnx {C Function} scm_setserv (stayopen) +If @var{stayopen} is omitted, this is equivalent to @code{endservent}. +Otherwise it is equivalent to @code{setservent stayopen}. +@end deffn + + +@node Network Socket Address +@subsubsection Network Socket Address +@cindex socket address +@cindex network socket address +@tpindex Socket address + +A @dfn{socket address} object identifies a socket endpoint for +communication. In the case of @code{AF_INET} for instance, the socket +address object comprises the host address (or interface on the host) +and a port number which specifies a particular open socket in a +running client or server process. A socket address object can be +created with, + +@deffn {Scheme Procedure} make-socket-address AF_INET ipv4addr port +@deffnx {Scheme Procedure} make-socket-address AF_INET6 ipv6addr port [flowinfo [scopeid]] +@deffnx {Scheme Procedure} make-socket-address AF_UNIX path +@deffnx {C Function} scm_make_socket_address (family, address, arglist) +Return a new socket address object. The first argument is the address +family, one of the @code{AF} constants, then the arguments vary +according to the family. + +For @code{AF_INET} the arguments are an IPv4 network address number +(@pxref{Network Address Conversion}), and a port number. + +For @code{AF_INET6} the arguments are an IPv6 network address number +and a port number. Optional @var{flowinfo} and @var{scopeid} +arguments may be given (both integers, default 0). + +For @code{AF_UNIX} the argument is a filename (a string). + +The C function @code{scm_make_socket_address} takes the @var{family} +and @var{address} arguments directly, then @var{arglist} is a list of +further arguments, being the port for IPv4, port and optional flowinfo +and scopeid for IPv6, or the empty list @code{SCM_EOL} for Unix +domain. +@end deffn + +@noindent +The following functions access the fields of a socket address object, + +@deffn {Scheme Procedure} sockaddr:fam sa +Return the address family from socket address object @var{sa}. This +is one of the @code{AF} constants (e.g.@: @code{AF_INET}). +@end deffn + +@deffn {Scheme Procedure} sockaddr:path sa +For an @code{AF_UNIX} socket address object @var{sa}, return the +filename. +@end deffn + +@deffn {Scheme Procedure} sockaddr:addr sa +For an @code{AF_INET} or @code{AF_INET6} socket address object +@var{sa}, return the network address number. +@end deffn + +@deffn {Scheme Procedure} sockaddr:port sa +For an @code{AF_INET} or @code{AF_INET6} socket address object +@var{sa}, return the port number. +@end deffn + +@deffn {Scheme Procedure} sockaddr:flowinfo sa +For an @code{AF_INET6} socket address object @var{sa}, return the +flowinfo value. +@end deffn + +@deffn {Scheme Procedure} sockaddr:scopeid sa +For an @code{AF_INET6} socket address object @var{sa}, return the +scope ID value. +@end deffn + +@tpindex @code{struct sockaddr} +@tpindex @code{sockaddr} +The functions below convert to and from the C @code{struct sockaddr} +(@pxref{Address Formats,,, libc, The GNU C Library Reference Manual}). +That structure is a generic type, an application can cast to or from +@code{struct sockaddr_in}, @code{struct sockaddr_in6} or @code{struct +sockaddr_un} according to the address family. + +In a @code{struct sockaddr} taken or returned, the byte ordering in +the fields follows the C conventions (@pxref{Byte Order,, Byte Order +Conversion, libc, The GNU C Library Reference Manual}). This means +network byte order for @code{AF_INET} host address +(@code{sin_addr.s_addr}) and port number (@code{sin_port}), and +@code{AF_INET6} port number (@code{sin6_port}). But at the Scheme +level these values are taken or returned in host byte order, so the +port is an ordinary integer, and the host address likewise is an +ordinary integer (as described in @ref{Network Address Conversion}). + +@deftypefn {C Function} {struct sockaddr *} scm_c_make_socket_address (SCM family, SCM address, SCM args, size_t *outsize) +Return a newly-@code{malloc}ed @code{struct sockaddr} created from +arguments like those taken by @code{scm_make_socket_address} above. + +The size (in bytes) of the @code{struct sockaddr} return is stored +into @code{*@var{outsize}}. An application must call @code{free} to +release the returned structure when no longer required. +@end deftypefn + +@deftypefn {C Function} SCM scm_from_sockaddr (const struct sockaddr *address, unsigned address_size) +Return a Scheme socket address object from the C @var{address} +structure. @var{address_size} is the size in bytes of @var{address}. +@end deftypefn + +@deftypefn {C Function} {struct sockaddr *} scm_to_sockaddr (SCM address, size_t *address_size) +Return a newly-@code{malloc}ed @code{struct sockaddr} from a Scheme +level socket address object. + +The size (in bytes) of the @code{struct sockaddr} return is stored +into @code{*@var{outsize}}. An application must call @code{free} to +release the returned structure when no longer required. +@end deftypefn + + +@node Network Sockets and Communication +@subsubsection Network Sockets and Communication +@cindex socket +@cindex network socket + +Socket ports can be created using @code{socket} and @code{socketpair}. +The ports are initially unbuffered, to make reading and writing to the +same port more reliable. A buffer can be added to the port using +@code{setvbuf} (@pxref{Buffering}). + +Most systems have limits on how many files and sockets can be open, so +it's strongly recommended that socket ports be closed explicitly when +no longer required (@pxref{Ports}). + +Some of the underlying C functions take values in network byte order, +but the convention in Guile is that at the Scheme level everything is +ordinary host byte order and conversions are made automatically where +necessary. + +@deffn {Scheme Procedure} socket family style proto +@deffnx {C Function} scm_socket (family, style, proto) +Return a new socket port of the type specified by @var{family}, +@var{style} and @var{proto}. All three parameters are integers. The +possible values for @var{family} are as follows, where supported by +the system, + +@defvar PF_UNIX +@defvarx PF_INET +@defvarx PF_INET6 +@end defvar + +The possible values for @var{style} are as follows, again where +supported by the system, + +@defvar SOCK_STREAM +@defvarx SOCK_DGRAM +@defvarx SOCK_RAW +@defvarx SOCK_RDM +@defvarx SOCK_SEQPACKET +@end defvar + +@var{proto} can be obtained from a protocol name using +@code{getprotobyname} (@pxref{Network Databases}). A value of zero +means the default protocol, which is usually right. + +A socket cannot by used for communication until it has been connected +somewhere, usually with either @code{connect} or @code{accept} below. +@end deffn + +@deffn {Scheme Procedure} socketpair family style proto +@deffnx {C Function} scm_socketpair (family, style, proto) +Return a pair, the @code{car} and @code{cdr} of which are two unnamed +socket ports connected to each other. The connection is full-duplex, +so data can be transferred in either direction between the two. + +@var{family}, @var{style} and @var{proto} are as per @code{socket} +above. But many systems only support socket pairs in the +@code{PF_UNIX} family. Zero is likely to be the only meaningful value +for @var{proto}. +@end deffn + +@deffn {Scheme Procedure} getsockopt sock level optname +@deffnx {Scheme Procedure} setsockopt sock level optname value +@deffnx {C Function} scm_getsockopt (sock, level, optname) +@deffnx {C Function} scm_setsockopt (sock, level, optname, value) +Get or set an option on socket port @var{sock}. @code{getsockopt} +returns the current value. @code{setsockopt} sets a value and the +return is unspecified. + +@var{level} is an integer specifying a protocol layer, either +@code{SOL_SOCKET} for socket level options, or a protocol number from +the @code{IPPROTO} constants or @code{getprotoent} (@pxref{Network +Databases}). + +@defvar SOL_SOCKET +@defvarx IPPROTO_IP +@defvarx IPPROTO_TCP +@defvarx IPPROTO_UDP +@end defvar + +@var{optname} is an integer specifying an option within the protocol +layer. + +For @code{SOL_SOCKET} level the following @var{optname}s are defined +(when provided by the system). For their meaning see +@ref{Socket-Level Options,,, libc, The GNU C Library Reference +Manual}, or @command{man 7 socket}. + +@defvar SO_DEBUG +@defvarx SO_REUSEADDR +@defvarx SO_STYLE +@defvarx SO_TYPE +@defvarx SO_ERROR +@defvarx SO_DONTROUTE +@defvarx SO_BROADCAST +@defvarx SO_SNDBUF +@defvarx SO_RCVBUF +@defvarx SO_KEEPALIVE +@defvarx SO_OOBINLINE +@defvarx SO_NO_CHECK +@defvarx SO_PRIORITY +@defvarx SO_REUSEPORT +The @var{value} taken or returned is an integer. +@end defvar + +@defvar SO_LINGER +The @var{value} taken or returned is a pair of integers +@code{(@var{ENABLE} . @var{TIMEOUT})}. On old systems without timeout +support (ie.@: without @code{struct linger}), only @var{ENABLE} has an +effect but the value in Guile is always a pair. +@end defvar + +@c Note that we refer only to ``man ip'' here. On GNU/Linux it's +@c ``man 7 ip'' but on NetBSD it's ``man 4 ip''. +@c +For IP level (@code{IPPROTO_IP}) the following @var{optname}s are +defined (when provided by the system). See @command{man ip} for what +they mean. + +@defvar IP_MULTICAST_IF +This sets the source interface used by multicast traffic. +@end defvar + +@defvar IP_MULTICAST_TTL +This sets the default TTL for multicast traffic. This defaults +to 1 and should be increased to allow traffic to pass beyond the +local network. +@end defvar + +@defvar IP_ADD_MEMBERSHIP +@defvarx IP_DROP_MEMBERSHIP +These can be used only with @code{setsockopt}, not @code{getsockopt}. +@var{value} is a pair @code{(@var{MULTIADDR} . @var{INTERFACEADDR})} +of integer IPv4 addresses (@pxref{Network Address Conversion}). +@var{MULTIADDR} is a multicast address to be added to or dropped from +the interface @var{INTERFACEADDR}. @var{INTERFACEADDR} can be +@code{INADDR_ANY} to have the system select the interface. +@var{INTERFACEADDR} can also be an interface index number, on systems +supporting that. +@end defvar +@end deffn + +For @code{IPPROTO_TCP} level the following @var{optname}s are defined +(when provided by the system). For their meaning see @command{man 7 +tcp}. + +@defvar TCP_NODELAY +@defvarx TCP_CORK +The @var{value} taken or returned is an integer. +@end defvar + +@deffn {Scheme Procedure} shutdown sock how +@deffnx {C Function} scm_shutdown (sock, how) +Sockets can be closed simply by using @code{close-port}. The +@code{shutdown} procedure allows reception or transmission on a +connection to be shut down individually, according to the parameter +@var{how}: + +@table @asis +@item 0 +Stop receiving data for this socket. If further data arrives, reject it. +@item 1 +Stop trying to transmit data from this socket. Discard any +data waiting to be sent. Stop looking for acknowledgement of +data already sent; don't retransmit it if it is lost. +@item 2 +Stop both reception and transmission. +@end table + +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} connect sock sockaddr +@deffnx {Scheme Procedure} connect sock AF_INET ipv4addr port +@deffnx {Scheme Procedure} connect sock AF_INET6 ipv6addr port [flowinfo [scopeid]] +@deffnx {Scheme Procedure} connect sock AF_UNIX path +@deffnx {C Function} scm_connect (sock, fam, address, args) +Initiate a connection on socket port @var{sock} to a given address. The +destination is either a socket address object, or arguments the same as +@code{make-socket-address} would take to make such an object +(@pxref{Network Socket Address}). Return true unless the socket was +configured as non-blocking and the connection could not be made +immediately. + +@example +(connect sock AF_INET INADDR_LOOPBACK 23) +(connect sock (make-socket-address AF_INET INADDR_LOOPBACK 23)) +@end example +@end deffn + +@deffn {Scheme Procedure} bind sock sockaddr +@deffnx {Scheme Procedure} bind sock AF_INET ipv4addr port +@deffnx {Scheme Procedure} bind sock AF_INET6 ipv6addr port [flowinfo [scopeid]] +@deffnx {Scheme Procedure} bind sock AF_UNIX path +@deffnx {C Function} scm_bind (sock, fam, address, args) +Bind socket port @var{sock} to the given address. The address is +either a socket address object, or arguments the same as +@code{make-socket-address} would take to make such an object +(@pxref{Network Socket Address}). The return value is unspecified. + +Generally a socket is only explicitly bound to a particular address +when making a server, i.e.@: to listen on a particular port. For an +outgoing connection the system will assign a local address +automatically, if not already bound. + +@example +(bind sock AF_INET INADDR_ANY 12345) +(bind sock (make-socket-address AF_INET INADDR_ANY 12345)) +@end example +@end deffn + +@deffn {Scheme Procedure} listen sock backlog +@deffnx {C Function} scm_listen (sock, backlog) +Enable @var{sock} to accept connection +requests. @var{backlog} is an integer specifying +the maximum length of the queue for pending connections. +If the queue fills, new clients will fail to connect until +the server calls @code{accept} to accept a connection from +the queue. + +The return value is unspecified. +@end deffn + +@deffn {Scheme Procedure} accept sock [flags] +@deffnx {C Function} scm_accept (sock) +Accept a connection from socket port @var{sock} which has been enabled +for listening with @code{listen} above. + +If there are no incoming connections in the queue, there are two +possible behaviors, depending on whether @var{sock} has been configured +for non-blocking operation or not: + +@itemize +@item +If there is no connection waiting and the socket was set to non-blocking +mode with the @code{O_NONBLOCK} port option (@pxref{Ports and File +Descriptors,@code{fcntl}}), return @code{#f} directly. + +@item +Otherwise wait until a connection is available. +@end itemize + +The return value is a pair. The @code{car} is a new socket port, +connected and ready to communicate. The @code{cdr} is a socket address +object (@pxref{Network Socket Address}) which is where the remote +connection is from (like @code{getpeername} below). + +@var{flags}, if given, may include @code{SOCK_CLOEXEC} or +@code{SOCK_NONBLOCK}, which like @code{O_CLOEXEC} and @code{O_NONBLOCK} +apply to the newly accepted socket. + +All communication takes place using the new socket returned. The +given @var{sock} remains bound and listening, and @code{accept} may be +called on it again to get another incoming connection when desired. +@end deffn + +@deffn {Scheme Procedure} getsockname sock +@deffnx {C Function} scm_getsockname (sock) +Return a socket address object which is the where @var{sock} is bound +locally. @var{sock} may have obtained its local address from +@code{bind} (above), or if a @code{connect} is done with an otherwise +unbound socket (which is usual) then the system will have assigned an +address. + +Note that on many systems the address of a socket in the +@code{AF_UNIX} namespace cannot be read. +@end deffn + +@deffn {Scheme Procedure} getpeername sock +@deffnx {C Function} scm_getpeername (sock) +Return a socket address object which is where @var{sock} is connected +to, i.e.@: the remote endpoint. + +Note that on many systems the address of a socket in the +@code{AF_UNIX} namespace cannot be read. +@end deffn + +@deffn {Scheme Procedure} recv! sock buf [flags] +@deffnx {C Function} scm_recv (sock, buf, flags) +Receive data from a socket port. +@var{sock} must already +be bound to the address from which data is to be received. +@var{buf} is a bytevector into which +the data will be written. The size of @var{buf} limits +the amount of +data which can be received: in the case of packet +protocols, if a packet larger than this limit is encountered +then some data +will be irrevocably lost. + +@vindex MSG_OOB +@vindex MSG_PEEK +@vindex MSG_DONTROUTE +The optional @var{flags} argument is a value or bitwise OR of +@code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc. + +The value returned is the number of bytes read from the +socket. + +Note that the data is read directly from the socket file +descriptor: +any unread buffered port data is ignored. +@end deffn + +@deffn {Scheme Procedure} send sock message [flags] +@deffnx {C Function} scm_send (sock, message, flags) +@vindex MSG_OOB +@vindex MSG_PEEK +@vindex MSG_DONTROUTE +Transmit bytevector @var{message} on socket port @var{sock}. +@var{sock} must already be bound to a destination address. The value +returned is the number of bytes transmitted---it's possible for this +to be less than the length of @var{message} if the socket is set to be +non-blocking. The optional @var{flags} argument is a value or bitwise +OR of @code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc. + +Note that the data is written directly to the socket +file descriptor: +any unflushed buffered port data is ignored. +@end deffn + +@deffn {Scheme Procedure} recvfrom! sock buf [flags [start [end]]] +@deffnx {C Function} scm_recvfrom (sock, buf, flags, start, end) +Receive data from socket port @var{sock}, returning the originating +address as well as the data. This function is usually for datagram +sockets, but can be used on stream-oriented sockets too. + +The data received is stored in bytevector @var{buf}, using +either the whole bytevector or just the region between the optional +@var{start} and @var{end} positions. The size of @var{buf} +limits the amount of data that can be received. For datagram +protocols if a packet larger than this is received then excess +bytes are irrevocably lost. + +The return value is a pair. The @code{car} is the number of bytes +read. The @code{cdr} is a socket address object (@pxref{Network +Socket Address}) which is where the data came from, or @code{#f} if +the origin is unknown. + +@vindex MSG_OOB +@vindex MSG_PEEK +@vindex MSG_DONTROUTE +The optional @var{flags} argument is a or bitwise-OR (@code{logior}) +of @code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc. + +Data is read directly from the socket file descriptor, any buffered +port data is ignored. + +@c This was linux kernel 2.6.15 and glibc 2.3.6, not sure what any +@c specs are supposed to say about recvfrom threading. +@c +On a GNU/Linux system @code{recvfrom!} is not multi-threading, all +threads stop while a @code{recvfrom!} call is in progress. An +application may need to use @code{select}, @code{O_NONBLOCK} or +@code{MSG_DONTWAIT} to avoid this. +@end deffn + +@deffn {Scheme Procedure} sendto sock message sockaddr [flags] +@deffnx {Scheme Procedure} sendto sock message AF_INET ipv4addr port [flags] +@deffnx {Scheme Procedure} sendto sock message AF_INET6 ipv6addr port [flowinfo [scopeid [flags]]] +@deffnx {Scheme Procedure} sendto sock message AF_UNIX path [flags] +@deffnx {C Function} scm_sendto (sock, message, fam, address, args_and_flags) +Transmit bytevector @var{message} as a datagram socket port +@var{sock}. The destination is specified either as a socket address +object, or as arguments the same as would be taken by +@code{make-socket-address} to create such an object (@pxref{Network +Socket Address}). + +The destination address may be followed by an optional @var{flags} +argument which is a @code{logior} (@pxref{Bitwise Operations}) of +@code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc. + +The value returned is the number of bytes transmitted -- +it's possible for +this to be less than the length of @var{message} if the +socket is +set to be non-blocking. +Note that the data is written directly to the socket +file descriptor: +any unflushed buffered port data is ignored. +@end deffn + + +@node Internet Socket Examples +@subsubsection Network Socket Examples +@cindex network examples +@cindex socket examples + +The following give examples of how to use network sockets. + +@subsubheading Internet Socket Client Example + +@cindex socket client example +The following example demonstrates an Internet socket client. +It connects to the HTTP daemon running on the local machine and +returns the contents of the root index URL. + +@example +(let ((s (socket PF_INET SOCK_STREAM 0))) + (connect s AF_INET (inet-pton AF_INET "127.0.0.1") 80) + (display "GET / HTTP/1.0\r\n\r\n" s) + + (do ((line (read-line s) (read-line s))) + ((eof-object? line)) + (display line) + (newline))) +@end example + + +@subsubheading Internet Socket Server Example + +@cindex socket server example +The following example shows a simple Internet server which listens on +port 2904 for incoming connections and sends a greeting back to the +client. + +@example +(let ((s (socket PF_INET SOCK_STREAM 0))) + (setsockopt s SOL_SOCKET SO_REUSEADDR 1) + ;; @r{Specific address?} + ;; @r{(bind s AF_INET (inet-pton AF_INET "127.0.0.1") 2904)} + (bind s AF_INET INADDR_ANY 2904) + (listen s 5) + + (simple-format #t "Listening for clients in pid: ~S" (getpid)) + (newline) + + (while #t + (let* ((client-connection (accept s)) + (client-details (cdr client-connection)) + (client (car client-connection))) + (simple-format #t "Got new client connection: ~S" + client-details) + (newline) + (simple-format #t "Client address: ~S" + (gethostbyaddr + (sockaddr:addr client-details))) + (newline) + ;; @r{Send back the greeting to the client port} + (display "Hello client\r\n" client) + (close client)))) +@end example + + +@node System Identification +@subsection System Identification +@cindex system name + +This section lists the various procedures Guile provides for accessing +information about the system it runs on. + +@deffn {Scheme Procedure} uname +@deffnx {C Function} scm_uname () +Return an object with some information about the computer +system the program is running on. + +The following procedures accept an object as returned by @code{uname} +and return a selected component (all of which are strings). + +@deffn {Scheme Procedure} utsname:sysname un +The name of the operating system. +@end deffn +@deffn {Scheme Procedure} utsname:nodename un +The network name of the computer. +@end deffn +@deffn {Scheme Procedure} utsname:release un +The current release level of the operating system implementation. +@end deffn +@deffn {Scheme Procedure} utsname:version un +The current version level within the release of the operating system. +@end deffn +@deffn {Scheme Procedure} utsname:machine un +A description of the hardware. +@end deffn +@end deffn + +@deffn {Scheme Procedure} gethostname +@deffnx {C Function} scm_gethostname () +@cindex host name +Return the host name of the current processor. +@end deffn + +@deffn {Scheme Procedure} sethostname name +@deffnx {C Function} scm_sethostname (name) +Set the host name of the current processor to @var{name}. May +only be used by the superuser. The return value is not +specified. +@end deffn + +@node Locales +@subsection Locales +@cindex locale + +@deffn {Scheme Procedure} setlocale category [locale] +@deffnx {C Function} scm_setlocale (category, locale) +Get or set the current locale, used for various internationalizations. +Locales are strings, such as @samp{sv_SE}. + +If @var{locale} is given then the locale for the given @var{category} +is set and the new value returned. If @var{locale} is not given then +the current value is returned. @var{category} should be one of the +following values (@pxref{Locale Categories, Categories of Activities +that Locales Affect,, libc, The GNU C Library Reference Manual}): + +@defvar LC_ALL +@defvarx LC_COLLATE +@defvarx LC_CTYPE +@defvarx LC_MESSAGES +@defvarx LC_MONETARY +@defvarx LC_NUMERIC +@defvarx LC_TIME +@end defvar + +@cindex @code{LANG} +A common usage is @samp{(setlocale LC_ALL "")}, which initializes all +categories based on standard environment variables (@code{LANG} etc). +For full details on categories and locale names @pxref{Locales,, +Locales and Internationalization, libc, The GNU C Library Reference +Manual}. + +Note that @code{setlocale} affects locale settings for the whole +process. @xref{i18n Introduction, locale objects and +@code{make-locale}}, for a thread-safe alternative. +@end deffn + +@node Encryption +@subsection Encryption +@cindex encryption + +Please note that the procedures in this section are not suited for +strong encryption, they are only interfaces to the well-known and +common system library functions of the same name. They are just as good +(or bad) as the underlying functions, so you should refer to your system +documentation before using them (@pxref{crypt,, Encrypting Passwords, +libc, The GNU C Library Reference Manual}). + +@deffn {Scheme Procedure} crypt key salt +@deffnx {C Function} scm_crypt (key, salt) +Encrypt @var{key}, with the addition of @var{salt} (both strings), +using the @code{crypt} C library call. +@end deffn + +Although @code{getpass} is not an encryption procedure per se, it +appears here because it is often used in combination with @code{crypt}: + +@deffn {Scheme Procedure} getpass prompt +@deffnx {C Function} scm_getpass (prompt) +@cindex password +Display @var{prompt} to the standard error output and read +a password from @file{/dev/tty}. If this file is not +accessible, it reads from standard input. The password may be +up to 127 characters in length. Additional characters and the +terminating newline character are discarded. While reading +the password, echoing and the generation of signals by special +characters is disabled. +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/preface.texi b/doc/ref/preface.texi new file mode 100644 index 000000000..87f481015 --- /dev/null +++ b/doc/ref/preface.texi @@ -0,0 +1,113 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010, 2011, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Preface +@unnumbered Preface + +This manual describes how to use Guile, GNU's Ubiquitous Intelligent +Language for Extensions. It relates particularly to Guile version +@value{VERSION}. + +@menu +* Contributors:: +* Guile License:: +@end menu + +@node Contributors +@unnumberedsec Contributors to this Manual + +Like Guile itself, the Guile reference manual is a living entity, cared +for by many people over a long period of time. As such, it is hard to +identify individuals of whom to say ``yes, this person, she wrote the +manual.'' + +Still, among the many contributions, some caretakers stand out. First +among them is Neil Jerram, who has worked on this document for over ten +years. Neil's attention both to detail and to the big picture have made +a real difference in the understanding of a generation of Guile hackers. + +Next we should note Marius Vollmer's effect on this document. Marius +maintained Guile during a period in which Guile's API was +clarified---put to the fire, so to speak---and he had the good sense to +effect the same change on the manual. + +Martin Grabmueller made substantial contributions throughout the manual +in preparation for the Guile 1.6 release, including filling out a lot of +the documentation of Scheme data types, control mechanisms and +procedures. In addition, he wrote the documentation for Guile's SRFI +modules and modules associated with the Guile REPL. + +Ludovic Court@`es and Andy Wingo, who co-maintain Guile since 2010, +along with Mark Weaver, have also made their dent in the manual, writing +documentation for new modules and subsystems that arrived with Guile +2.0. Ludovic, Andy, and Mark are also responsible for ensuring that the +existing text retains its relevance as Guile evolves. @xref{Reporting +Bugs}, for more information on reporting problems in this manual. + +The content for the first versions of this manual incorporated and was +inspired by documents from Aubrey Jaffer, author of the SCM system on +which Guile was based, and from Tom Lord, Guile's first maintainer. +Although most of this text has been rewritten, all of it was important, +and some of the structure remains. + +The manual for the first versions of Guile were largely written, edited, +and compiled by Mark Galassi and Jim Blandy. In particular, Jim wrote +the original tutorial on Guile's data representation and the C API for +accessing Guile objects. + +Significant portions were also contributed by Thien-Thi Nguyen, Kevin +Ryde, Mikael Djurfeldt, Christian Lynbech, Julian Graham, Gary Houston, +Tim Pierce, and a few dozen more. You, reader, are most welcome to join +their esteemed ranks. Visit Guile's web site at +@uref{http://www.gnu.org/software/guile/} to find out how to get +involved. + + +@node Guile License +@unnumberedsec The Guile License +@cindex copying +@cindex GPL +@cindex LGPL +@cindex license + +Guile is Free Software. Guile is copyrighted, not public domain, and +there are restrictions on its distribution or redistribution, but +these restrictions are designed to permit everything a cooperating +person would want to do. + +@itemize @bullet +@item +The Guile library (libguile) and supporting files are published under +the terms of the GNU Lesser General Public License version 3 or later. +See the files @file{COPYING.LESSER} and @file{COPYING}. + +@item +The Guile readline module is published under the terms of the GNU +General Public License version 3 or later. See the file @file{COPYING}. + +@item +The manual you're now reading is published under the terms of the GNU +Free Documentation License (@pxref{GNU Free Documentation License}). +@end itemize + +C code linking to the Guile library is subject to terms of that +library. Basically such code may be published on any terms, provided +users can re-link against a new or modified version of Guile. + +C code linking to the Guile readline module is subject to the terms of +that module. Basically such code must be published on Free terms. + +Scheme level code written to be run by Guile (but not derived from +Guile itself) is not restricted in any way, and may be published on any +terms. We encourage authors to publish on Free terms. + +You must be aware there is no warranty whatsoever for Guile. This is +described in full in the licenses. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/r6rs.texi b/doc/ref/r6rs.texi new file mode 100644 index 000000000..fa8d7d213 --- /dev/null +++ b/doc/ref/r6rs.texi @@ -0,0 +1,2888 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2010, 2011, 2012, 2013, +@c 2014 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node R6RS Support +@section R6RS Support +@cindex R6RS + +@xref{R6RS Libraries}, for more information on how to define R6RS libraries, and +their integration with Guile modules. + +@menu +* R6RS Incompatibilities:: Guile mostly implements R6RS. +* R6RS Standard Libraries:: Modules defined by the R6RS. +@end menu + +@node R6RS Incompatibilities +@subsection Incompatibilities with the R6RS + +There are some incompatibilities between Guile and the R6RS. Some of +them are intentional, some of them are bugs, and some are simply +unimplemented features. Please let the Guile developers know if you +find one that is not on this list. + +@itemize +@item +The R6RS specifies many situations in which a conforming implementation +must signal a specific error. Guile doesn't really care about that too +much---if a correct R6RS program would not hit that error, we don't +bother checking for it. + +@item +Multiple @code{library} forms in one file are not yet supported. This +is because the expansion of @code{library} sets the current module, but +does not restore it. This is a bug. + +@item +R6RS unicode escapes within strings are disabled by default, because +they conflict with Guile's already-existing escapes. The same is the +case for R6RS treatment of escaped newlines in strings. + +R6RS behavior can be turned on via a reader option. @xref{String +Syntax}, for more information. + +@item +A @code{set!} to a variable transformer may only expand to an +expression, not a definition---even if the original @code{set!} +expression was in definition context. + +@item +Instead of using the algorithm detailed in chapter 10 of the R6RS, +expansion of toplevel forms happens sequentially. + +For example, while the expansion of the following set of toplevel +definitions does the correct thing: + +@example +(begin + (define even? + (lambda (x) + (or (= x 0) (odd? (- x 1))))) + (define-syntax odd? + (syntax-rules () + ((odd? x) (not (even? x))))) + (even? 10)) +@result{} #t +@end example + +@noindent +The same definitions outside of the @code{begin} wrapper do not: + +@example +(define even? + (lambda (x) + (or (= x 0) (odd? (- x 1))))) +(define-syntax odd? + (syntax-rules () + ((odd? x) (not (even? x))))) +(even? 10) +<unnamed port>:4:18: In procedure even?: +<unnamed port>:4:18: Wrong type to apply: #<syntax-transformer odd?> +@end example + +This is because when expanding the right-hand-side of @code{even?}, the +reference to @code{odd?} is not yet marked as a syntax transformer, so +it is assumed to be a function. + +This bug will only affect top-level programs, not code in @code{library} +forms. Fixing it for toplevel forms seems doable, but tricky to +implement in a backward-compatible way. Suggestions and/or patches would +be appreciated. + +@item +The @code{(rnrs io ports)} module is incomplete. Work is +ongoing to fix this. + +@item +Guile does not prevent use of textual I/O procedures on binary ports, or +vice versa. All ports in Guile support both binary and textual I/O. +@xref{Encoding}, for full details. + +@item +Guile's implementation of @code{equal?} may fail to terminate when +applied to arguments containing cycles. +@end itemize + +@node R6RS Standard Libraries +@subsection R6RS Standard Libraries + +In contrast with earlier versions of the Revised Report, the R6RS +organizes the procedures and syntactic forms required of conforming +implementations into a set of ``standard libraries'' which can be +imported as necessary by user programs and libraries. Here we briefly +list the libraries that have been implemented for Guile. + +We do not attempt to document these libraries fully here, as most of +their functionality is already available in Guile itself. The +expectation is that most Guile users will use the well-known and +well-documented Guile modules. These R6RS libraries are mostly useful +to users who want to port their code to other R6RS systems. + +The documentation in the following sections reproduces some of the +content of the library section of the Report, but is mostly intended to +provide supplementary information about Guile's implementation of the +R6RS standard libraries. For complete documentation, design rationales +and further examples, we advise you to consult the ``Standard +Libraries'' section of the Report (@pxref{Standard Libraries, +R6RS Standard Libraries,, r6rs, The Revised^6 Report on the Algorithmic +Language Scheme}). + +@menu +* Library Usage:: What to know about Guile's library support. +* rnrs base:: The base library. +* rnrs unicode:: Access to Unicode operations. +* rnrs bytevectors:: Functions for working with binary data. +* rnrs lists:: List utilities. +* rnrs sorting:: Sorting for lists and vectors. +* rnrs control:: Additional control structures. + +* R6RS Records:: A note about R6RS records. +* rnrs records syntactic:: Syntactic API for R6RS records. +* rnrs records procedural:: Procedural API for R6RS records. +* rnrs records inspection:: Reflection on R6RS records. + +* rnrs exceptions:: Handling exceptional situations. +* rnrs conditions:: Data structures for exceptions. + +* R6RS I/O Conditions:: Predefined I/O error types. +* R6RS Transcoders:: Characters and bytes. +* rnrs io ports:: Support for port-based I/O. +* R6RS File Ports:: Working with files. +* rnrs io simple:: High-level I/O API. + +* rnrs files:: Functions for working with files. +* rnrs programs:: Functions for working with processes. +* rnrs arithmetic fixnums:: Fixed-precision arithmetic operations. +* rnrs arithmetic flonums:: Floating-point arithmetic operations. +* rnrs arithmetic bitwise:: Exact bitwise arithmetic operations. +* rnrs syntax-case:: Support for `syntax-case' macros. +* rnrs hashtables:: Hashtables. +* rnrs enums:: Enumerations. +* rnrs:: The composite library. +* rnrs eval:: Support for on-the-fly evaluation. +* rnrs mutable-pairs:: Support for mutable pairs. +* rnrs mutable-strings:: Support for mutable strings. +* rnrs r5rs:: Compatibility layer for R5RS Scheme. + +@end menu + +@node Library Usage +@subsubsection Library Usage + +Guile implements the R6RS `library' form as a transformation to a native +Guile module definition. As a consequence of this, all of the libraries +described in the following subsections, in addition to being available +for use by R6RS libraries and top-level programs, can also be imported +as if they were normal Guile modules---via a @code{use-modules} form, +say. For example, the R6RS ``composite'' library can be imported by: + +@lisp + (import (rnrs (6))) +@end lisp + +@lisp + (use-modules ((rnrs) :version (6))) +@end lisp + +For more information on Guile's library implementation, see +(@pxref{R6RS Libraries}). + +@node rnrs base +@subsubsection rnrs base + +The @code{(rnrs base (6))} library exports the procedures and syntactic +forms described in the main section of the Report +(@pxref{Base library, R6RS Base library,, r6rs, +The Revised^6 Report on the Algorithmic Language Scheme}). They are +grouped below by the existing manual sections to which they correspond. + +@deffn {Scheme Procedure} boolean? obj +@deffnx {Scheme Procedure} not x +@xref{Booleans}, for documentation. +@end deffn + +@deffn {Scheme Procedure} symbol? obj +@deffnx {Scheme Procedure} symbol->string sym +@deffnx {Scheme Procedure} string->symbol str +@xref{Symbol Primitives}, for documentation. +@end deffn + +@deffn {Scheme Procedure} char? obj +@deffnx {Scheme Procedure} char=? +@deffnx {Scheme Procedure} char<? +@deffnx {Scheme Procedure} char>? +@deffnx {Scheme Procedure} char<=? +@deffnx {Scheme Procedure} char>=? +@deffnx {Scheme Procedure} integer->char n +@deffnx {Scheme Procedure} char->integer chr +@xref{Characters}, for documentation. +@end deffn + +@deffn {Scheme Procedure} list? x +@deffnx {Scheme Procedure} null? x +@xref{List Predicates}, for documentation. +@end deffn + +@deffn {Scheme Procedure} pair? x +@deffnx {Scheme Procedure} cons x y +@deffnx {Scheme Procedure} car pair +@deffnx {Scheme Procedure} cdr pair +@deffnx {Scheme Procedure} caar pair +@deffnx {Scheme Procedure} cadr pair +@deffnx {Scheme Procedure} cdar pair +@deffnx {Scheme Procedure} cddr pair +@deffnx {Scheme Procedure} caaar pair +@deffnx {Scheme Procedure} caadr pair +@deffnx {Scheme Procedure} cadar pair +@deffnx {Scheme Procedure} cdaar pair +@deffnx {Scheme Procedure} caddr pair +@deffnx {Scheme Procedure} cdadr pair +@deffnx {Scheme Procedure} cddar pair +@deffnx {Scheme Procedure} cdddr pair +@deffnx {Scheme Procedure} caaaar pair +@deffnx {Scheme Procedure} caaadr pair +@deffnx {Scheme Procedure} caadar pair +@deffnx {Scheme Procedure} cadaar pair +@deffnx {Scheme Procedure} cdaaar pair +@deffnx {Scheme Procedure} cddaar pair +@deffnx {Scheme Procedure} cdadar pair +@deffnx {Scheme Procedure} cdaadr pair +@deffnx {Scheme Procedure} cadadr pair +@deffnx {Scheme Procedure} caaddr pair +@deffnx {Scheme Procedure} caddar pair +@deffnx {Scheme Procedure} cadddr pair +@deffnx {Scheme Procedure} cdaddr pair +@deffnx {Scheme Procedure} cddadr pair +@deffnx {Scheme Procedure} cdddar pair +@deffnx {Scheme Procedure} cddddr pair +@xref{Pairs}, for documentation. +@end deffn + +@deffn {Scheme Procedure} number? obj +@xref{Numerical Tower}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string? obj +@xref{String Predicates}, for documentation. +@end deffn + +@deffn {Scheme Procedure} procedure? obj +@xref{Procedure Properties}, for documentation. +@end deffn + +@deffn {Scheme Syntax} define name value +@deffnx {Scheme Syntax} set! variable-name value +@xref{Definition}, for documentation. +@end deffn + +@deffn {Scheme Syntax} define-syntax keyword expression +@deffnx {Scheme Syntax} let-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +@deffnx {Scheme Syntax} letrec-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +@xref{Defining Macros}, for documentation. +@end deffn + +@deffn {Scheme Syntax} identifier-syntax exp +@xref{Identifier Macros}, for documentation. +@end deffn + +@deffn {Scheme Syntax} syntax-rules literals (pattern template) ... +@xref{Syntax Rules}, for documentation. +@end deffn + +@deffn {Scheme Syntax} lambda formals body +@xref{Lambda}, for documentation. +@end deffn + +@deffn {Scheme Syntax} let bindings body +@deffnx {Scheme Syntax} let* bindings body +@deffnx {Scheme Syntax} letrec bindings body +@deffnx {Scheme Syntax} letrec* bindings body +@xref{Local Bindings}, for documentation. +@end deffn + +@deffn {Scheme Syntax} let-values bindings body +@deffnx {Scheme Syntax} let*-values bindings body +@xref{SRFI-11}, for documentation. +@end deffn + +@deffn {Scheme Syntax} begin expr1 expr2 ... +@xref{begin}, for documentation. +@end deffn + +@deffn {Scheme Syntax} quote expr +@deffnx {Scheme Syntax} quasiquote expr +@deffnx {Scheme Syntax} unquote expr +@deffnx {Scheme Syntax} unquote-splicing expr +@xref{Expression Syntax}, for documentation. +@end deffn + +@deffn {Scheme Syntax} if test consequence [alternate] +@deffnx {Scheme Syntax} cond clause1 clause2 ... +@deffnx {Scheme Syntax} case key clause1 clause2 ... +@xref{Conditionals}, for documentation. +@end deffn + +@deffn {Scheme Syntax} and expr ... +@deffnx {Scheme Syntax} or expr ... +@xref{and or}, for documentation. +@end deffn + +@deffn {Scheme Procedure} eq? x y +@deffnx {Scheme Procedure} eqv? x y +@deffnx {Scheme Procedure} equal? x y +@deffnx {Scheme Procedure} symbol=? symbol1 symbol2 ... +@xref{Equality}, for documentation. + +@code{symbol=?} is identical to @code{eq?}. +@end deffn + +@deffn {Scheme Procedure} complex? z +@xref{Complex Numbers}, for documentation. +@end deffn + +@deffn {Scheme Procedure} real-part z +@deffnx {Scheme Procedure} imag-part z +@deffnx {Scheme Procedure} make-rectangular real_part imaginary_part +@deffnx {Scheme Procedure} make-polar x y +@deffnx {Scheme Procedure} magnitude z +@deffnx {Scheme Procedure} angle z +@xref{Complex}, for documentation. +@end deffn + +@deffn {Scheme Procedure} sqrt z +@deffnx {Scheme Procedure} exp z +@deffnx {Scheme Procedure} expt z1 z2 +@deffnx {Scheme Procedure} log z +@deffnx {Scheme Procedure} sin z +@deffnx {Scheme Procedure} cos z +@deffnx {Scheme Procedure} tan z +@deffnx {Scheme Procedure} asin z +@deffnx {Scheme Procedure} acos z +@deffnx {Scheme Procedure} atan z +@xref{Scientific}, for documentation. +@end deffn + +@deffn {Scheme Procedure} real? x +@deffnx {Scheme Procedure} rational? x +@deffnx {Scheme Procedure} numerator x +@deffnx {Scheme Procedure} denominator x +@deffnx {Scheme Procedure} rationalize x eps +@xref{Reals and Rationals}, for documentation. +@end deffn + +@deffn {Scheme Procedure} exact? x +@deffnx {Scheme Procedure} inexact? x +@deffnx {Scheme Procedure} exact z +@deffnx {Scheme Procedure} inexact z +@xref{Exactness}, for documentation. The @code{exact} and +@code{inexact} procedures are identical to the @code{inexact->exact} and +@code{exact->inexact} procedures provided by Guile's code library. +@end deffn + +@deffn {Scheme Procedure} integer? x +@xref{Integers}, for documentation. +@end deffn + +@deffn {Scheme Procedure} odd? n +@deffnx {Scheme Procedure} even? n +@deffnx {Scheme Procedure} gcd x ... +@deffnx {Scheme Procedure} lcm x ... +@deffnx {Scheme Procedure} exact-integer-sqrt k +@xref{Integer Operations}, for documentation. +@end deffn + +@deffn {Scheme Procedure} = +@deffnx {Scheme Procedure} < +@deffnx {Scheme Procedure} > +@deffnx {Scheme Procedure} <= +@deffnx {Scheme Procedure} >= +@deffnx {Scheme Procedure} zero? x +@deffnx {Scheme Procedure} positive? x +@deffnx {Scheme Procedure} negative? x +@xref{Comparison}, for documentation. +@end deffn + +@deffn {Scheme Procedure} for-each f lst1 lst2 ... +@xref{SRFI-1 Fold and Map}, for documentation. +@end deffn + +@deffn {Scheme Procedure} list elem @dots{} +@xref{List Constructors}, for documentation. +@end deffn + +@deffn {Scheme Procedure} length lst +@deffnx {Scheme Procedure} list-ref lst k +@deffnx {Scheme Procedure} list-tail lst k +@xref{List Selection}, for documentation. +@end deffn + +@deffn {Scheme Procedure} append lst @dots{} obj +@deffnx {Scheme Procedure} append +@deffnx {Scheme Procedure} reverse lst +@xref{Append/Reverse}, for documentation. +@end deffn + +@deffn {Scheme Procedure} number->string n [radix] +@deffnx {Scheme Procedure} string->number str [radix] +@xref{Conversion}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string char ... +@deffnx {Scheme Procedure} make-string k [chr] +@deffnx {Scheme Procedure} list->string lst +@xref{String Constructors}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string->list str [start [end]] +@xref{List/String Conversion}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-length str +@deffnx {Scheme Procedure} string-ref str k +@deffnx {Scheme Procedure} string-copy str [start [end]] +@deffnx {Scheme Procedure} substring str start [end] +@xref{String Selection}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string=? s1 s2 s3 @dots{} +@deffnx {Scheme Procedure} string<? s1 s2 s3 @dots{} +@deffnx {Scheme Procedure} string>? s1 s2 s3 @dots{} +@deffnx {Scheme Procedure} string<=? s1 s2 s3 @dots{} +@deffnx {Scheme Procedure} string>=? s1 s2 s3 @dots{} +@xref{String Comparison}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-append arg @dots{} +@xref{Reversing and Appending Strings}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-for-each proc s [start [end]] +@xref{Mapping Folding and Unfolding}, for documentation. +@end deffn + +@deffn {Scheme Procedure} + z1 ... +@deffnx {Scheme Procedure} - z1 z2 ... +@deffnx {Scheme Procedure} * z1 ... +@deffnx {Scheme Procedure} / z1 z2 ... +@deffnx {Scheme Procedure} max x1 x2 ... +@deffnx {Scheme Procedure} min x1 x2 ... +@deffnx {Scheme Procedure} abs x +@deffnx {Scheme Procedure} truncate x +@deffnx {Scheme Procedure} floor x +@deffnx {Scheme Procedure} ceiling x +@deffnx {Scheme Procedure} round x +@xref{Arithmetic}, for documentation. +@end deffn + +@rnindex div +@rnindex mod +@rnindex div-and-mod +@deffn {Scheme Procedure} div x y +@deffnx {Scheme Procedure} mod x y +@deffnx {Scheme Procedure} div-and-mod x y +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{div} returns the integer @var{q} +and @code{mod} returns the real number @var{r} such that +@math{@var{x} = @var{q}*@var{y} + @var{r}} and @math{0 <= @var{r} < abs(@var{y})}. +@code{div-and-mod} returns both @var{q} and @var{r}, and is more +efficient than computing each separately. Note that when @math{@var{y} > 0}, +@code{div} returns @math{floor(@var{x}/@var{y})}, otherwise +it returns @math{ceiling(@var{x}/@var{y})}. + +@lisp +(div 123 10) @result{} 12 +(mod 123 10) @result{} 3 +(div-and-mod 123 10) @result{} 12 and 3 +(div-and-mod 123 -10) @result{} -12 and 3 +(div-and-mod -123 10) @result{} -13 and 7 +(div-and-mod -123 -10) @result{} 13 and 7 +(div-and-mod -123.2 -63.5) @result{} 2.0 and 3.8 +(div-and-mod 16/3 -10/7) @result{} -3 and 22/21 +@end lisp +@end deffn + +@rnindex div0 +@rnindex mod0 +@rnindex div0-and-mod0 +@deffn {Scheme Procedure} div0 x y +@deffnx {Scheme Procedure} mod0 x y +@deffnx {Scheme Procedure} div0-and-mod0 x y +These procedures accept two real numbers @var{x} and @var{y}, where the +divisor @var{y} must be non-zero. @code{div0} returns the +integer @var{q} and @code{mod0} returns the real number +@var{r} such that @math{@var{x} = @var{q}*@var{y} + @var{r}} and +@math{-abs(@var{y}/2) <= @var{r} < abs(@var{y}/2)}. @code{div0-and-mod0} +returns both @var{q} and @var{r}, and is more efficient than computing +each separately. + +Note that @code{div0} returns @math{@var{x}/@var{y}} rounded to the +nearest integer. When @math{@var{x}/@var{y}} lies exactly half-way +between two integers, the tie is broken according to the sign of +@var{y}. If @math{@var{y} > 0}, ties are rounded toward positive +infinity, otherwise they are rounded toward negative infinity. +This is a consequence of the requirement that +@math{-abs(@var{y}/2) <= @var{r} < abs(@var{y}/2)}. + +@lisp +(div0 123 10) @result{} 12 +(mod0 123 10) @result{} 3 +(div0-and-mod0 123 10) @result{} 12 and 3 +(div0-and-mod0 123 -10) @result{} -12 and 3 +(div0-and-mod0 -123 10) @result{} -12 and -3 +(div0-and-mod0 -123 -10) @result{} 12 and -3 +(div0-and-mod0 -123.2 -63.5) @result{} 2.0 and 3.8 +(div0-and-mod0 16/3 -10/7) @result{} -4 and -8/21 +@end lisp +@end deffn + +@deffn {Scheme Procedure} real-valued? obj +@deffnx {Scheme Procedure} rational-valued? obj +@deffnx {Scheme Procedure} integer-valued? obj +These procedures return @code{#t} if and only if their arguments can, +respectively, be coerced to a real, rational, or integer value without a +loss of numerical precision. + +@code{real-valued?} will return @code{#t} for complex numbers whose +imaginary parts are zero. +@end deffn + +@deffn {Scheme Procedure} nan? x +@deffnx {Scheme Procedure} infinite? x +@deffnx {Scheme Procedure} finite? x +@code{nan?} returns @code{#t} if @var{x} is a NaN value, @code{#f} +otherwise. @code{infinite?} returns @code{#t} if @var{x} is an infinite +value, @code{#f} otherwise. @code{finite?} returns @code{#t} if @var{x} +is neither infinite nor a NaN value, otherwise it returns @code{#f}. +Every real number satisfies exactly one of these predicates. An +exception is raised if @var{x} is not real. +@end deffn + +@deffn {Scheme Syntax} assert expr +Raises an @code{&assertion} condition if @var{expr} evaluates to +@code{#f}; otherwise evaluates to the value of @var{expr}. +@end deffn + +@deffn {Scheme Procedure} error who message irritant1 ... +@deffnx {Scheme Procedure} assertion-violation who message irritant1 ... +These procedures raise compound conditions based on their arguments: +If @var{who} is not @code{#f}, the condition will include a @code{&who} +condition whose @code{who} field is set to @var{who}; a @code{&message} +condition will be included with a @code{message} field equal to +@var{message}; an @code{&irritants} condition will be included with its +@code{irritants} list given by @code{irritant1 ...}. + +@code{error} produces a compound condition with the simple conditions +described above, as well as an @code{&error} condition; +@code{assertion-violation} produces one that includes an +@code{&assertion} condition. +@end deffn + +@deffn {Scheme Procedure} vector-map proc v +@deffnx {Scheme Procedure} vector-for-each proc v +These procedures implement the @code{map} and @code{for-each} contracts +over vectors. +@end deffn + +@deffn {Scheme Procedure} vector arg @dots{} +@deffnx {Scheme Procedure} vector? obj +@deffnx {Scheme Procedure} make-vector len +@deffnx {Scheme Procedure} make-vector len fill +@deffnx {Scheme Procedure} list->vector l +@deffnx {Scheme Procedure} vector->list v +@xref{Vector Creation}, for documentation. +@end deffn + +@deffn {Scheme Procedure} vector-length vector +@deffnx {Scheme Procedure} vector-ref vector k +@deffnx {Scheme Procedure} vector-set! vector k obj +@deffnx {Scheme Procedure} vector-fill! v fill +@xref{Vector Accessors}, for documentation. +@end deffn + +@deffn {Scheme Procedure} call-with-current-continuation proc +@deffnx {Scheme Procedure} call/cc proc +@xref{Continuations}, for documentation. +@end deffn + +@deffn {Scheme Procedure} values arg @dots{} +@deffnx {Scheme Procedure} call-with-values producer consumer +@xref{Multiple Values}, for documentation. +@end deffn + +@deffn {Scheme Procedure} dynamic-wind in_guard thunk out_guard +@xref{Dynamic Wind}, for documentation. +@end deffn + +@deffn {Scheme Procedure} apply proc arg @dots{} arglst +@xref{Fly Evaluation}, for documentation. +@end deffn + +@node rnrs unicode +@subsubsection rnrs unicode + +The @code{(rnrs unicode (6))} library provides procedures for +manipulating Unicode characters and strings. + +@deffn {Scheme Procedure} char-upcase char +@deffnx {Scheme Procedure} char-downcase char +@deffnx {Scheme Procedure} char-titlecase char +@deffnx {Scheme Procedure} char-foldcase char +These procedures translate their arguments from one Unicode character +set to another. @code{char-upcase}, @code{char-downcase}, and +@code{char-titlecase} are identical to their counterparts in the +Guile core library; @xref{Characters}, for documentation. + +@code{char-foldcase} returns the result of applying @code{char-upcase} +to its argument, followed by @code{char-downcase}---except in the case +of the Turkic characters @code{U+0130} and @code{U+0131}, for which the +procedure acts as the identity function. +@end deffn + +@deffn {Scheme Procedure} char-ci=? char1 char2 char3 ... +@deffnx {Scheme Procedure} char-ci<? char1 char2 char3 ... +@deffnx {Scheme Procedure} char-ci>? char1 char2 char3 ... +@deffnx {Scheme Procedure} char-ci<=? char1 char2 char3 ... +@deffnx {Scheme Procedure} char-ci>=? char1 char2 char3 ... +These procedures facilitate case-insensitive comparison of Unicode +characters. They are identical to the procedures provided by Guile's +core library. @xref{Characters}, for documentation. +@end deffn + +@deffn {Scheme Procedure} char-alphabetic? char +@deffnx {Scheme Procedure} char-numeric? char +@deffnx {Scheme Procedure} char-whitespace? char +@deffnx {Scheme Procedure} char-upper-case? char +@deffnx {Scheme Procedure} char-lower-case? char +@deffnx {Scheme Procedure} char-title-case? char +These procedures implement various Unicode character set predicates. +They are identical to the procedures provided by Guile's core library. +@xref{Characters}, for documentation. +@end deffn + +@deffn {Scheme Procedure} char-general-category char +@xref{Characters}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-upcase string +@deffnx {Scheme Procedure} string-downcase string +@deffnx {Scheme Procedure} string-titlecase string +@deffnx {Scheme Procedure} string-foldcase string +These procedures perform Unicode case folding operations on their input. +@xref{Alphabetic Case Mapping}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-ci=? string1 string2 string3 ... +@deffnx {Scheme Procedure} string-ci<? string1 string2 string3 ... +@deffnx {Scheme Procedure} string-ci>? string1 string2 string3 ... +@deffnx {Scheme Procedure} string-ci<=? string1 string2 string3 ... +@deffnx {Scheme Procedure} string-ci>=? string1 string2 string3 ... +These procedures perform case-insensitive comparison on their input. +@xref{String Comparison}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-normalize-nfd string +@deffnx {Scheme Procedure} string-normalize-nfkd string +@deffnx {Scheme Procedure} string-normalize-nfc string +@deffnx {Scheme Procedure} string-normalize-nfkc string +These procedures perform Unicode string normalization operations on +their input. @xref{String Comparison}, for documentation. +@end deffn + +@node rnrs bytevectors +@subsubsection rnrs bytevectors + +The @code{(rnrs bytevectors (6))} library provides procedures for +working with blocks of binary data. This functionality is documented +in its own section of the manual; @xref{Bytevectors}. + +@node rnrs lists +@subsubsection rnrs lists + +The @code{(rnrs lists (6))} library provides procedures additional +procedures for working with lists. + +@deffn {Scheme Procedure} find proc list +This procedure is identical to the one defined in Guile's SRFI-1 +implementation. @xref{SRFI-1 Searching}, for documentation. +@end deffn + +@deffn {Scheme Procedure} for-all proc list1 list2 ... +@deffnx {Scheme Procedure} exists proc list1 list2 ... + +The @code{for-all} procedure is identical to the @code{every} procedure +defined by SRFI-1; the @code{exists} procedure is identical to SRFI-1's +@code{any}. @xref{SRFI-1 Searching}, for documentation. +@end deffn + +@deffn {Scheme Procedure} filter proc list +@deffnx {Scheme Procedure} partition proc list +These procedures are identical to the ones provided by SRFI-1. +@xref{List Modification}, for a description of @code{filter}; +@xref{SRFI-1 Filtering and Partitioning}, for @code{partition}. +@end deffn + +@deffn {Scheme Procedure} fold-right combine nil list1 list2 @dots{} +This procedure is identical the @code{fold-right} procedure provided by +SRFI-1. @xref{SRFI-1 Fold and Map}, for documentation. +@end deffn + +@deffn {Scheme Procedure} fold-left combine nil list1 list2 @dots{} +This procedure is like @code{fold} from SRFI-1, but @var{combine} is +called with the seed as the first argument. @xref{SRFI-1 Fold and Map}, +for documentation. +@end deffn + +@deffn {Scheme Procedure} remp proc list +@deffnx {Scheme Procedure} remove obj list +@deffnx {Scheme Procedure} remv obj list +@deffnx {Scheme Procedure} remq obj list +@code{remove}, @code{remv}, and @code{remq} are identical to the +@code{delete}, @code{delv}, and @code{delq} procedures provided by +Guile's core library, (@pxref{List Modification}). @code{remp} is +identical to the alternate @code{remove} procedure provided by SRFI-1; +@xref{SRFI-1 Deleting}. +@end deffn + +@deffn {Scheme Procedure} memp proc list +@deffnx {Scheme Procedure} member obj list +@deffnx {Scheme Procedure} memv obj list +@deffnx {Scheme Procedure} memq obj list +@code{member}, @code{memv}, and @code{memq} are identical to the +procedures provided by Guile's core library; @xref{List Searching}, +for their documentation. @code{memp} uses the specified predicate +function @code{proc} to test elements of the list @var{list}---it +behaves similarly to @code{find}, except that it returns the first +sublist of @var{list} whose @code{car} satisfies @var{proc}. +@end deffn + +@deffn {Scheme Procedure} assp proc alist +@deffnx {Scheme Procedure} assoc obj alist +@deffnx {Scheme Procedure} assv obj alist +@deffnx {Scheme Procedure} assq obj alist +@code{assoc}, @code{assv}, and @code{assq} are identical to the +procedures provided by Guile's core library; +@xref{Alist Key Equality}, for their documentation. @code{assp} uses +the specified predicate function @code{proc} to test keys in the +association list @var{alist}. +@end deffn + +@deffn {Scheme Procedure} cons* obj1 ... obj +@deffnx {Scheme Procedure} cons* obj +This procedure is identical to the one exported by Guile's core +library. @xref{List Constructors}, for documentation. +@end deffn + +@node rnrs sorting +@subsubsection rnrs sorting + +The @code{(rnrs sorting (6))} library provides procedures for sorting +lists and vectors. + +@deffn {Scheme Procedure} list-sort proc list +@deffnx {Scheme Procedure} vector-sort proc vector +These procedures return their input sorted in ascending order, without +modifying the original data. @var{proc} must be a procedure that takes +two elements from the input list or vector as arguments, and returns a +true value if the first is ``less'' than the second, @code{#f} +otherwise. @code{list-sort} returns a list; @code{vector-sort} returns +a vector. + +Both @code{list-sort} and @code{vector-sort} are implemented in terms of +the @code{stable-sort} procedure from Guile's core library. +@xref{Sorting}, for a discussion of the behavior of that procedure. +@end deffn + +@deffn {Scheme Procedure} vector-sort! proc vector +Performs a destructive, ``in-place'' sort of @var{vector}, using +@var{proc} as described above to determine an ascending ordering of +elements. @code{vector-sort!} returns an unspecified value. + +This procedure is implemented in terms of the @code{sort!} procedure +from Guile's core library. @xref{Sorting}, for more information. +@end deffn + +@node rnrs control +@subsubsection rnrs control + +The @code{(rnrs control (6))} library provides syntactic forms useful +for constructing conditional expressions and controlling the flow of +execution. + +@deffn {Scheme Syntax} when test expression1 expression2 ... +@deffnx {Scheme Syntax} unless test expression1 expression2 ... +The @code{when} form is evaluated by evaluating the specified @var{test} +expression; if the result is a true value, the @var{expression}s that +follow it are evaluated in order, and the value of the final +@var{expression} becomes the value of the entire @code{when} expression. + +The @code{unless} form behaves similarly, with the exception that the +specified @var{expression}s are only evaluated if the value of +@var{test} is false. +@end deffn + +@deffn {Scheme Syntax} do ((variable init step) ...) (test expression ...) command ... +This form is identical to the one provided by Guile's core library. +@xref{while do}, for documentation. +@end deffn + +@deffn {Scheme Syntax} case-lambda clause ... +This form is identical to the one provided by Guile's core library. +@xref{Case-lambda}, for documentation. +@end deffn + +@node R6RS Records +@subsubsection R6RS Records + +The manual sections below describe Guile's implementation of R6RS +records, which provide support for user-defined data types. The R6RS +records API provides a superset of the features provided by Guile's +``native'' records, as well as those of the SRFI-9 records API; +@xref{Records}, and @ref{SRFI-9 Records}, for a description of those +interfaces. + +As with SRFI-9 and Guile's native records, R6RS records are constructed +using a record-type descriptor that specifies attributes like the +record's name, its fields, and the mutability of those fields. + +R6RS records extend this framework to support single inheritance via the +specification of a ``parent'' type for a record type at definition time. +Accessors and mutator procedures for the fields of a parent type may be +applied to records of a subtype of this parent. A record type may be +@dfn{sealed}, in which case it cannot be used as the parent of another +record type. + +The inheritance mechanism for record types also informs the process of +initializing the fields of a record and its parents. Constructor +procedures that generate new instances of a record type are obtained +from a record constructor descriptor, which encapsulates the record-type +descriptor of the record to be constructed along with a @dfn{protocol} +procedure that defines how constructors for record subtypes delegate to +the constructors of their parent types. + +A protocol is a procedure used by the record system at construction time +to bind arguments to the fields of the record being constructed. The +protocol procedure is passed a procedure @var{n} that accepts the +arguments required to construct the record's parent type; this +procedure, when invoked, will return a procedure @var{p} that accepts +the arguments required to construct a new instance of the record type +itself and returns a new instance of the record type. + +The protocol should in turn return a procedure that uses @var{n} and +@var{p} to initialize the fields of the record type and its parent +type(s). This procedure will be the constructor returned by + +As a trivial example, consider the hypothetical record type +@code{pixel}, which encapsulates an x-y location on a screen, and +@code{voxel}, which has @code{pixel} as its parent type and stores an +additional coordinate. The following protocol produces a constructor +procedure that accepts all three coordinates, uses the first two to +initialize the fields of @code{pixel}, and binds the third to the single +field of @code{voxel}. + +@lisp + (lambda (n) + (lambda (x y z) + (let ((p (n x y))) + (p z)))) +@end lisp + +It may be helpful to think of protocols as ``constructor factories'' +that produce chains of delegating constructors glued together by the +helper procedure @var{n}. + +An R6RS record type may be declared to be @dfn{nongenerative} via the +use of a unique generated or user-supplied symbol---or +@dfn{uid}---such that subsequent record type declarations with the same +uid and attributes will return the previously-declared record-type +descriptor. + +R6RS record types may also be declared to be @dfn{opaque}, in which case +the various predicates and introspection procedures defined in +@code{(rnrs records introspection)} will behave as if records of this +type are not records at all. + +Note that while the R6RS records API shares much of its namespace with +both the SRFI-9 and native Guile records APIs, it is not currently +compatible with either. + +@node rnrs records syntactic +@subsubsection rnrs records syntactic + +The @code{(rnrs records syntactic (6))} library exports the syntactic +API for working with R6RS records. + +@deffn {Scheme Syntax} define-record-type name-spec record-clause @dots{} +Defines a new record type, introducing bindings for a record-type +descriptor, a record constructor descriptor, a constructor procedure, +a record predicate, and accessor and mutator procedures for the new +record type's fields. + +@var{name-spec} must either be an identifier or must take the form +@code{(record-name constructor-name predicate-name)}, where +@var{record-name}, @var{constructor-name}, and @var{predicate-name} are +all identifiers and specify the names to which, respectively, the +record-type descriptor, constructor, and predicate procedures will be +bound. If @var{name-spec} is only an identifier, it specifies the name +to which the generated record-type descriptor will be bound. + +Each @var{record-clause} must be one of the following: + +@itemize @bullet +@item +@code{(fields field-spec*)}, where each @var{field-spec} specifies a +field of the new record type and takes one of the following forms: +@itemize @bullet +@item +@code{(immutable field-name accessor-name)}, which specifies an +immutable field with the name @var{field-name} and binds an accessor +procedure for it to the name given by @var{accessor-name} +@item +@code{(mutable field-name accessor-name mutator-name)}, which specifies +a mutable field with the name @var{field-name} and binds accessor and +mutator procedures to @var{accessor-name} and @var{mutator-name}, +respectively +@item +@code{(immutable field-name)}, which specifies an immutable field with +the name @var{field-name}; an accessor procedure for it will be created +and named by appending record name and @var{field-name} with a hyphen +separator +@item +@code{(mutable field-name}), which specifies a mutable field with the +name @var{field-name}; an accessor procedure for it will be created and +named as described above; a mutator procedure will also be created and +named by appending @code{-set!} to the accessor name +@item +@code{field-name}, which specifies an immutable field with the name +@var{field-name}; an access procedure for it will be created and named +as described above +@end itemize +@item +@code{(parent parent-name)}, where @var{parent-name} is a symbol giving +the name of the record type to be used as the parent of the new record +type +@item +@code{(protocol expression)}, where @var{expression} evaluates to a +protocol procedure which behaves as described above, and is used to +create a record constructor descriptor for the new record type +@item +@code{(sealed sealed?)}, where @var{sealed?} is a boolean value that +specifies whether or not the new record type is sealed +@item +@code{(opaque opaque?)}, where @var{opaque?} is a boolean value that +specifies whether or not the new record type is opaque +@item +@code{(nongenerative [uid])}, which specifies that the record type is +nongenerative via the optional uid @var{uid}. If @var{uid} is not +specified, a unique uid will be generated at expansion time +@item +@code{(parent-rtd parent-rtd parent-cd)}, a more explicit form of the +@code{parent} form above; @var{parent-rtd} and @var{parent-cd} should +evaluate to a record-type descriptor and a record constructor +descriptor, respectively +@end itemize +@end deffn + +@deffn {Scheme Syntax} record-type-descriptor record-name +Evaluates to the record-type descriptor associated with the type +specified by @var{record-name}. +@end deffn + +@deffn {Scheme Syntax} record-constructor-descriptor record-name +Evaluates to the record-constructor descriptor associated with the type +specified by @var{record-name}. +@end deffn + +@node rnrs records procedural +@subsubsection rnrs records procedural + +The @code{(rnrs records procedural (6))} library exports the procedural +API for working with R6RS records. + +@deffn {Scheme Procedure} make-record-type-descriptor name parent uid sealed? opaque? fields +Returns a new record-type descriptor with the specified characteristics: +@var{name} must be a symbol giving the name of the new record type; +@var{parent} must be either @code{#f} or a non-sealed record-type +descriptor for the returned record type to extend; @var{uid} must be +either @code{#f}, indicating that the record type is generative, or +a symbol giving the type's nongenerative uid; @var{sealed?} and +@var{opaque?} must be boolean values that specify the sealedness and +opaqueness of the record type; @var{fields} must be a vector of zero or +more field specifiers of the form @code{(mutable name)} or +@code{(immutable name)}, where name is a symbol giving a name for the +field. + +If @var{uid} is not @code{#f}, it must be a symbol +@end deffn + +@deffn {Scheme Procedure} record-type-descriptor? obj +Returns @code{#t} if @var{obj} is a record-type descriptor, @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} make-record-constructor-descriptor rtd parent-constructor-descriptor protocol +Returns a new record constructor descriptor that can be used to produce +constructors for the record type specified by the record-type descriptor +@var{rtd} and whose delegation and binding behavior are specified by the +protocol procedure @var{protocol}. + +@var{parent-constructor-descriptor} specifies a record constructor +descriptor for the parent type of @var{rtd}, if one exists. If +@var{rtd} represents a base type, then +@var{parent-constructor-descriptor} must be @code{#f}. If @var{rtd} +is an extension of another type, @var{parent-constructor-descriptor} may +still be @code{#f}, but protocol must also be @code{#f} in this case. +@end deffn + +@deffn {Scheme Procedure} record-constructor rcd +Returns a record constructor procedure by invoking the protocol +defined by the record-constructor descriptor @var{rcd}. +@end deffn + +@deffn {Scheme Procedure} record-predicate rtd +Returns the record predicate procedure for the record-type descriptor +@var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-accessor rtd k +Returns the record field accessor procedure for the @var{k}th field of +the record-type descriptor @var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-mutator rtd k +Returns the record field mutator procedure for the @var{k}th field of +the record-type descriptor @var{rtd}. An @code{&assertion} condition +will be raised if this field is not mutable. +@end deffn + +@node rnrs records inspection +@subsubsection rnrs records inspection + +The @code{(rnrs records inspection (6))} library provides procedures +useful for accessing metadata about R6RS records. + +@deffn {Scheme Procedure} record? obj +Return @code{#t} if the specified object is a non-opaque R6RS record, +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} record-rtd record +Returns the record-type descriptor for @var{record}. An +@code{&assertion} is raised if @var{record} is opaque. +@end deffn + +@deffn {Scheme Procedure} record-type-name rtd +Returns the name of the record-type descriptor @var{rtd}. +@end deffn + +@deffn {Scheme Procedure} record-type-parent rtd +Returns the parent of the record-type descriptor @var{rtd}, or @code{#f} +if it has none. +@end deffn + +@deffn {Scheme Procedure} record-type-uid rtd +Returns the uid of the record-type descriptor @var{rtd}, or @code{#f} if +it has none. +@end deffn + +@deffn {Scheme Procedure} record-type-generative? rtd +Returns @code{#t} if the record-type descriptor @var{rtd} is generative, +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} record-type-sealed? rtd +Returns @code{#t} if the record-type descriptor @var{rtd} is sealed, +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} record-type-opaque? rtd +Returns @code{#t} if the record-type descriptor @var{rtd} is opaque, +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} record-type-field-names rtd +Returns a vector of symbols giving the names of the fields defined by +the record-type descriptor @var{rtd} (and not any of its sub- or +supertypes). +@end deffn + +@deffn {Scheme Procedure} record-field-mutable? rtd k +Returns @code{#t} if the field at index @var{k} of the record-type +descriptor @var{rtd} (and not any of its sub- or supertypes) is mutable. +@end deffn + +@node rnrs exceptions +@subsubsection rnrs exceptions + +The @code{(rnrs exceptions (6))} library provides functionality related +to signaling and handling exceptional situations. This functionality is +similar to the exception handling systems provided by Guile's core +library @xref{Exceptions}, and by the SRFI-18 and SRFI-34 +modules---@xref{SRFI-18 Exceptions}, and @ref{SRFI-34}, +respectively---but there are some key differences in concepts and +behavior. + +A raised exception may be @dfn{continuable} or @dfn{non-continuable}. +When an exception is raised non-continuably, another exception, with the +condition type @code{&non-continuable}, will be raised when the +exception handler returns locally. Raising an exception continuably +captures the current continuation and invokes it after a local return +from the exception handler. + +Like SRFI-18 and SRFI-34, R6RS exceptions are implemented on top of +Guile's native @code{throw} and @code{catch} forms, and use custom +``throw keys'' to identify their exception types. As a consequence, +Guile's @code{catch} form can handle exceptions thrown by these APIs, +but the reverse is not true: Handlers registered by the +@code{with-exception-handler} procedure described below will only be +called on exceptions thrown by the corresponding @code{raise} procedure. + +@deffn {Scheme Procedure} with-exception-handler handler thunk +Installs @var{handler}, which must be a procedure taking one argument, +as the current exception handler during the invocation of @var{thunk}, a +procedure taking zero arguments. The handler in place at the time +@code{with-exception-handler} is called is made current again once +either @var{thunk} returns or @var{handler} is invoked after an +exception is thrown from within @var{thunk}. + +This procedure is similar to the @code{with-throw-handler} procedure +provided by Guile's code library; (@pxref{Throw Handlers}). +@end deffn + +@deffn {Scheme Syntax} guard (variable clause1 clause2 ...) body +Evaluates the expression given by @var{body}, first creating an ad hoc +exception handler that binds a raised exception to @var{variable} and +then evaluates the specified @var{clause}s as if they were part of a +@code{cond} expression, with the value of the first matching clause +becoming the value of the @code{guard} expression +(@pxref{Conditionals}). If none of the clause's test expressions +evaluates to @code{#t}, the exception is re-raised, with the exception +handler that was current before the evaluation of the @code{guard} form. + +For example, the expression + +@lisp +(guard (ex ((eq? ex 'foo) 'bar) ((eq? ex 'bar) 'baz)) + (raise 'bar)) +@end lisp + +evaluates to @code{baz}. +@end deffn + +@deffn {Scheme Procedure} raise obj +Raises a non-continuable exception by invoking the currently-installed +exception handler on @var{obj}. If the handler returns, a +@code{&non-continuable} exception will be raised in the dynamic context +in which the handler was installed. +@end deffn + +@deffn {Scheme Procedure} raise-continuable obj +Raises a continuable exception by invoking currently-installed exception +handler on @var{obj}. +@end deffn + +@node rnrs conditions +@subsubsection rnrs conditions + +The @code{(rnrs condition (6))} library provides forms and procedures +for constructing new condition types, as well as a library of +pre-defined condition types that represent a variety of common +exceptional situations. Conditions are records of a subtype of the +@code{&condition} record type, which is neither sealed nor opaque. +@xref{R6RS Records}. + +Conditions may be manipulated singly, as @dfn{simple conditions}, or +when composed with other conditions to form @dfn{compound conditions}. +Compound conditions do not ``nest''---constructing a new compound +condition out of existing compound conditions will ``flatten'' them +into their component simple conditions. For example, making a new +condition out of a @code{&message} condition and a compound condition +that contains an @code{&assertion} condition and another @code{&message} +condition will produce a compound condition that contains two +@code{&message} conditions and one @code{&assertion} condition. + +The record type predicates and field accessors described below can +operate on either simple or compound conditions. In the latter case, +the predicate returns @code{#t} if the compound condition contains a +component simple condition of the appropriate type; the field accessors +return the requisite fields from the first component simple condition +found to be of the appropriate type. + +This library is quite similar to the SRFI-35 conditions module +(@pxref{SRFI-35}). Among other minor differences, the +@code{(rnrs conditions)} library features slightly different semantics +around condition field accessors, and comes with a larger number of +pre-defined condition types. The two APIs are not currently compatible, +however; the @code{condition?} predicate from one API will return +@code{#f} when applied to a condition object created in the other. + +@deffn {Condition Type} &condition +@deffnx {Scheme Procedure} condition? obj +The base record type for conditions. +@end deffn + +@deffn {Scheme Procedure} condition condition1 ... +@deffnx {Scheme Procedure} simple-conditions condition +The @code{condition} procedure creates a new compound condition out of +its condition arguments, flattening any specified compound conditions +into their component simple conditions as described above. + +@code{simple-conditions} returns a list of the component simple +conditions of the compound condition @code{condition}, in the order in +which they were specified at construction time. +@end deffn + +@deffn {Scheme Procedure} condition-predicate rtd +@deffnx {Scheme Procedure} condition-accessor rtd proc +These procedures return condition predicate and accessor procedures for +the specified condition record type @var{rtd}. +@end deffn + +@deffn {Scheme Syntax} define-condition-type condition-type supertype constructor predicate field-spec ... +Evaluates to a new record type definition for a condition type with the +name @var{condition-type} that has the condition type @var{supertype} as +its parent. A default constructor, which binds its arguments to the +fields of this type and its parent types, will be bound to the +identifier @var{constructor}; a condition predicate will be bound to +@var{predicate}. The fields of the new type, which are immutable, are +specified by the @var{field-spec}s, each of which must be of the form: +@lisp +(field accessor) +@end lisp +where @var{field} gives the name of the field and @var{accessor} gives +the name for a binding to an accessor procedure created for this field. +@end deffn + +@deffn {Condition Type} &message +@deffnx {Scheme Procedure} make-message-condition message +@deffnx {Scheme Procedure} message-condition? obj +@deffnx {Scheme Procedure} condition-message condition +A type that includes a message describing the condition that occurred. +@end deffn + +@deffn {Condition Type} &warning +@deffnx {Scheme Procedure} make-warning +@deffnx {Scheme Procedure} warning? obj +A base type for representing non-fatal conditions during execution. +@end deffn + +@deffn {Condition Type} &serious +@deffnx {Scheme Procedure} make-serious-condition +@deffnx {Scheme Procedure} serious-condition? obj +A base type for conditions representing errors serious enough that +cannot be ignored. +@end deffn + +@deffn {Condition Type} &error +@deffnx {Scheme Procedure} make-error +@deffnx {Scheme Procedure} error? obj +A base type for conditions representing errors. +@end deffn + +@deffn {Condition Type} &violation +@deffnx {Scheme Procedure} make-violation +@deffnx {Scheme Procedure} violation? +A subtype of @code{&serious} that can be used to represent violations +of a language or library standard. +@end deffn + +@deffn {Condition Type} &assertion +@deffnx {Scheme Procedure} make-assertion-violation +@deffnx {Scheme Procedure} assertion-violation? obj +A subtype of @code{&violation} that indicates an invalid call to a +procedure. +@end deffn + +@deffn {Condition Type} &irritants +@deffnx {Scheme Procedure} make-irritants-condition irritants +@deffnx {Scheme Procedure} irritants-condition? obj +@deffnx {Scheme Procedure} condition-irritants condition +A base type used for storing information about the causes of another +condition in a compound condition. +@end deffn + +@deffn {Condition Type} &who +@deffnx {Scheme Procedure} make-who-condition who +@deffnx {Scheme Procedure} who-condition? obj +@deffnx {Scheme Procedure} condition-who condition +A base type used for storing the identity, a string or symbol, of the +entity responsible for another condition in a compound condition. +@end deffn + +@deffn {Condition Type} &non-continuable +@deffnx {Scheme Procedure} make-non-continuable-violation +@deffnx {Scheme Procedure} non-continuable-violation? obj +A subtype of @code{&violation} used to indicate that an exception +handler invoked by @code{raise} has returned locally. +@end deffn + +@deffn {Condition Type} &implementation-restriction +@deffnx {Scheme Procedure} make-implementation-restriction-violation +@deffnx {Scheme Procedure} implementation-restriction-violation? obj +A subtype of @code{&violation} used to indicate a violation of an +implementation restriction. +@end deffn + +@deffn {Condition Type} &lexical +@deffnx {Scheme Procedure} make-lexical-violation +@deffnx {Scheme Procedure} lexical-violation? obj +A subtype of @code{&violation} used to indicate a syntax violation at +the level of the datum syntax. +@end deffn + +@deffn {Condition Type} &syntax +@deffnx {Scheme Procedure} make-syntax-violation form subform +@deffnx {Scheme Procedure} syntax-violation? obj +@deffnx {Scheme Procedure} syntax-violation-form condition +@deffnx {Scheme Procedure} syntax-violation-subform condition +A subtype of @code{&violation} that indicates a syntax violation. The +@var{form} and @var{subform} fields, which must be datum values, +indicate the syntactic form responsible for the condition. +@end deffn + +@deffn {Condition Type} &undefined +@deffnx {Scheme Procedure} make-undefined-violation +@deffnx {Scheme Procedure} undefined-violation? obj +A subtype of @code{&violation} that indicates a reference to an unbound +identifier. +@end deffn + +@node R6RS I/O Conditions +@subsubsection I/O Conditions + +These condition types are exported by both the +@code{(rnrs io ports (6))} and @code{(rnrs io simple (6))} libraries. + +@deffn {Condition Type} &i/o +@deffnx {Scheme Procedure} make-i/o-error +@deffnx {Scheme Procedure} i/o-error? obj +A condition supertype for more specific I/O errors. +@end deffn + +@deffn {Condition Type} &i/o-read +@deffnx {Scheme Procedure} make-i/o-read-error +@deffnx {Scheme Procedure} i/o-read-error? obj +A subtype of @code{&i/o}; represents read-related I/O errors. +@end deffn + +@deffn {Condition Type} &i/o-write +@deffnx {Scheme Procedure} make-i/o-write-error +@deffnx {Scheme Procedure} i/o-write-error? obj +A subtype of @code{&i/o}; represents write-related I/O errors. +@end deffn + +@deffn {Condition Type} &i/o-invalid-position +@deffnx {Scheme Procedure} make-i/o-invalid-position-error position +@deffnx {Scheme Procedure} i/o-invalid-position-error? obj +@deffnx {Scheme Procedure} i/o-error-position condition +A subtype of @code{&i/o}; represents an error related to an attempt to +set the file position to an invalid position. +@end deffn + +@deffn {Condition Type} &i/o-filename +@deffnx {Scheme Procedure} make-io-filename-error filename +@deffnx {Scheme Procedure} i/o-filename-error? obj +@deffnx {Scheme Procedure} i/o-error-filename condition +A subtype of @code{&i/o}; represents an error related to an operation on +a named file. +@end deffn + +@deffn {Condition Type} &i/o-file-protection +@deffnx {Scheme Procedure} make-i/o-file-protection-error filename +@deffnx {Scheme Procedure} i/o-file-protection-error? obj +A subtype of @code{&i/o-filename}; represents an error resulting from an +attempt to access a named file for which the caller had insufficient +permissions. +@end deffn + +@deffn {Condition Type} &i/o-file-is-read-only +@deffnx {Scheme Procedure} make-i/o-file-is-read-only-error filename +@deffnx {Scheme Procedure} i/o-file-is-read-only-error? obj +A subtype of @code{&i/o-file-protection}; represents an error related to +an attempt to write to a read-only file. +@end deffn + +@deffn {Condition Type} &i/o-file-already-exists +@deffnx {Scheme Procedure} make-i/o-file-already-exists-error filename +@deffnx {Scheme Procedure} i/o-file-already-exists-error? obj +A subtype of @code{&i/o-filename}; represents an error related to an +operation on an existing file that was assumed not to exist. +@end deffn + +@deffn {Condition Type} &i/o-file-does-not-exist +@deffnx {Scheme Procedure} make-i/o-file-does-not-exist-error +@deffnx {Scheme Procedure} i/o-file-does-not-exist-error? obj +A subtype of @code{&i/o-filename}; represents an error related to an +operation on a non-existent file that was assumed to exist. +@end deffn + +@deffn {Condition Type} &i/o-port +@deffnx {Scheme Procedure} make-i/o-port-error port +@deffnx {Scheme Procedure} i/o-port-error? obj +@deffnx {Scheme Procedure} i/o-error-port condition +A subtype of @code{&i/o}; represents an error related to an operation on +the port @var{port}. +@end deffn + +@node R6RS Transcoders +@subsubsection Transcoders +@cindex codec +@cindex end-of-line style +@cindex transcoder +@cindex binary port +@cindex textual port + +The transcoder facilities are exported by @code{(rnrs io ports)}. + +Several different Unicode encoding schemes describe standard ways to +encode characters and strings as byte sequences and to decode those +sequences. Within this document, a @dfn{codec} is an immutable Scheme +object that represents a Unicode or similar encoding scheme. + +An @dfn{end-of-line style} is a symbol that, if it is not @code{none}, +describes how a textual port transcodes representations of line endings. + +A @dfn{transcoder} is an immutable Scheme object that combines a codec +with an end-of-line style and a method for handling decoding errors. +Each transcoder represents some specific bidirectional (but not +necessarily lossless), possibly stateful translation between byte +sequences and Unicode characters and strings. Every transcoder can +operate in the input direction (bytes to characters) or in the output +direction (characters to bytes). A @var{transcoder} parameter name +means that the corresponding argument must be a transcoder. + +A @dfn{binary port} is a port that supports binary I/O, does not have an +associated transcoder and does not support textual I/O. A @dfn{textual +port} is a port that supports textual I/O, and does not support binary +I/O. A textual port may or may not have an associated transcoder. + +@deffn {Scheme Procedure} latin-1-codec +@deffnx {Scheme Procedure} utf-8-codec +@deffnx {Scheme Procedure} utf-16-codec + +These are predefined codecs for the ISO 8859-1, UTF-8, and UTF-16 +encoding schemes. + +A call to any of these procedures returns a value that is equal in the +sense of @code{eqv?} to the result of any other call to the same +procedure. +@end deffn + +@deffn {Scheme Syntax} eol-style @var{eol-style-symbol} + +@var{eol-style-symbol} should be a symbol whose name is one of +@code{lf}, @code{cr}, @code{crlf}, @code{nel}, @code{crnel}, @code{ls}, +and @code{none}. + +The form evaluates to the corresponding symbol. If the name of +@var{eol-style-symbol} is not one of these symbols, the effect and +result are implementation-dependent; in particular, the result may be an +eol-style symbol acceptable as an @var{eol-style} argument to +@code{make-transcoder}. Otherwise, an exception is raised. + +All eol-style symbols except @code{none} describe a specific +line-ending encoding: + +@table @code +@item lf +linefeed +@item cr +carriage return +@item crlf +carriage return, linefeed +@item nel +next line +@item crnel +carriage return, next line +@item ls +line separator +@end table + +For a textual port with a transcoder, and whose transcoder has an +eol-style symbol @code{none}, no conversion occurs. For a textual input +port, any eol-style symbol other than @code{none} means that all of the +above line-ending encodings are recognized and are translated into a +single linefeed. For a textual output port, @code{none} and @code{lf} +are equivalent. Linefeed characters are encoded according to the +specified eol-style symbol, and all other characters that participate in +possible line endings are encoded as is. + +@quotation Note + Only the name of @var{eol-style-symbol} is significant. +@end quotation +@end deffn + +@deffn {Scheme Procedure} native-eol-style +Returns the default end-of-line style of the underlying platform, e.g., +@code{lf} on Unix and @code{crlf} on Windows. +@end deffn + +@deffn {Condition Type} &i/o-decoding +@deffnx {Scheme Procedure} make-i/o-decoding-error port +@deffnx {Scheme Procedure} i/o-decoding-error? obj +This condition type could be defined by + +@lisp +(define-condition-type &i/o-decoding &i/o-port + make-i/o-decoding-error i/o-decoding-error?) +@end lisp + +An exception with this type is raised when one of the operations for +textual input from a port encounters a sequence of bytes that cannot be +translated into a character or string by the input direction of the +port's transcoder. + +When such an exception is raised, the port's position is past the +invalid encoding. +@end deffn + +@deffn {Condition Type} &i/o-encoding +@deffnx {Scheme Procedure} make-i/o-encoding-error port char +@deffnx {Scheme Procedure} i/o-encoding-error? obj +@deffnx {Scheme Procedure} i/o-encoding-error-char condition +This condition type could be defined by + +@lisp +(define-condition-type &i/o-encoding &i/o-port + make-i/o-encoding-error i/o-encoding-error? + (char i/o-encoding-error-char)) +@end lisp + +An exception with this type is raised when one of the operations for +textual output to a port encounters a character that cannot be +translated into bytes by the output direction of the port's transcoder. +@var{char} is the character that could not be encoded. +@end deffn + +@deffn {Scheme Syntax} error-handling-mode @var{error-handling-mode-symbol} +@var{error-handling-mode-symbol} should be a symbol whose name is one of +@code{ignore}, @code{raise}, and @code{replace}. The form evaluates to +the corresponding symbol. If @var{error-handling-mode-symbol} is not +one of these identifiers, effect and result are +implementation-dependent: The result may be an error-handling-mode +symbol acceptable as a @var{handling-mode} argument to +@code{make-transcoder}. If it is not acceptable as a +@var{handling-mode} argument to @code{make-transcoder}, an exception is +raised. + +@quotation Note + Only the name of @var{error-handling-mode-symbol} is significant. +@end quotation + +The error-handling mode of a transcoder specifies the behavior +of textual I/O operations in the presence of encoding or decoding +errors. + +If a textual input operation encounters an invalid or incomplete +character encoding, and the error-handling mode is @code{ignore}, an +appropriate number of bytes of the invalid encoding are ignored and +decoding continues with the following bytes. + +If the error-handling mode is @code{replace}, the replacement +character U+FFFD is injected into the data stream, an appropriate +number of bytes are ignored, and decoding +continues with the following bytes. + +If the error-handling mode is @code{raise}, an exception with condition +type @code{&i/o-decoding} is raised. + +If a textual output operation encounters a character it cannot encode, +and the error-handling mode is @code{ignore}, the character is ignored +and encoding continues with the next character. If the error-handling +mode is @code{replace}, a codec-specific replacement character is +emitted by the transcoder, and encoding continues with the next +character. The replacement character is U+FFFD for transcoders whose +codec is one of the Unicode encodings, but is the @code{?} character +for the Latin-1 encoding. If the error-handling mode is @code{raise}, +an exception with condition type @code{&i/o-encoding} is raised. +@end deffn + +@deffn {Scheme Procedure} make-transcoder codec +@deffnx {Scheme Procedure} make-transcoder codec eol-style +@deffnx {Scheme Procedure} make-transcoder codec eol-style handling-mode +@var{codec} must be a codec; @var{eol-style}, if present, an eol-style +symbol; and @var{handling-mode}, if present, an error-handling-mode +symbol. + +@var{eol-style} may be omitted, in which case it defaults to the native +end-of-line style of the underlying platform. @var{handling-mode} may +be omitted, in which case it defaults to @code{replace}. The result is +a transcoder with the behavior specified by its arguments. +@end deffn + +@deffn {Scheme procedure} native-transcoder +Returns an implementation-dependent transcoder that represents a +possibly locale-dependent ``native'' transcoding. +@end deffn + +@deffn {Scheme Procedure} transcoder-codec transcoder +@deffnx {Scheme Procedure} transcoder-eol-style transcoder +@deffnx {Scheme Procedure} transcoder-error-handling-mode transcoder +These are accessors for transcoder objects; when applied to a +transcoder returned by @code{make-transcoder}, they return the +@var{codec}, @var{eol-style}, and @var{handling-mode} arguments, +respectively. +@end deffn + +@deffn {Scheme Procedure} bytevector->string bytevector transcoder +Returns the string that results from transcoding the +@var{bytevector} according to the input direction of the transcoder. +@end deffn + +@deffn {Scheme Procedure} string->bytevector string transcoder +Returns the bytevector that results from transcoding the +@var{string} according to the output direction of the transcoder. +@end deffn + +@node rnrs io ports +@subsubsection rnrs io ports + +@cindex R6RS +@cindex R6RS ports +Guile's binary and textual port interface was heavily inspired by R6RS, +so many R6RS port interfaces are documented elsewhere. Note that R6RS +ports are not disjoint from Guile's native ports, so Guile-specific +procedures will work on ports created using the R6RS API, and vice +versa. Also note that in Guile, all ports are both textual and binary. +@xref{Input and Output}, for more on Guile's core port API. The R6RS +ports module wraps Guile's I/O routines in a helper that will translate +native Guile exceptions to R6RS conditions; @xref{R6RS I/O Conditions}, +for more. @xref{R6RS File Ports}, for documentation on the R6RS file +port interface. + +@c FIXME: Update description when implemented. +@emph{Note}: The implementation of this R6RS API is not complete yet. + +@deffn {Scheme Procedure} eof-object? obj +@xref{Binary I/O}, for documentation. +@end deffn + +@deffn {Scheme Procedure} eof-object +Return the end-of-file (EOF) object. + +@lisp +(eof-object? (eof-object)) +@result{} #t +@end lisp +@end deffn + +@deffn {Scheme Procedure} port? obj +@deffnx {Scheme Procedure} input-port? obj +@deffnx {Scheme Procedure} output-port? obj +@xref{Ports}, for documentation. +@end deffn + +@deffn {Scheme Procedure} port-transcoder port +Return a transcoder associated with the encoding of @var{port}. +@xref{Encoding}, and @xref{R6RS Transcoders}. +@end deffn + +@deffn {Scheme Procedure} binary-port? port +@deffnx {Scheme Procedure} textual-port? port +Return @code{#t}, as all ports in Guile are suitable for binary and +textual I/O. @xref{Encoding}, for more details. +@end deffn + +@deffn {Scheme Procedure} transcoded-port binary-port transcoder +The @code{transcoded-port} procedure +returns a new textual port with the specified @var{transcoder}. +Otherwise the new textual port's state is largely the same as +that of @var{binary-port}. +If @var{binary-port} is an input port, the new textual +port will be an input port and +will transcode the bytes that have not yet been read from +@var{binary-port}. +If @var{binary-port} is an output port, the new textual +port will be an output port and +will transcode output characters into bytes that are +written to the byte sink represented by @var{binary-port}. + +As a side effect, however, @code{transcoded-port} +closes @var{binary-port} in +a special way that allows the new textual port to continue to +use the byte source or sink represented by @var{binary-port}, +even though @var{binary-port} itself is closed and cannot +be used by the input and output operations described in this +chapter. +@end deffn + +@deffn {Scheme Procedure} port-position port +Equivalent to @code{(seek @var{port} SEEK_CUR 0)}. @xref{Random +Access}. +@end deffn + +@deffn {Scheme Procedure} port-has-port-position? port +Return @code{#t} is @var{port} supports @code{port-position}. +@end deffn + +@deffn {Scheme Procedure} set-port-position! port offset +Equivalent to @code{(seek @var{port} SEEK_SET @var{offset})}. +@xref{Random Access}. +@end deffn + +@deffn {Scheme Procedure} port-has-set-port-position!? port +Return @code{#t} is @var{port} supports @code{set-port-position!}. +@end deffn + +@deffn {Scheme Procedure} call-with-port port proc +Call @var{proc}, passing it @var{port} and closing @var{port} upon exit +of @var{proc}. Return the return values of @var{proc}. +@end deffn + +@deffn {Scheme Procedure} port-eof? input-port +Equivalent to @code{(eof-object? (lookahead-u8 @var{input-port}))}. +@end deffn + +@deffn {Scheme Procedure} standard-input-port +@deffnx {Scheme Procedure} standard-output-port +@deffnx {Scheme Procedure} standard-error-port +Returns a fresh binary input port connected to standard input, or a +binary output port connected to the standard output or standard error, +respectively. Whether the port supports the @code{port-position} and +@code{set-port-position!} operations is implementation-dependent. +@end deffn + +@deffn {Scheme Procedure} current-input-port +@deffnx {Scheme Procedure} current-output-port +@deffnx {Scheme Procedure} current-error-port +@xref{Default Ports}. +@end deffn + +@deffn {Scheme Procedure} open-bytevector-input-port bv [transcoder] +@deffnx {Scheme Procedure} open-bytevector-output-port [transcoder] +@xref{Bytevector Ports}. +@end deffn + +@deffn {Scheme Procedure} make-custom-binary-input-port id read! get-position set-position! close +@deffnx {Scheme Procedure} make-custom-binary-output-port id write! get-position set-position! close +@deffnx {Scheme Procedure} make-custom-binary-input/output-port id read! write! get-position set-position! close +@xref{Custom Ports}. +@end deffn + +@deffn {Scheme Procedure} get-u8 port +@deffnx {Scheme Procedure} lookahead-u8 port +@deffnx {Scheme Procedure} get-bytevector-n port count +@deffnx {Scheme Procedure} get-bytevector-n! port bv start count +@deffnx {Scheme Procedure} get-bytevector-some port +@deffnx {Scheme Procedure} get-bytevector-all port +@deffnx {Scheme Procedure} put-u8 port octet +@deffnx {Scheme Procedure} put-bytevector port bv [start [count]] +@xref{Binary I/O}. +@end deffn + +@deffn {Scheme Procedure} get-char textual-input-port +@deffnx {Scheme Procedure} lookahead-char textual-input-port +@deffnx {Scheme Procedure} get-string-n textual-input-port count +@deffnx {Scheme Procedure} get-string-n! textual-input-port string start count +@deffnx {Scheme Procedure} get-string-all textual-input-port +@deffnx {Scheme Procedure} get-line textual-input-port +@deffnx {Scheme Procedure} put-char port char +@deffnx {Scheme Procedure} put-string port string [start [count]] +@xref{Textual I/O}. +@end deffn + +@deffn {Scheme Procedure} get-datum textual-input-port count +Reads an external representation from @var{textual-input-port} and returns the +datum it represents. The @code{get-datum} procedure returns the next +datum that can be parsed from the given @var{textual-input-port}, updating +@var{textual-input-port} to point exactly past the end of the external +representation of the object. + +Any @emph{interlexeme space} (comment or whitespace, @pxref{Scheme +Syntax}) in the input is first skipped. If an end of file occurs after +the interlexeme space, the end-of-file object is returned. + +If a character inconsistent with an external representation is +encountered in the input, an exception with condition types +@code{&lexical} and @code{&i/o-read} is raised. Also, if the end of +file is encountered after the beginning of an external representation, +but the external representation is incomplete and therefore cannot be +parsed, an exception with condition types @code{&lexical} and +@code{&i/o-read} is raised. +@end deffn + +@deffn {Scheme Procedure} put-datum textual-output-port datum +@var{datum} should be a datum value. The @code{put-datum} procedure +writes an external representation of @var{datum} to +@var{textual-output-port}. The specific external representation is +implementation-dependent. However, whenever possible, an implementation +should produce a representation for which @code{get-datum}, when reading +the representation, will return an object equal (in the sense of +@code{equal?}) to @var{datum}. + +@quotation Note + Not all datums may allow producing an external representation for which + @code{get-datum} will produce an object that is equal to the + original. Specifically, NaNs contained in @var{datum} may make + this impossible. +@end quotation + +@quotation Note + The @code{put-datum} procedure merely writes the external + representation, but no trailing delimiter. If @code{put-datum} is + used to write several subsequent external representations to an + output port, care should be taken to delimit them properly so they can + be read back in by subsequent calls to @code{get-datum}. +@end quotation +@end deffn + +@deffn {Scheme Procedure} flush-output-port port +@xref{Buffering}, for documentation on @code{force-output}. +@end deffn + +@node R6RS File Ports +@subsubsection R6RS File Ports + +The facilities described in this section are exported by the @code{(rnrs +io ports)} module. + +@deffn {Scheme Syntax} buffer-mode @var{buffer-mode-symbol} +@var{buffer-mode-symbol} must be a symbol whose name is one of +@code{none}, @code{line}, and @code{block}. The result is the +corresponding symbol, and specifies the associated buffer mode. +@xref{Buffering}, for a discussion of these different buffer modes. To +control the amount of buffering, use @code{setvbuf} instead. Note that +only the name of @var{buffer-mode-symbol} is significant. + +@xref{Buffering}, for a discussion of port buffering. +@end deffn + +@deffn {Scheme Procedure} buffer-mode? obj +Returns @code{#t} if the argument is a valid buffer-mode symbol, and +returns @code{#f} otherwise. +@end deffn + +When opening a file, the various procedures accept a @code{file-options} +object that encapsulates flags to specify how the file is to be +opened. A @code{file-options} object is an enum-set (@pxref{rnrs enums}) +over the symbols constituting valid file options. + +A @var{file-options} parameter name means that the corresponding +argument must be a file-options object. + +@deffn {Scheme Syntax} file-options @var{file-options-symbol} ... + +Each @var{file-options-symbol} must be a symbol. + +The @code{file-options} syntax returns a file-options object that +encapsulates the specified options. + +When supplied to an operation that opens a file for output, the +file-options object returned by @code{(file-options)} specifies that the +file is created if it does not exist and an exception with condition +type @code{&i/o-file-already-exists} is raised if it does exist. The +following standard options can be included to modify the default +behavior. + +@table @code +@item no-create + If the file does not already exist, it is not created; + instead, an exception with condition type @code{&i/o-file-does-not-exist} + is raised. + If the file already exists, the exception with condition type + @code{&i/o-file-already-exists} is not raised + and the file is truncated to zero length. +@item no-fail + If the file already exists, the exception with condition type + @code{&i/o-file-already-exists} is not raised, + even if @code{no-create} is not included, + and the file is truncated to zero length. +@item no-truncate + If the file already exists and the exception with condition type + @code{&i/o-file-already-exists} has been inhibited by inclusion of + @code{no-create} or @code{no-fail}, the file is not truncated, but + the port's current position is still set to the beginning of the + file. +@end table + +These options have no effect when a file is opened only for input. +Symbols other than those listed above may be used as +@var{file-options-symbol}s; they have implementation-specific meaning, +if any. + +@quotation Note + Only the name of @var{file-options-symbol} is significant. +@end quotation +@end deffn + +@deffn {Scheme Procedure} open-file-input-port filename +@deffnx {Scheme Procedure} open-file-input-port filename file-options +@deffnx {Scheme Procedure} open-file-input-port filename file-options buffer-mode +@deffnx {Scheme Procedure} open-file-input-port filename file-options buffer-mode maybe-transcoder +@var{maybe-transcoder} must be either a transcoder or @code{#f}. + +The @code{open-file-input-port} procedure returns an +input port for the named file. The @var{file-options} and +@var{maybe-transcoder} arguments are optional. + +The @var{file-options} argument, which may determine various aspects of +the returned port, defaults to the value of @code{(file-options)}. + +The @var{buffer-mode} argument, if supplied, +must be one of the symbols that name a buffer mode. +The @var{buffer-mode} argument defaults to @code{block}. + +If @var{maybe-transcoder} is a transcoder, it becomes the transcoder associated +with the returned port. + +If @var{maybe-transcoder} is @code{#f} or absent, +the port will be a binary port and will support the +@code{port-position} and @code{set-port-position!} operations. +Otherwise the port will be a textual port, and whether it supports +the @code{port-position} and @code{set-port-position!} operations +is implementation-dependent (and possibly transcoder-dependent). +@end deffn + +@deffn {Scheme Procedure} open-file-output-port filename +@deffnx {Scheme Procedure} open-file-output-port filename file-options +@deffnx {Scheme Procedure} open-file-output-port filename file-options buffer-mode +@deffnx {Scheme Procedure} open-file-output-port filename file-options buffer-mode maybe-transcoder +@var{maybe-transcoder} must be either a transcoder or @code{#f}. + +The @code{open-file-output-port} procedure returns an output port for the named file. + +The @var{file-options} argument, which may determine various aspects of +the returned port, defaults to the value of @code{(file-options)}. + +The @var{buffer-mode} argument, if supplied, +must be one of the symbols that name a buffer mode. +The @var{buffer-mode} argument defaults to @code{block}. + +If @var{maybe-transcoder} is a transcoder, it becomes the transcoder +associated with the port. + +If @var{maybe-transcoder} is @code{#f} or absent, +the port will be a binary port and will support the +@code{port-position} and @code{set-port-position!} operations. +Otherwise the port will be a textual port, and whether it supports +the @code{port-position} and @code{set-port-position!} operations +is implementation-dependent (and possibly transcoder-dependent). +@end deffn + +@node rnrs io simple +@subsubsection rnrs io simple + +The @code{(rnrs io simple (6))} library provides convenience functions +for performing textual I/O on ports. This library also exports all of +the condition types and associated procedures described in (@pxref{R6RS +I/O Conditions}). In the context of this section, when stating that a +procedure behaves ``identically'' to the corresponding procedure in +Guile's core library, this is modulo the behavior wrt. conditions: such +procedures raise the appropriate R6RS conditions in case of error, but +otherwise behave identically. + +@c FIXME: remove the following note when proper condition behavior has +@c been verified. + +@quotation Note +There are still known issues regarding condition-correctness; some +errors may still be thrown as native Guile exceptions instead of the +appropriate R6RS conditions. +@end quotation + +@deffn {Scheme Procedure} eof-object +@deffnx {Scheme Procedure} eof-object? obj +These procedures are identical to the ones provided by the @code{(rnrs +io ports (6))} library. @xref{rnrs io ports}, for documentation. +@end deffn + +@deffn {Scheme Procedure} input-port? obj +@deffnx {Scheme Procedure} output-port? obj +These procedures are identical to the ones provided by Guile's core +library. @xref{Ports}, for documentation. +@end deffn + +@deffn {Scheme Procedure} call-with-input-file filename proc +@deffnx {Scheme Procedure} call-with-output-file filename proc +@deffnx {Scheme Procedure} open-input-file filename +@deffnx {Scheme Procedure} open-output-file filename +@deffnx {Scheme Procedure} with-input-from-file filename thunk +@deffnx {Scheme Procedure} with-output-to-file filename thunk +These procedures are identical to the ones provided by Guile's core +library. @xref{File Ports}, for documentation. +@end deffn + +@deffn {Scheme Procedure} close-input-port input-port +@deffnx {Scheme Procedure} close-output-port output-port +Closes the given @var{input-port} or @var{output-port}. These are +legacy interfaces; just use @code{close-port}. +@end deffn + +@deffn {Scheme Procedure} peek-char +@deffnx {Scheme Procedure} peek-char textual-input-port +@deffnx {Scheme Procedure} read-char +@deffnx {Scheme Procedure} read-char textual-input-port +These procedures are identical to the ones provided by Guile's core +library. @xref{Venerable Port Interfaces}, for documentation. +@end deffn + +@deffn {Scheme Procedure} read +@deffnx {Scheme Procedure} read textual-input-port +This procedure is identical to the one provided by Guile's core library. +@xref{Scheme Read}, for documentation. +@end deffn + +@deffn {Scheme Procedure} display obj +@deffnx {Scheme Procedure} display obj textual-output-port +@deffnx {Scheme Procedure} newline +@deffnx {Scheme Procedure} newline textual-output-port +@deffnx {Scheme Procedure} write obj +@deffnx {Scheme Procedure} write obj textual-output-port +@deffnx {Scheme Procedure} write-char char +@deffnx {Scheme Procedure} write-char char textual-output-port +These procedures are identical to the ones provided by Guile's core +library. @xref{Venerable Port Interfaces}, and @xref{Scheme Write}, for +documentation. +@end deffn + +@node rnrs files +@subsubsection rnrs files + +The @code{(rnrs files (6))} library provides the @code{file-exists?} and +@code{delete-file} procedures, which test for the existence of a file +and allow the deletion of files from the file system, respectively. + +These procedures are identical to the ones provided by Guile's core +library. @xref{File System}, for documentation. + +@node rnrs programs +@subsubsection rnrs programs + +The @code{(rnrs programs (6))} library provides procedures for +process management and introspection. + +@deffn {Scheme Procedure} command-line +This procedure is identical to the one provided by Guile's core library. +@xref{Runtime Environment}, for documentation. +@end deffn + +@deffn {Scheme Procedure} exit [status] +This procedure is identical to the one provided by Guile's core +library. @xref{Processes}, for documentation. +@end deffn + +@node rnrs arithmetic fixnums +@subsubsection rnrs arithmetic fixnums + +The @code{(rnrs arithmetic fixnums (6))} library provides procedures for +performing arithmetic operations on an implementation-dependent range of +exact integer values, which R6RS refers to as @dfn{fixnums}. In Guile, +the size of a fixnum is determined by the size of the @code{SCM} type; a +single SCM struct is guaranteed to be able to hold an entire fixnum, +making fixnum computations particularly +efficient---(@pxref{The SCM Type}). On 32-bit systems, the most +negative and most positive fixnum values are, respectively, -536870912 +and 536870911. + +Unless otherwise specified, all of the procedures below take fixnums as +arguments, and will raise an @code{&assertion} condition if passed a +non-fixnum argument or an @code{&implementation-restriction} condition +if their result is not itself a fixnum. + +@deffn {Scheme Procedure} fixnum? obj +Returns @code{#t} if @var{obj} is a fixnum, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} fixnum-width +@deffnx {Scheme Procedure} least-fixnum +@deffnx {Scheme Procedure} greatest-fixnum +These procedures return, respectively, the maximum number of bits +necessary to represent a fixnum value in Guile, the minimum fixnum +value, and the maximum fixnum value. +@end deffn + +@deffn {Scheme Procedure} fx=? fx1 fx2 fx3 ... +@deffnx {Scheme Procedure} fx>? fx1 fx2 fx3 ... +@deffnx {Scheme Procedure} fx<? fx1 fx2 fx3 ... +@deffnx {Scheme Procedure} fx>=? fx1 fx2 fx3 ... +@deffnx {Scheme Procedure} fx<=? fx1 fx2 fx3 ... +These procedures return @code{#t} if their fixnum arguments are +(respectively): equal, monotonically increasing, monotonically +decreasing, monotonically nondecreasing, or monotonically nonincreasing; +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} fxzero? fx +@deffnx {Scheme Procedure} fxpositive? fx +@deffnx {Scheme Procedure} fxnegative? fx +@deffnx {Scheme Procedure} fxodd? fx +@deffnx {Scheme Procedure} fxeven? fx +These numerical predicates return @code{#t} if @var{fx} is, +respectively, zero, greater than zero, less than zero, odd, or even; +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} fxmax fx1 fx2 ... +@deffnx {Scheme Procedure} fxmin fx1 fx2 ... +These procedures return the maximum or minimum of their arguments. +@end deffn + +@deffn {Scheme Procedure} fx+ fx1 fx2 +@deffnx {Scheme Procedure} fx* fx1 fx2 +These procedures return the sum or product of their arguments. +@end deffn + +@deffn {Scheme Procedure} fx- fx1 fx2 +@deffnx {Scheme Procedure} fx- fx +Returns the difference of @var{fx1} and @var{fx2}, or the negation of +@var{fx}, if called with a single argument. + +An @code{&assertion} condition is raised if the result is not itself a +fixnum. +@end deffn + +@deffn {Scheme Procedure} fxdiv-and-mod fx1 fx2 +@deffnx {Scheme Procedure} fxdiv fx1 fx2 +@deffnx {Scheme Procedure} fxmod fx1 fx2 +@deffnx {Scheme Procedure} fxdiv0-and-mod0 fx1 fx2 +@deffnx {Scheme Procedure} fxdiv0 fx1 fx2 +@deffnx {Scheme Procedure} fxmod0 fx1 fx2 +These procedures implement number-theoretic division on fixnums; +@xref{(rnrs base)}, for a description of their semantics. +@end deffn + +@deffn {Scheme Procedure} fx+/carry fx1 fx2 fx3 +Returns the two fixnum results of the following computation: +@lisp +(let* ((s (+ fx1 fx2 fx3)) + (s0 (mod0 s (expt 2 (fixnum-width)))) + (s1 (div0 s (expt 2 (fixnum-width))))) + (values s0 s1)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} fx-/carry fx1 fx2 fx3 +Returns the two fixnum results of the following computation: +@lisp +(let* ((d (- fx1 fx2 fx3)) + (d0 (mod0 d (expt 2 (fixnum-width)))) + (d1 (div0 d (expt 2 (fixnum-width))))) + (values d0 d1)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} fx*/carry fx1 fx2 fx3 +@lisp +Returns the two fixnum results of the following computation: +(let* ((s (+ (* fx1 fx2) fx3)) + (s0 (mod0 s (expt 2 (fixnum-width)))) + (s1 (div0 s (expt 2 (fixnum-width))))) + (values s0 s1)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} fxnot fx +@deffnx {Scheme Procedure} fxand fx1 ... +@deffnx {Scheme Procedure} fxior fx1 ... +@deffnx {Scheme Procedure} fxxor fx1 ... +These procedures are identical to the @code{lognot}, @code{logand}, +@code{logior}, and @code{logxor} procedures provided by Guile's core +library. @xref{Bitwise Operations}, for documentation. +@end deffn + +@deffn {Scheme Procedure} fxif fx1 fx2 fx3 +Returns the bitwise ``if'' of its fixnum arguments. The bit at position +@code{i} in the return value will be the @code{i}th bit from @var{fx2} +if the @code{i}th bit of @var{fx1} is 1, the @code{i}th bit from +@var{fx3}. +@end deffn + +@deffn {Scheme Procedure} fxbit-count fx +Returns the number of 1 bits in the two's complement representation of +@var{fx}. +@end deffn + +@deffn {Scheme Procedure} fxlength fx +Returns the number of bits necessary to represent @var{fx}. +@end deffn + +@deffn {Scheme Procedure} fxfirst-bit-set fx +Returns the index of the least significant 1 bit in the two's complement +representation of @var{fx}. +@end deffn + +@deffn {Scheme Procedure} fxbit-set? fx1 fx2 +Returns @code{#t} if the @var{fx2}th bit in the two's complement +representation of @var{fx1} is 1, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} fxcopy-bit fx1 fx2 fx3 +Returns the result of setting the @var{fx2}th bit of @var{fx1} to the +@var{fx2}th bit of @var{fx3}. +@end deffn + +@deffn {Scheme Procedure} fxbit-field fx1 fx2 fx3 +Returns the integer representation of the contiguous sequence of bits in +@var{fx1} that starts at position @var{fx2} (inclusive) and ends at +position @var{fx3} (exclusive). +@end deffn + +@deffn {Scheme Procedure} fxcopy-bit-field fx1 fx2 fx3 fx4 +Returns the result of replacing the bit field in @var{fx1} with start +and end positions @var{fx2} and @var{fx3} with the corresponding bit +field from @var{fx4}. +@end deffn + +@deffn {Scheme Procedure} fxarithmetic-shift fx1 fx2 +@deffnx {Scheme Procedure} fxarithmetic-shift-left fx1 fx2 +@deffnx {Scheme Procedure} fxarithmetic-shift-right fx1 fx2 +Returns the result of shifting the bits of @var{fx1} right or left by +the @var{fx2} positions. @code{fxarithmetic-shift} is identical +to @code{fxarithmetic-shift-left}. +@end deffn + +@deffn {Scheme Procedure} fxrotate-bit-field fx1 fx2 fx3 fx4 +Returns the result of cyclically permuting the bit field in @var{fx1} +with start and end positions @var{fx2} and @var{fx3} by @var{fx4} bits +in the direction of more significant bits. +@end deffn + +@deffn {Scheme Procedure} fxreverse-bit-field fx1 fx2 fx3 +Returns the result of reversing the order of the bits of @var{fx1} +between position @var{fx2} (inclusive) and position @var{fx3} +(exclusive). +@end deffn + +@node rnrs arithmetic flonums +@subsubsection rnrs arithmetic flonums + +The @code{(rnrs arithmetic flonums (6))} library provides procedures for +performing arithmetic operations on inexact representations of real +numbers, which R6RS refers to as @dfn{flonums}. + +Unless otherwise specified, all of the procedures below take flonums as +arguments, and will raise an @code{&assertion} condition if passed a +non-flonum argument. + +@deffn {Scheme Procedure} flonum? obj +Returns @code{#t} if @var{obj} is a flonum, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} real->flonum x +Returns the flonum that is numerically closest to the real number +@var{x}. +@end deffn + +@deffn {Scheme Procedure} fl=? fl1 fl2 fl3 ... +@deffnx {Scheme Procedure} fl<? fl1 fl2 fl3 ... +@deffnx {Scheme Procedure} fl<=? fl1 fl2 fl3 ... +@deffnx {Scheme Procedure} fl>? fl1 fl2 fl3 ... +@deffnx {Scheme Procedure} fl>=? fl1 fl2 fl3 ... +These procedures return @code{#t} if their flonum arguments are +(respectively): equal, monotonically increasing, monotonically +decreasing, monotonically nondecreasing, or monotonically nonincreasing; +@code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} flinteger? fl +@deffnx {Scheme Procedure} flzero? fl +@deffnx {Scheme Procedure} flpositive? fl +@deffnx {Scheme Procedure} flnegative? fl +@deffnx {Scheme Procedure} flodd? fl +@deffnx {Scheme Procedure} fleven? fl +These numerical predicates return @code{#t} if @var{fl} is, +respectively, an integer, zero, greater than zero, less than zero, odd, +even, @code{#f} otherwise. In the case of @code{flodd?} and +@code{fleven?}, @var{fl} must be an integer-valued flonum. +@end deffn + +@deffn {Scheme Procedure} flfinite? fl +@deffnx {Scheme Procedure} flinfinite? fl +@deffnx {Scheme Procedure} flnan? fl +These numerical predicates return @code{#t} if @var{fl} is, +respectively, not infinite, infinite, or a @code{NaN} value. +@end deffn + +@deffn {Scheme Procedure} flmax fl1 fl2 ... +@deffnx {Scheme Procedure} flmin fl1 fl2 ... +These procedures return the maximum or minimum of their arguments. +@end deffn + +@deffn {Scheme Procedure} fl+ fl1 ... +@deffnx {Scheme Procedure} fl* fl ... +These procedures return the sum or product of their arguments. +@end deffn + +@deffn {Scheme Procedure} fl- fl1 fl2 ... +@deffnx {Scheme Procedure} fl- fl +@deffnx {Scheme Procedure} fl/ fl1 fl2 ... +@deffnx {Scheme Procedure} fl/ fl +These procedures return, respectively, the difference or quotient of +their arguments when called with two arguments; when called with a +single argument, they return the additive or multiplicative inverse of +@var{fl}. +@end deffn + +@deffn {Scheme Procedure} flabs fl +Returns the absolute value of @var{fl}. +@end deffn + +@deffn {Scheme Procedure} fldiv-and-mod fl1 fl2 +@deffnx {Scheme Procedure} fldiv fl1 fl2 +@deffnx {Scheme Procedure} fldmod fl1 fl2 +@deffnx {Scheme Procedure} fldiv0-and-mod0 fl1 fl2 +@deffnx {Scheme Procedure} fldiv0 fl1 fl2 +@deffnx {Scheme Procedure} flmod0 fl1 fl2 +These procedures implement number-theoretic division on flonums; +@xref{(rnrs base)}, for a description for their semantics. +@end deffn + +@deffn {Scheme Procedure} flnumerator fl +@deffnx {Scheme Procedure} fldenominator fl +These procedures return the numerator or denominator of @var{fl} as a +flonum. +@end deffn + +@deffn {Scheme Procedure} flfloor fl1 +@deffnx {Scheme Procedure} flceiling fl +@deffnx {Scheme Procedure} fltruncate fl +@deffnx {Scheme Procedure} flround fl +These procedures are identical to the @code{floor}, @code{ceiling}, +@code{truncate}, and @code{round} procedures provided by Guile's core +library. @xref{Arithmetic}, for documentation. +@end deffn + +@deffn {Scheme Procedure} flexp fl +@deffnx {Scheme Procedure} fllog fl +@deffnx {Scheme Procedure} fllog fl1 fl2 +@deffnx {Scheme Procedure} flsin fl +@deffnx {Scheme Procedure} flcos fl +@deffnx {Scheme Procedure} fltan fl +@deffnx {Scheme Procedure} flasin fl +@deffnx {Scheme Procedure} flacos fl +@deffnx {Scheme Procedure} flatan fl +@deffnx {Scheme Procedure} flatan fl1 fl2 +These procedures, which compute the usual transcendental functions, are +the flonum variants of the procedures provided by the R6RS base library +(@pxref{(rnrs base)}). +@end deffn + +@deffn {Scheme Procedure} flsqrt fl +Returns the square root of @var{fl}. If @var{fl} is @code{-0.0}, +@var{-0.0} is returned; for other negative values, a @code{NaN} value +is returned. +@end deffn + +@deffn {Scheme Procedure} flexpt fl1 fl2 +Returns the value of @var{fl1} raised to the power of @var{fl2}. +@end deffn + +The following condition types are provided to allow Scheme +implementations that do not support infinities or @code{NaN} values +to indicate that a computation resulted in such a value. Guile supports +both of these, so these conditions will never be raised by Guile's +standard libraries implementation. + +@deffn {Condition Type} &no-infinities +@deffnx {Scheme Procedure} make-no-infinities-violation obj +@deffnx {Scheme Procedure} no-infinities-violation? +A condition type indicating that a computation resulted in an infinite +value on a Scheme implementation incapable of representing infinities. +@end deffn + +@deffn {Condition Type} &no-nans +@deffnx {Scheme Procedure} make-no-nans-violation obj +@deffnx {Scheme Procedure} no-nans-violation? obj +A condition type indicating that a computation resulted in a @code{NaN} +value on a Scheme implementation incapable of representing @code{NaN}s. +@end deffn + +@deffn {Scheme Procedure} fixnum->flonum fx +Returns the flonum that is numerically closest to the fixnum @var{fx}. +@end deffn + +@node rnrs arithmetic bitwise +@subsubsection rnrs arithmetic bitwise + +The @code{(rnrs arithmetic bitwise (6))} library provides procedures for +performing bitwise arithmetic operations on the two's complement +representations of fixnums. + +This library and the procedures it exports share functionality with +SRFI-60, which provides support for bitwise manipulation of integers +(@pxref{SRFI-60}). + +@deffn {Scheme Procedure} bitwise-not ei +@deffnx {Scheme Procedure} bitwise-and ei1 ... +@deffnx {Scheme Procedure} bitwise-ior ei1 ... +@deffnx {Scheme Procedure} bitwise-xor ei1 ... +These procedures are identical to the @code{lognot}, @code{logand}, +@code{logior}, and @code{logxor} procedures provided by Guile's core +library. @xref{Bitwise Operations}, for documentation. +@end deffn + +@deffn {Scheme Procedure} bitwise-if ei1 ei2 ei3 +Returns the bitwise ``if'' of its arguments. The bit at position +@code{i} in the return value will be the @code{i}th bit from @var{ei2} +if the @code{i}th bit of @var{ei1} is 1, the @code{i}th bit from +@var{ei3}. +@end deffn + +@deffn {Scheme Procedure} bitwise-bit-count ei +Returns the number of 1 bits in the two's complement representation of +@var{ei}. +@end deffn + +@deffn {Scheme Procedure} bitwise-length ei +Returns the number of bits necessary to represent @var{ei}. +@end deffn + +@deffn {Scheme Procedure} bitwise-first-bit-set ei +Returns the index of the least significant 1 bit in the two's complement +representation of @var{ei}. +@end deffn + +@deffn {Scheme Procedure} bitwise-bit-set? ei1 ei2 +Returns @code{#t} if the @var{ei2}th bit in the two's complement +representation of @var{ei1} is 1, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} bitwise-copy-bit ei1 ei2 ei3 +Returns the result of setting the @var{ei2}th bit of @var{ei1} to the +@var{ei2}th bit of @var{ei3}. +@end deffn + +@deffn {Scheme Procedure} bitwise-bit-field ei1 ei2 ei3 +Returns the integer representation of the contiguous sequence of bits in +@var{ei1} that starts at position @var{ei2} (inclusive) and ends at +position @var{ei3} (exclusive). +@end deffn + +@deffn {Scheme Procedure} bitwise-copy-bit-field ei1 ei2 ei3 ei4 +Returns the result of replacing the bit field in @var{ei1} with start +and end positions @var{ei2} and @var{ei3} with the corresponding bit +field from @var{ei4}. +@end deffn + +@deffn {Scheme Procedure} bitwise-arithmetic-shift ei1 ei2 +@deffnx {Scheme Procedure} bitwise-arithmetic-shift-left ei1 ei2 +@deffnx {Scheme Procedure} bitwise-arithmetic-shift-right ei1 ei2 +Returns the result of shifting the bits of @var{ei1} right or left by +the @var{ei2} positions. @code{bitwise-arithmetic-shift} is identical +to @code{bitwise-arithmetic-shift-left}. +@end deffn + +@deffn {Scheme Procedure} bitwise-rotate-bit-field ei1 ei2 ei3 ei4 +Returns the result of cyclically permuting the bit field in @var{ei1} +with start and end positions @var{ei2} and @var{ei3} by @var{ei4} bits +in the direction of more significant bits. +@end deffn + +@deffn {Scheme Procedure} bitwise-reverse-bit-field ei1 ei2 ei3 +Returns the result of reversing the order of the bits of @var{ei1} +between position @var{ei2} (inclusive) and position @var{ei3} +(exclusive). +@end deffn + +@node rnrs syntax-case +@subsubsection rnrs syntax-case + +The @code{(rnrs syntax-case (6))} library provides access to the +@code{syntax-case} system for writing hygienic macros. With one +exception, all of the forms and procedures exported by this library +are ``re-exports'' of Guile's native support for @code{syntax-case}; +@xref{Syntax Case}, for documentation, examples, and rationale. + +@deffn {Scheme Procedure} make-variable-transformer proc +Creates a new variable transformer out of @var{proc}, a procedure that +takes a syntax object as input and returns a syntax object. If an +identifier to which the result of this procedure is bound appears on the +left-hand side of a @code{set!} expression, @var{proc} will be called +with a syntax object representing the entire @code{set!} expression, +and its return value will replace that @code{set!} expression. +@end deffn + +@deffn {Scheme Syntax} syntax-case expression (literal ...) clause ... +The @code{syntax-case} pattern matching form. +@end deffn + +@deffn {Scheme Syntax} syntax template +@deffnx {Scheme Syntax} quasisyntax template +@deffnx {Scheme Syntax} unsyntax template +@deffnx {Scheme Syntax} unsyntax-splicing template +These forms allow references to be made in the body of a syntax-case +output expression subform to datum and non-datum values. They are +identical to the forms provided by Guile's core library; +@xref{Syntax Case}, for documentation. +@end deffn + +@deffn {Scheme Procedure} identifier? obj +@deffnx {Scheme Procedure} bound-identifier=? id1 id2 +@deffnx {Scheme Procedure} free-identifier=? id1 id2 +These predicate procedures operate on syntax objects representing +Scheme identifiers. @code{identifier?} returns @code{#t} if @var{obj} +represents an identifier, @code{#f} otherwise. +@code{bound-identifier=?} returns @code{#t} if and only if a binding for +@var{id1} would capture a reference to @var{id2} in the transformer's +output, or vice-versa. @code{free-identifier=?} returns @code{#t} if +and only @var{id1} and @var{id2} would refer to the same binding in the +output of the transformer, independent of any bindings introduced by the +transformer. +@end deffn + +@deffn {Scheme Procedure} generate-temporaries l +Returns a list, of the same length as @var{l}, which must be a list or +a syntax object representing a list, of globally unique symbols. +@end deffn + +@deffn {Scheme Procedure} syntax->datum syntax-object +@deffnx {Scheme Procedure} datum->syntax template-id datum +These procedures convert wrapped syntax objects to and from Scheme datum +values. The syntax object returned by @code{datum->syntax} shares +contextual information with the syntax object @var{template-id}. +@end deffn + +@deffn {Scheme Procedure} syntax-violation whom message form +@deffnx {Scheme Procedure} syntax-violation whom message form subform +Constructs a new compound condition that includes the following +simple conditions: +@itemize @bullet +@item +If @var{whom} is not @code{#f}, a @code{&who} condition with the +@var{whom} as its field +@item +A @code{&message} condition with the specified @var{message} +@item +A @code{&syntax} condition with the specified @var{form} and optional +@var{subform} fields +@end itemize +@end deffn + +@node rnrs hashtables +@subsubsection rnrs hashtables + +The @code{(rnrs hashtables (6))} library provides structures and +procedures for creating and accessing hash tables. The hash tables API +defined by R6RS is substantially similar to both Guile's native hash +tables implementation as well as the one provided by SRFI-69; +@xref{Hash Tables}, and @ref{SRFI-69}, respectively. Note that you can +write portable R6RS library code that manipulates SRFI-69 hash tables +(by importing the @code{(srfi :69)} library); however, hash tables +created by one API cannot be used by another. + +Like SRFI-69 hash tables---and unlike Guile's native ones---R6RS hash +tables associate hash and equality functions with a hash table at the +time of its creation. Additionally, R6RS allows for the creation +(via @code{hashtable-copy}; see below) of immutable hash tables. + +@deffn {Scheme Procedure} make-eq-hashtable +@deffnx {Scheme Procedure} make-eq-hashtable k +Returns a new hash table that uses @code{eq?} to compare keys and +Guile's @code{hashq} procedure as a hash function. If @var{k} is given, +it specifies the initial capacity of the hash table. +@end deffn + +@deffn {Scheme Procedure} make-eqv-hashtable +@deffnx {Scheme Procedure} make-eqv-hashtable k +Returns a new hash table that uses @code{eqv?} to compare keys and +Guile's @code{hashv} procedure as a hash function. If @var{k} is given, +it specifies the initial capacity of the hash table. +@end deffn + +@deffn {Scheme Procedure} make-hashtable hash-function equiv +@deffnx {Scheme Procedure} make-hashtable hash-function equiv k +Returns a new hash table that uses @var{equiv} to compare keys and +@var{hash-function} as a hash function. @var{equiv} must be a procedure +that accepts two arguments and returns a true value if they are +equivalent, @code{#f} otherwise; @var{hash-function} must be a procedure +that accepts one argument and returns a non-negative integer. + +If @var{k} is given, it specifies the initial capacity of the hash +table. +@end deffn + +@deffn {Scheme Procedure} hashtable? obj +Returns @code{#t} if @var{obj} is an R6RS hash table, @code{#f} +otherwise. +@end deffn + +@deffn {Scheme Procedure} hashtable-size hashtable +Returns the number of keys currently in the hash table @var{hashtable}. +@end deffn + +@deffn {Scheme Procedure} hashtable-ref hashtable key default +Returns the value associated with @var{key} in the hash table +@var{hashtable}, or @var{default} if none is found. +@end deffn + +@deffn {Scheme Procedure} hashtable-set! hashtable key obj +Associates the key @var{key} with the value @var{obj} in the hash table +@var{hashtable}, and returns an unspecified value. An @code{&assertion} +condition is raised if @var{hashtable} is immutable. +@end deffn + +@deffn {Scheme Procedure} hashtable-delete! hashtable key +Removes any association found for the key @var{key} in the hash table +@var{hashtable}, and returns an unspecified value. An @code{&assertion} +condition is raised if @var{hashtable} is immutable. +@end deffn + +@deffn {Scheme Procedure} hashtable-contains? hashtable key +Returns @code{#t} if the hash table @var{hashtable} contains an +association for the key @var{key}, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} hashtable-update! hashtable key proc default +Associates with @var{key} in the hash table @var{hashtable} the result +of calling @var{proc}, which must be a procedure that takes one +argument, on the value currently associated @var{key} in +@var{hashtable}---or on @var{default} if no such association exists. +An @code{&assertion} condition is raised if @var{hashtable} is +immutable. +@end deffn + +@deffn {Scheme Procedure} hashtable-copy hashtable +@deffnx {Scheme Procedure} hashtable-copy hashtable mutable +Returns a copy of the hash table @var{hashtable}. If the optional +argument @var{mutable} is provided and is a true value, the new hash +table will be mutable. +@end deffn + +@deffn {Scheme Procedure} hashtable-clear! hashtable +@deffnx {Scheme Procedure} hashtable-clear! hashtable k +Removes all of the associations from the hash table @var{hashtable}. +The optional argument @var{k}, which specifies a new capacity for the +hash table, is accepted by Guile's @code{(rnrs hashtables)} +implementation, but is ignored. +@end deffn + +@deffn {Scheme Procedure} hashtable-keys hashtable +Returns a vector of the keys with associations in the hash table +@var{hashtable}, in an unspecified order. +@end deffn + +@deffn {Scheme Procedure} hashtable-entries hashtable +Return two values---a vector of the keys with associations in the hash +table @var{hashtable}, and a vector of the values to which these keys +are mapped, in corresponding but unspecified order. +@end deffn + +@deffn {Scheme Procedure} hashtable-equivalence-function hashtable +Returns the equivalence predicated use by @var{hashtable}. This +procedure returns @code{eq?} and @code{eqv?}, respectively, for hash +tables created by @code{make-eq-hashtable} and +@code{make-eqv-hashtable}. +@end deffn + +@deffn {Scheme Procedure} hashtable-hash-function hashtable +Returns the hash function used by @var{hashtable}. For hash tables +created by @code{make-eq-hashtable} or @code{make-eqv-hashtable}, +@code{#f} is returned. +@end deffn + +@deffn {Scheme Procedure} hashtable-mutable? hashtable +Returns @code{#t} if @var{hashtable} is mutable, @code{#f} otherwise. +@end deffn + +A number of hash functions are provided for convenience: + +@deffn {Scheme Procedure} equal-hash obj +Returns an integer hash value for @var{obj}, based on its structure and +current contents. This hash function is suitable for use with +@code{equal?} as an equivalence function. +@end deffn + +@deffn {Scheme Procedure} string-hash string +@deffnx {Scheme Procedure} symbol-hash symbol +These procedures are identical to the ones provided by Guile's core +library. @xref{Hash Table Reference}, for documentation. +@end deffn + +@deffn {Scheme Procedure} string-ci-hash string +Returns an integer hash value for @var{string} based on its contents, +ignoring case. This hash function is suitable for use with +@code{string-ci=?} as an equivalence function. +@end deffn + +@node rnrs enums +@subsubsection rnrs enums + +The @code{(rnrs enums (6))} library provides structures and procedures +for working with enumerable sets of symbols. Guile's implementation +defines an @dfn{enum-set} record type that encapsulates a finite set of +distinct symbols, the @dfn{universe}, and a subset of these symbols, +which define the enumeration set. + +The SRFI-1 list library provides a number of procedures for performing +set operations on lists; Guile's @code{(rnrs enums)} implementation +makes use of several of them. @xref{SRFI-1 Set Operations}, for +more information. + +@deffn {Scheme Procedure} make-enumeration symbol-list +Returns a new enum-set whose universe and enumeration set are both equal +to @var{symbol-list}, a list of symbols. +@end deffn + +@deffn {Scheme Procedure} enum-set-universe enum-set +Returns an enum-set representing the universe of @var{enum-set}, +an enum-set. +@end deffn + +@deffn {Scheme Procedure} enum-set-indexer enum-set +Returns a procedure that takes a single argument and returns the +zero-indexed position of that argument in the universe of +@var{enum-set}, or @code{#f} if its argument is not a member of that +universe. +@end deffn + +@deffn {Scheme Procedure} enum-set-constructor enum-set +Returns a procedure that takes a single argument, a list of symbols +from the universe of @var{enum-set}, an enum-set, and returns a new +enum-set with the same universe that represents a subset containing the +specified symbols. +@end deffn + +@deffn {Scheme Procedure} enum-set->list enum-set +Returns a list containing the symbols of the set represented by +@var{enum-set}, an enum-set, in the order that they appear in the +universe of @var{enum-set}. +@end deffn + +@deffn {Scheme Procedure} enum-set-member? symbol enum-set +@deffnx {Scheme Procedure} enum-set-subset? enum-set1 enum-set2 +@deffnx {Scheme Procedure} enum-set=? enum-set1 enum-set2 +These procedures test for membership of symbols and enum-sets in other +enum-sets. @code{enum-set-member?} returns @code{#t} if and only if +@var{symbol} is a member of the subset specified by @var{enum-set}. +@code{enum-set-subset?} returns @code{#t} if and only if the universe of +@var{enum-set1} is a subset of the universe of @var{enum-set2} and +every symbol in @var{enum-set1} is present in @var{enum-set2}. +@code{enum-set=?} returns @code{#t} if and only if @var{enum-set1} is a +subset, as per @code{enum-set-subset?} of @var{enum-set2} and vice +versa. +@end deffn + +@deffn {Scheme Procedure} enum-set-union enum-set1 enum-set2 +@deffnx {Scheme Procedure} enum-set-intersection enum-set1 enum-set2 +@deffnx {Scheme Procedure} enum-set-difference enum-set1 enum-set2 +These procedures return, respectively, the union, intersection, and +difference of their enum-set arguments. +@end deffn + +@deffn {Scheme Procedure} enum-set-complement enum-set +Returns @var{enum-set}'s complement (an enum-set), with regard to its +universe. +@end deffn + +@deffn {Scheme Procedure} enum-set-projection enum-set1 enum-set2 +Returns the projection of the enum-set @var{enum-set1} onto the universe +of the enum-set @var{enum-set2}. +@end deffn + +@deffn {Scheme Syntax} define-enumeration type-name (symbol ...) constructor-syntax +Evaluates to two new definitions: A constructor bound to +@var{constructor-syntax} that behaves similarly to constructors created +by @code{enum-set-constructor}, above, and creates new @var{enum-set}s +in the universe specified by @code{(symbol ...)}; and a ``predicate +macro'' bound to @var{type-name}, which has the following form: + +@lisp +(@var{type-name} sym) +@end lisp + +If @var{sym} is a member of the universe specified by the @var{symbol}s +above, this form evaluates to @var{sym}. Otherwise, a @code{&syntax} +condition is raised. +@end deffn + +@node rnrs +@subsubsection rnrs + +The @code{(rnrs (6))} library is a composite of all of the other R6RS +standard libraries---it imports and re-exports all of their exported +procedures and syntactic forms---with the exception of the following +libraries: + +@itemize @bullet +@item @code{(rnrs eval (6))} +@item @code{(rnrs mutable-pairs (6))} +@item @code{(rnrs mutable-strings (6))} +@item @code{(rnrs r5rs (6))} +@end itemize + +@node rnrs eval +@subsubsection rnrs eval + +The @code{(rnrs eval (6)} library provides procedures for performing +``on-the-fly'' evaluation of expressions. + +@deffn {Scheme Procedure} eval expression environment +Evaluates @var{expression}, which must be a datum representation of a +valid Scheme expression, in the environment specified by +@var{environment}. This procedure is identical to the one provided by +Guile's code library; @xref{Fly Evaluation}, for documentation. +@end deffn + +@deffn {Scheme Procedure} environment import-spec ... +Constructs and returns a new environment based on the specified +@var{import-spec}s, which must be datum representations of the import +specifications used with the @code{import} form. @xref{R6RS Libraries}, +for documentation. +@end deffn + +@node rnrs mutable-pairs +@subsubsection rnrs mutable-pairs + +The @code{(rnrs mutable-pairs (6))} library provides the @code{set-car!} +and @code{set-cdr!} procedures, which allow the @code{car} and +@code{cdr} fields of a pair to be modified. + +These procedures are identical to the ones provide by Guile's core +library. @xref{Pairs}, for documentation. All pairs in Guile are +mutable; consequently, these procedures will never throw the +@code{&assertion} condition described in the R6RS libraries +specification. + +@node rnrs mutable-strings +@subsubsection rnrs mutable-strings + +The @code{(rnrs mutable-strings (6))} library provides the +@code{string-set!} and @code{string-fill!} procedures, which allow the +content of strings to be modified ``in-place.'' + +These procedures are identical to the ones provided by Guile's core +library. @xref{String Modification}, for documentation. All strings in +Guile are mutable; consequently, these procedures will never throw the +@code{&assertion} condition described in the R6RS libraries +specification. + +@node rnrs r5rs +@subsubsection rnrs r5rs + +The @code{(rnrs r5rs (6))} library exports bindings for some procedures +present in R5RS but omitted from the R6RS base library specification. + +@deffn {Scheme Procedure} exact->inexact z +@deffnx {Scheme Procedure} inexact->exact z +These procedures are identical to the ones provided by Guile's core +library. @xref{Exactness}, for documentation. +@end deffn + +@deffn {Scheme Procedure} quotient n1 n2 +@deffnx {Scheme Procedure} remainder n1 n2 +@deffnx {Scheme Procedure} modulo n1 n2 +These procedures are identical to the ones provided by Guile's core +library. @xref{Integer Operations}, for documentation. +@end deffn + +@deffn {Scheme Syntax} delay expr +@deffnx {Scheme Procedure} force promise +The @code{delay} form and the @code{force} procedure are identical to +their counterparts in Guile's core library. @xref{Delayed Evaluation}, +for documentation. +@end deffn + +@deffn {Scheme Procedure} null-environment n +@deffnx {Scheme Procedure} scheme-report-environment n +These procedures are identical to the ones provided by the +@code{(ice-9 r5rs)} Guile module. @xref{Environments}, for +documentation. +@end deffn + +@c r6rs.texi ends here + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/repl-modules.texi b/doc/ref/repl-modules.texi new file mode 100644 index 000000000..e20393ba2 --- /dev/null +++ b/doc/ref/repl-modules.texi @@ -0,0 +1,256 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Readline Support +@section Readline Support + +@c FIXME::martin: Review me! + +@cindex readline +@cindex command line history +Guile comes with an interface module to the readline library +(@pxref{Top,,, readline, GNU Readline Library}). This +makes interactive use much more convenient, because of the command-line +editing features of readline. Using @code{(ice-9 readline)}, you can +navigate through the current input line with the cursor keys, retrieve +older command lines from the input history and even search through the +history entries. + +@menu +* Loading Readline Support:: How to load readline support into Guile. +* Readline Options:: How to modify readline's behaviour. +* Readline Functions:: Programming with readline. +@end menu + + +@node Loading Readline Support +@subsection Loading Readline Support + +The module is not loaded by default and so has to be loaded and +activated explicitly. This is done with two simple lines of code: + +@lisp +(use-modules (ice-9 readline)) +(activate-readline) +@end lisp + +@c FIXME::martin: Review me! + +The first line will load the necessary code, and the second will +activate readline's features for the REPL. If you plan to use this +module often, you should save these to lines to your @file{.guile} +personal startup file. + +You will notice that the REPL's behaviour changes a bit when you have +loaded the readline module. For example, when you press Enter before +typing in the closing parentheses of a list, you will see the +@dfn{continuation} prompt, three dots: @code{...} This gives you a nice +visual feedback when trying to match parentheses. To make this even +easier, @dfn{bouncing parentheses} are implemented. That means that +when you type in a closing parentheses, the cursor will jump to the +corresponding opening parenthesis for a short time, making it trivial to make +them match. + +Once the readline module is activated, all lines entered interactively +will be stored in a history and can be recalled later using the +cursor-up and -down keys. Readline also understands the Emacs keys for +navigating through the command line and history. + +@cindex @file{.guile_history} +When you quit your Guile session by evaluating @code{(quit)} or pressing +Ctrl-D, the history will be saved to the file @file{.guile_history} and +read in when you start Guile for the next time. Thus you can start a +new Guile session and still have the (probably long-winded) definition +expressions available. + +@cindex @env{GUILE_HISTORY} +@cindex @file{.inputrc} +You can specify a different history file by setting the environment +variable @env{GUILE_HISTORY}. And you can make Guile specific +customizations to your @file{.inputrc} by testing for application +@samp{Guile} (@pxref{Conditional Init Constructs,,, readline, GNU +Readline Library}). For instance to define a key inserting a matched +pair of parentheses, + +@example +$if Guile + "\C-o": "()\C-b" +$endif +@end example + +@node Readline Options +@subsection Readline Options + +@cindex readline options +The readline interface module can be tweaked in a few ways to better +suit the user's needs. Configuration is done via the readline module's +options interface, in a similar way to the evaluator and debugging +options (@pxref{Runtime Options}). + +@deffn {Scheme Procedure} readline-options +@deffnx {Scheme Procedure} readline-enable option-name +@deffnx {Scheme Procedure} readline-disable option-name +@deffnx {Scheme Syntax} readline-set! option-name value +Accessors for the readline options. Note that unlike the enable/disable +procedures, @code{readline-set!} is syntax, which expects an unquoted +option name. +@end deffn + +Here is the list of readline options generated by typing +@code{(readline-options 'help)} in Guile. You can also see the +default values. + +@smalllisp +history-file yes Use history file. +history-length 200 History length. +bounce-parens 500 Time (ms) to show matching opening parenthesis + (0 = off). +bracketed-paste yes Disable interpretation of control characters + in pastes. +@end smalllisp + +The readline options interface can only be used @emph{after} loading +the readline module, because it is defined in that module. + +@node Readline Functions +@subsection Readline Functions + +The following functions are provided by + +@example +(use-modules (ice-9 readline)) +@end example + +There are two ways to use readline from Scheme code, either make calls +to @code{readline} directly to get line by line input, or use the +readline port below with all the usual reading functions. + +@defun readline [prompt] +Read a line of input from the user and return it as a string (without +a newline at the end). @var{prompt} is the prompt to show, or the +default is the string set in @code{set-readline-prompt!} below. + +@example +(readline "Type something: ") @result{} "hello" +@end example +@end defun + +@defun set-readline-input-port! port +@defunx set-readline-output-port! port +Set the input and output port the readline function should read from +and write to. @var{port} must be a file port (@pxref{File Ports}), +and should usually be a terminal. + +The default is the @code{current-input-port} and +@code{current-output-port} (@pxref{Default Ports}) when @code{(ice-9 +readline)} loads, which in an interactive user session means the Unix +``standard input'' and ``standard output''. +@end defun + +@subsubsection Readline Port + +@defun readline-port +Return a buffered input port (@pxref{Buffered Input}) which calls the +@code{readline} function above to get input. This port can be used +with all the usual reading functions (@code{read}, @code{read-char}, +etc), and the user gets the interactive editing features of readline. + +There's only a single readline port created. @code{readline-port} +creates it when first called, and on subsequent calls just returns +what it previously made. +@end defun + +@defun activate-readline +If the @code{current-input-port} is a terminal (@pxref{Terminals and +Ptys,, @code{isatty?}}) then enable readline for all reading from +@code{current-input-port} (@pxref{Default Ports}) and enable readline +features in the interactive REPL (@pxref{The REPL}). + +@example +(activate-readline) +(read-char) +@end example + +@code{activate-readline} enables readline on @code{current-input-port} +simply by a @code{set-current-input-port} to the @code{readline-port} +above. An application can do that directly if the extra REPL features +that @code{activate-readline} adds are not wanted. +@end defun + +@defun set-readline-prompt! prompt1 [prompt2] +Set the prompt string to print when reading input. This is used when +reading through @code{readline-port}, and is also the default prompt +for the @code{readline} function above. + +@var{prompt1} is the initial prompt shown. If a user might enter an +expression across multiple lines, then @var{prompt2} is a different +prompt to show further input required. In the Guile REPL for instance +this is an ellipsis (@samp{...}). + +See @code{set-buffered-input-continuation?!} (@pxref{Buffered Input}) +for an application to indicate the boundaries of logical expressions +(assuming of course an application has such a notion). +@end defun + +@subsubsection Completion + +@defun with-readline-completion-function completer thunk +Call @code{(@var{thunk})} with @var{completer} as the readline tab +completion function to be used in any readline calls within that +@var{thunk}. @var{completer} can be @code{#f} for no completion. + +@var{completer} will be called as @code{(@var{completer} text state)}, +as described in (@pxref{How Completing Works,,, readline, GNU Readline +Library}). @var{text} is a partial word to be completed, and each +@var{completer} call should return a possible completion string or +@code{#f} when no more. @var{state} is @code{#f} for the first call +asking about a new @var{text} then @code{#t} while getting further +completions of that @var{text}. + +Here's an example @var{completer} for user login names from the +password file (@pxref{User Information}), much like readline's own +@code{rl_username_completion_function}, + +@example +(define (username-completer-function text state) + (if (not state) + (setpwent)) ;; new, go to start of database + (let more ((pw (getpwent))) + (if pw + (if (string-prefix? text (passwd:name pw)) + (passwd:name pw) ;; this name matches, return it + (more (getpwent))) ;; doesn't match, look at next + (begin + ;; end of database, close it and return #f + (endpwent) + #f)))) +@end example +@end defun + +@defun apropos-completion-function text state +A completion function offering completions for Guile functions and +variables (all @code{define}s). This is the default completion +function. +@c +@c FIXME: Cross reference the ``apropos'' stuff when it's documented. +@c +@end defun + +@defun filename-completion-function text state +A completion function offering filename completions. This is +readline's @code{rl_filename_completion_function} (@pxref{Completion +Functions,,, readline, GNU Readline Library}). +@end defun + +@defun make-completion-function string-list +Return a completion function which offers completions from the +possibilities in @var{string-list}. Matching is case-sensitive. +@end defun + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-ideas.texi b/doc/ref/scheme-ideas.texi new file mode 100644 index 000000000..d18d1012b --- /dev/null +++ b/doc/ref/scheme-ideas.texi @@ -0,0 +1,1593 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2012 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Hello Scheme! +@chapter Hello Scheme! + +In this chapter, we introduce the basic concepts that underpin the +elegance and power of the Scheme language. + +Readers who already possess a background knowledge of Scheme may happily +skip this chapter. For the reader who is new to the language, however, +the following discussions on data, procedures, expressions and closure +are designed to provide a minimum level of Scheme understanding that is +more or less assumed by the chapters that follow. + +The style of this introductory material aims about halfway between the terse +precision of R5RS and the discursiveness of existing Scheme tutorials. For +pointers to useful Scheme resources on the web, please see @ref{Further +Reading}. + +@menu +* About Data:: Latent typing, types, values and variables. +* About Procedures:: The representation and use of procedures. +* About Expressions:: All kinds of expressions and their meaning. +* About Closure:: Closure, scoping and environments. +* Further Reading:: Where to find out more about Scheme. +@end menu + + +@node About Data +@section Data Types, Values and Variables + +This section discusses the representation of data types and values, what +it means for Scheme to be a @dfn{latently typed} language, and the role +of variables. We conclude by introducing the Scheme syntaxes for +defining a new variable, and for changing the value of an existing +variable. + +@menu +* Latent Typing:: Scheme as a "latently typed" language. +* Values and Variables:: About data types, values and variables. +* Definition:: Defining variables and setting their values. +@end menu + + +@node Latent Typing +@subsection Latent Typing + +The term @dfn{latent typing} is used to describe a computer language, +such as Scheme, for which you cannot, @emph{in general}, simply look at +a program's source code and determine what type of data will be +associated with a particular variable, or with the result of a +particular expression. + +Sometimes, of course, you @emph{can} tell from the code what the type of +an expression will be. If you have a line in your program that sets the +variable @code{x} to the numeric value 1, you can be certain that, +immediately after that line has executed (and in the absence of multiple +threads), @code{x} has the numeric value 1. Or if you write a procedure +that is designed to concatenate two strings, it is likely that the rest +of your application will always invoke this procedure with two string +parameters, and quite probable that the procedure would go wrong in some +way if it was ever invoked with parameters that were not both strings. + +Nevertheless, the point is that there is nothing in Scheme which +requires the procedure parameters always to be strings, or @code{x} +always to hold a numeric value, and there is no way of declaring in your +program that such constraints should always be obeyed. In the same +vein, there is no way to declare the expected type of a procedure's +return value. + +Instead, the types of variables and expressions are only known -- in +general -- at run time. If you @emph{need} to check at some point that +a value has the expected type, Scheme provides run time procedures that +you can invoke to do so. But equally, it can be perfectly valid for two +separate invocations of the same procedure to specify arguments with +different types, and to return values with different types. + +The next subsection explains what this means in practice, for the ways +that Scheme programs use data types, values and variables. + + +@node Values and Variables +@subsection Values and Variables + +Scheme provides many data types that you can use to represent your data. +Primitive types include characters, strings, numbers and procedures. +Compound types, which allow a group of primitive and compound values to +be stored together, include lists, pairs, vectors and multi-dimensional +arrays. In addition, Guile allows applications to define their own data +types, with the same status as the built-in standard Scheme types. + +As a Scheme program runs, values of all types pop in and out of +existence. Sometimes values are stored in variables, but more commonly +they pass seamlessly from being the result of one computation to being +one of the parameters for the next. + +Consider an example. A string value is created because the interpreter +reads in a literal string from your program's source code. Then a +numeric value is created as the result of calculating the length of the +string. A second numeric value is created by doubling the calculated +length. Finally the program creates a list with two elements -- the +doubled length and the original string itself -- and stores this list in +a program variable. + +All of the values involved here -- in fact, all values in Scheme -- +carry their type with them. In other words, every value ``knows,'' at +runtime, what kind of value it is. A number, a string, a list, +whatever. + +A variable, on the other hand, has no fixed type. A variable -- +@code{x}, say -- is simply the name of a location -- a box -- in which +you can store any kind of Scheme value. So the same variable in a +program may hold a number at one moment, a list of procedures the next, +and later a pair of strings. The ``type'' of a variable -- insofar as +the idea is meaningful at all -- is simply the type of whatever value +the variable happens to be storing at a particular moment. + + +@node Definition +@subsection Defining and Setting Variables + +To define a new variable, you use Scheme's @code{define} syntax like +this: + +@lisp +(define @var{variable-name} @var{value}) +@end lisp + +This makes a new variable called @var{variable-name} and stores +@var{value} in it as the variable's initial value. For example: + +@lisp +;; Make a variable `x' with initial numeric value 1. +(define x 1) + +;; Make a variable `organization' with an initial string value. +(define organization "Free Software Foundation") +@end lisp + +(In Scheme, a semicolon marks the beginning of a comment that continues +until the end of the line. So the lines beginning @code{;;} are +comments.) + +Changing the value of an already existing variable is very similar, +except that @code{define} is replaced by the Scheme syntax @code{set!}, +like this: + +@lisp +(set! @var{variable-name} @var{new-value}) +@end lisp + +Remember that variables do not have fixed types, so @var{new-value} may +have a completely different type from whatever was previously stored in +the location named by @var{variable-name}. Both of the following +examples are therefore correct. + +@lisp +;; Change the value of `x' to 5. +(set! x 5) + +;; Change the value of `organization' to the FSF's street number. +(set! organization 545) +@end lisp + +In these examples, @var{value} and @var{new-value} are literal numeric +or string values. In general, however, @var{value} and @var{new-value} +can be any Scheme expression. Even though we have not yet covered the +forms that Scheme expressions can take (@pxref{About Expressions}), you +can probably guess what the following @code{set!} example does@dots{} + +@lisp +(set! x (+ x 1)) +@end lisp + +(Note: this is not a complete description of @code{define} and +@code{set!}, because we need to introduce some other aspects of Scheme +before the missing pieces can be filled in. If, however, you are +already familiar with the structure of Scheme, you may like to read +about those missing pieces immediately by jumping ahead to the following +references. + +@itemize @bullet +@item +@ref{Lambda Alternatives}, to read about an alternative form of the +@code{define} syntax that can be used when defining new procedures. + +@item +@ref{Procedures with Setters}, to read about an alternative form of the +@code{set!} syntax that helps with changing a single value in the depths +of a compound data structure.) + +@item +@xref{Internal Definitions}, to read about using @code{define} other +than at top level in a Scheme program, including a discussion of when it +works to use @code{define} rather than @code{set!} to change the value +of an existing variable. +@end itemize + + +@node About Procedures +@section The Representation and Use of Procedures + +This section introduces the basics of using and creating Scheme +procedures. It discusses the representation of procedures as just +another kind of Scheme value, and shows how procedure invocation +expressions are constructed. We then explain how @code{lambda} is used +to create new procedures, and conclude by presenting the various +shorthand forms of @code{define} that can be used instead of writing an +explicit @code{lambda} expression. + +@menu +* Procedures as Values:: Procedures are values like everything else. +* Simple Invocation:: How to write a simple procedure invocation. +* Creating a Procedure:: How to create your own procedures. +* Lambda Alternatives:: Other ways of writing procedure definitions. +@end menu + + +@node Procedures as Values +@subsection Procedures as Values + +One of the great simplifications of Scheme is that a procedure is just +another type of value, and that procedure values can be passed around +and stored in variables in exactly the same way as, for example, strings +and lists. When we talk about a built-in standard Scheme procedure such +as @code{open-input-file}, what we actually mean is that there is a +pre-defined top level variable called @code{open-input-file}, whose +value is a procedure that implements what R5RS says that +@code{open-input-file} should do. + +Note that this is quite different from many dialects of Lisp --- +including Emacs Lisp --- in which a program can use the same name with +two quite separate meanings: one meaning identifies a Lisp function, +while the other meaning identifies a Lisp variable, whose value need +have nothing to do with the function that is associated with the first +meaning. In these dialects, functions and variables are said to live in +different @dfn{namespaces}. + +In Scheme, on the other hand, all names belong to a single unified +namespace, and the variables that these names identify can hold any kind +of Scheme value, including procedure values. + +One consequence of the ``procedures as values'' idea is that, if you +don't happen to like the standard name for a Scheme procedure, you can +change it. + +For example, @code{call-with-current-continuation} is a very important +standard Scheme procedure, but it also has a very long name! So, many +programmers use the following definition to assign the same procedure +value to the more convenient name @code{call/cc}. + +@lisp +(define call/cc call-with-current-continuation) +@end lisp + +Let's understand exactly how this works. The definition creates a new +variable @code{call/cc}, and then sets its value to the value of the +variable @code{call-with-current-continuation}; the latter value is a +procedure that implements the behaviour that R5RS specifies under the +name ``call-with-current-continuation''. So @code{call/cc} ends up +holding this value as well. + +Now that @code{call/cc} holds the required procedure value, you could +choose to use @code{call-with-current-continuation} for a completely +different purpose, or just change its value so that you will get an +error if you accidentally use @code{call-with-current-continuation} as a +procedure in your program rather than @code{call/cc}. For example: + +@lisp +(set! call-with-current-continuation "Not a procedure any more!") +@end lisp + +Or you could just leave @code{call-with-current-continuation} as it was. +It's perfectly fine for more than one variable to hold the same +procedure value. + + +@node Simple Invocation +@subsection Simple Procedure Invocation + +A procedure invocation in Scheme is written like this: + +@lisp +(@var{procedure} [@var{arg1} [@var{arg2} @dots{}]]) +@end lisp + +In this expression, @var{procedure} can be any Scheme expression whose +value is a procedure. Most commonly, however, @var{procedure} is simply +the name of a variable whose value is a procedure. + +For example, @code{string-append} is a standard Scheme procedure whose +behaviour is to concatenate together all the arguments, which are +expected to be strings, that it is given. So the expression + +@lisp +(string-append "/home" "/" "andrew") +@end lisp + +@noindent +is a procedure invocation whose result is the string value +@code{"/home/andrew"}. + +Similarly, @code{string-length} is a standard Scheme procedure that +returns the length of a single string argument, so + +@lisp +(string-length "abc") +@end lisp + +@noindent +is a procedure invocation whose result is the numeric value 3. + +Each of the parameters in a procedure invocation can itself be any +Scheme expression. Since a procedure invocation is itself a type of +expression, we can put these two examples together to get + +@lisp +(string-length (string-append "/home" "/" "andrew")) +@end lisp + +@noindent +--- a procedure invocation whose result is the numeric value 12. + +(You may be wondering what happens if the two examples are combined the +other way round. If we do this, we can make a procedure invocation +expression that is @emph{syntactically} correct: + +@lisp +(string-append "/home" (string-length "abc")) +@end lisp + +@noindent +but when this expression is executed, it will cause an error, because +the result of @code{(string-length "abc")} is a numeric value, and +@code{string-append} is not designed to accept a numeric value as one of +its arguments.) + + +@node Creating a Procedure +@subsection Creating and Using a New Procedure + +Scheme has lots of standard procedures, and Guile provides all of these +via predefined top level variables. All of these standard procedures +are documented in the later chapters of this reference manual. + +Before very long, though, you will want to create new procedures that +encapsulate aspects of your own applications' functionality. To do +this, you can use the famous @code{lambda} syntax. + +For example, the value of the following Scheme expression + +@lisp +(lambda (name address) @var{expression} @dots{}) +@end lisp + +@noindent +is a newly created procedure that takes two arguments: +@code{name} and @code{address}. The behaviour of the +new procedure is determined by the sequence of @var{expression}s in the +@dfn{body} of the procedure definition. (Typically, these +@var{expression}s would use the arguments in some way, or else there +wouldn't be any point in giving them to the procedure.) When invoked, +the new procedure returns a value that is the value of the last +@var{expression} in the procedure body. + +To make things more concrete, let's suppose that the two arguments are +both strings, and that the purpose of this procedure is to form a +combined string that includes these arguments. Then the full lambda +expression might look like this: + +@lisp +(lambda (name address) + (string-append "Name=" name ":Address=" address)) +@end lisp + +We noted in the previous subsection that the @var{procedure} part of a +procedure invocation expression can be any Scheme expression whose value +is a procedure. But that's exactly what a lambda expression is! So we +can use a lambda expression directly in a procedure invocation, like +this: + +@lisp +((lambda (name address) + (string-append "Name=" name ":Address=" address)) + "FSF" + "Cambridge") +@end lisp + +@noindent +This is a valid procedure invocation expression, and its result is the +string: + +@lisp +"Name=FSF:Address=Cambridge" +@end lisp + +It is more common, though, to store the procedure value in a variable --- + +@lisp +(define make-combined-string + (lambda (name address) + (string-append "Name=" name ":Address=" address))) +@end lisp + +@noindent +--- and then to use the variable name in the procedure invocation: + +@lisp +(make-combined-string "FSF" "Cambridge") +@end lisp + +@noindent +Which has exactly the same result. + +It's important to note that procedures created using @code{lambda} have +exactly the same status as the standard built in Scheme procedures, and +can be invoked, passed around, and stored in variables in exactly the +same ways. + + +@node Lambda Alternatives +@subsection Lambda Alternatives + +Since it is so common in Scheme programs to want to create a procedure +and then store it in a variable, there is an alternative form of the +@code{define} syntax that allows you to do just that. + +A @code{define} expression of the form + +@lisp +(define (@var{name} [@var{arg1} [@var{arg2} @dots{}]]) + @var{expression} @dots{}) +@end lisp + +@noindent +is exactly equivalent to the longer form + +@lisp +(define @var{name} + (lambda ([@var{arg1} [@var{arg2} @dots{}]]) + @var{expression} @dots{})) +@end lisp + +So, for example, the definition of @code{make-combined-string} in the +previous subsection could equally be written: + +@lisp +(define (make-combined-string name address) + (string-append "Name=" name ":Address=" address)) +@end lisp + +This kind of procedure definition creates a procedure that requires +exactly the expected number of arguments. There are two further forms +of the @code{lambda} expression, which create a procedure that can +accept a variable number of arguments: + +@lisp +(lambda (@var{arg1} @dots{} . @var{args}) @var{expression} @dots{}) + +(lambda @var{args} @var{expression} @dots{}) +@end lisp + +@noindent +The corresponding forms of the alternative @code{define} syntax are: + +@lisp +(define (@var{name} @var{arg1} @dots{} . @var{args}) @var{expression} @dots{}) + +(define (@var{name} . @var{args}) @var{expression} @dots{}) +@end lisp + +@noindent +For details on how these forms work, see @xref{Lambda}. + +Prior to Guile 2.0, Guile provided an extension to @code{define} syntax +that allowed you to nest the previous extension up to an arbitrary +depth. These are no longer provided by default, and instead have been +moved to @ref{Curried Definitions} + +(It could be argued that the alternative @code{define} forms are rather +confusing, especially for newcomers to the Scheme language, as they hide +both the role of @code{lambda} and the fact that procedures are values +that are stored in variables in the same way as any other kind of value. +On the other hand, they are very convenient, and they are also a good +example of another of Scheme's powerful features: the ability to specify +arbitrary syntactic transformations at run time, which can be applied to +subsequently read input.) + + +@node About Expressions +@section Expressions and Evaluation + +So far, we have met expressions that @emph{do} things, such as the +@code{define} expressions that create and initialize new variables, and +we have also talked about expressions that have @emph{values}, for +example the value of the procedure invocation expression: + +@lisp +(string-append "/home" "/" "andrew") +@end lisp + +@noindent +but we haven't yet been precise about what causes an expression like +this procedure invocation to be reduced to its ``value'', or how the +processing of such expressions relates to the execution of a Scheme +program as a whole. + +This section clarifies what we mean by an expression's value, by +introducing the idea of @dfn{evaluation}. It discusses the side effects +that evaluation can have, explains how each of the various types of +Scheme expression is evaluated, and describes the behaviour and use of +the Guile REPL as a mechanism for exploring evaluation. The section +concludes with a very brief summary of Scheme's common syntactic +expressions. + +@menu +* Evaluating:: How a Scheme program is executed. +* Tail Calls:: Space-safe recursion. +* The REPL:: Interacting with the Guile interpreter. +* Syntax Summary:: Common syntactic expressions -- in brief. +@end menu + + +@node Evaluating +@subsection Evaluating Expressions and Executing Programs + +In Scheme, the process of executing an expression is known as +@dfn{evaluation}. Evaluation has two kinds of result: + +@itemize @bullet +@item +the @dfn{value} of the evaluated expression + +@item +the @dfn{side effects} of the evaluation, which consist of any effects of +evaluating the expression that are not represented by the value. +@end itemize + +Of the expressions that we have met so far, @code{define} and +@code{set!} expressions have side effects --- the creation or +modification of a variable --- but no value; @code{lambda} expressions +have values --- the newly constructed procedures --- but no side +effects; and procedure invocation expressions, in general, have either +values, or side effects, or both. + +It is tempting to try to define more intuitively what we mean by +``value'' and ``side effects'', and what the difference between them is. +In general, though, this is extremely difficult. It is also +unnecessary; instead, we can quite happily define the behaviour of a +Scheme program by specifying how Scheme executes a program as a whole, +and then by describing the value and side effects of evaluation for each +type of expression individually. + +@noindent +So, some@footnote{These definitions are approximate. For the whole +and detailed truth, see @ref{Formal syntax and semantics,R5RS +syntax,,r5rs,The Revised(5) Report on the Algorithmic Language +Scheme}.} definitions@dots{} + +@itemize @bullet + +@item +A Scheme program consists of a sequence of expressions. + +@item +A Scheme interpreter executes the program by evaluating these +expressions in order, one by one. + +@item +An expression can be + +@itemize @bullet +@item +a piece of literal data, such as a number @code{2.3} or a string +@code{"Hello world!"} +@item +a variable name +@item +a procedure invocation expression +@item +one of Scheme's special syntactic expressions. +@end itemize +@end itemize + +@noindent +The following subsections describe how each of these types of expression +is evaluated. + +@menu +* Eval Literal:: Evaluating literal data. +* Eval Variable:: Evaluating variable references. +* Eval Procedure:: Evaluating procedure invocation expressions. +* Eval Special:: Evaluating special syntactic expressions. +@end menu + +@node Eval Literal +@subsubsection Evaluating Literal Data + +When a literal data expression is evaluated, the value of the expression +is simply the value that the expression describes. The evaluation of a +literal data expression has no side effects. + +@noindent +So, for example, + +@itemize @bullet +@item +the value of the expression @code{"abc"} is the string value +@code{"abc"} + +@item +the value of the expression @code{3+4i} is the complex number 3 + 4i + +@item +the value of the expression @code{#(1 2 3)} is a three-element vector +containing the numeric values 1, 2 and 3. +@end itemize + +For any data type which can be expressed literally like this, the syntax +of the literal data expression for that data type --- in other words, +what you need to write in your code to indicate a literal value of that +type --- is known as the data type's @dfn{read syntax}. This manual +specifies the read syntax for each such data type in the section that +describes that data type. + +Some data types do not have a read syntax. Procedures, for example, +cannot be expressed as literal data; they must be created using a +@code{lambda} expression (@pxref{Creating a Procedure}) or implicitly +using the shorthand form of @code{define} (@pxref{Lambda Alternatives}). + + +@node Eval Variable +@subsubsection Evaluating a Variable Reference + +When an expression that consists simply of a variable name is evaluated, +the value of the expression is the value of the named variable. The +evaluation of a variable reference expression has no side effects. + +So, after + +@lisp +(define key "Paul Evans") +@end lisp + +@noindent +the value of the expression @code{key} is the string value @code{"Paul +Evans"}. If @var{key} is then modified by + +@lisp +(set! key 3.74) +@end lisp + +@noindent +the value of the expression @code{key} is the numeric value 3.74. + +If there is no variable with the specified name, evaluation of the +variable reference expression signals an error. + + +@node Eval Procedure +@subsubsection Evaluating a Procedure Invocation Expression + +This is where evaluation starts getting interesting! As already noted, +a procedure invocation expression has the form + +@lisp +(@var{procedure} [@var{arg1} [@var{arg2} @dots{}]]) +@end lisp + +@noindent +where @var{procedure} must be an expression whose value, when evaluated, +is a procedure. + +The evaluation of a procedure invocation expression like this proceeds +by + +@itemize @bullet +@item +evaluating individually the expressions @var{procedure}, @var{arg1}, +@var{arg2}, and so on + +@item +calling the procedure that is the value of the @var{procedure} +expression with the list of values obtained from the evaluations of +@var{arg1}, @var{arg2} etc. as its parameters. +@end itemize + +For a procedure defined in Scheme, ``calling the procedure with the list +of values as its parameters'' means binding the values to the +procedure's formal parameters and then evaluating the sequence of +expressions that make up the body of the procedure definition. The +value of the procedure invocation expression is the value of the last +evaluated expression in the procedure body. The side effects of calling +the procedure are the combination of the side effects of the sequence of +evaluations of expressions in the procedure body. + +For a built-in procedure, the value and side-effects of calling the +procedure are best described by that procedure's documentation. + +Note that the complete side effects of evaluating a procedure invocation +expression consist not only of the side effects of the procedure call, +but also of any side effects of the preceding evaluation of the +expressions @var{procedure}, @var{arg1}, @var{arg2}, and so on. + +To illustrate this, let's look again at the procedure invocation +expression: + +@lisp +(string-length (string-append "/home" "/" "andrew")) +@end lisp + +In the outermost expression, @var{procedure} is @code{string-length} and +@var{arg1} is @code{(string-append "/home" "/" "andrew")}. + +@itemize @bullet +@item +Evaluation of @code{string-length}, which is a variable, gives a +procedure value that implements the expected behaviour for +``string-length''. + +@item +Evaluation of @code{(string-append "/home" "/" "andrew")}, which is +another procedure invocation expression, means evaluating each of + +@itemize @bullet +@item +@code{string-append}, which gives a procedure value that implements the +expected behaviour for ``string-append'' + +@item +@code{"/home"}, which gives the string value @code{"/home"} + +@item +@code{"/"}, which gives the string value @code{"/"} + +@item +@code{"andrew"}, which gives the string value @code{"andrew"} +@end itemize + +and then invoking the procedure value with this list of string values as +its arguments. The resulting value is a single string value that is the +concatenation of all the arguments, namely @code{"/home/andrew"}. +@end itemize + +In the evaluation of the outermost expression, the interpreter can now +invoke the procedure value obtained from @var{procedure} with the value +obtained from @var{arg1} as its arguments. The resulting value is a +numeric value that is the length of the argument string, which is 12. + + +@node Eval Special +@subsubsection Evaluating Special Syntactic Expressions + +When a procedure invocation expression is evaluated, the procedure and +@emph{all} the argument expressions must be evaluated before the +procedure can be invoked. Special syntactic expressions are special +because they are able to manipulate their arguments in an unevaluated +form, and can choose whether to evaluate any or all of the argument +expressions. + +Why is this needed? Consider a program fragment that asks the user +whether or not to delete a file, and then deletes the file if the user +answers yes. + +@lisp +(if (string=? (read-answer "Should I delete this file?") + "yes") + (delete-file file)) +@end lisp + +If the outermost @code{(if @dots{})} expression here was a procedure +invocation expression, the expression @code{(delete-file file)}, whose +side effect is to actually delete a file, would already have been +evaluated before the @code{if} procedure even got invoked! Clearly this +is no use --- the whole point of an @code{if} expression is that the +@dfn{consequent} expression is only evaluated if the condition of the +@code{if} expression is ``true''. + +Therefore @code{if} must be special syntax, not a procedure. Other +special syntaxes that we have already met are @code{define}, @code{set!} +and @code{lambda}. @code{define} and @code{set!} are syntax because +they need to know the variable @emph{name} that is given as the first +argument in a @code{define} or @code{set!} expression, not that +variable's value. @code{lambda} is syntax because it does not +immediately evaluate the expressions that define the procedure body; +instead it creates a procedure object that incorporates these +expressions so that they can be evaluated in the future, when that +procedure is invoked. + +The rules for evaluating each special syntactic expression are specified +individually for each special syntax. For a summary of standard special +syntax, see @xref{Syntax Summary}. + + +@node Tail Calls +@subsection Tail calls +@cindex tail calls +@cindex recursion + +Scheme is ``properly tail recursive'', meaning that tail calls or +recursions from certain contexts do not consume stack space or other +resources and can therefore be used on arbitrarily large data or for +an arbitrarily long calculation. Consider for example, + +@example +(define (foo n) + (display n) + (newline) + (foo (1+ n))) + +(foo 1) +@print{} +1 +2 +3 +@dots{} +@end example + +@code{foo} prints numbers infinitely, starting from the given @var{n}. +It's implemented by printing @var{n} then recursing to itself to print +@math{@var{n}+1} and so on. This recursion is a tail call, it's the +last thing done, and in Scheme such tail calls can be made without +limit. + +Or consider a case where a value is returned, a version of the SRFI-1 +@code{last} function (@pxref{SRFI-1 Selectors}) returning the last +element of a list, + +@example +(define (my-last lst) + (if (null? (cdr lst)) + (car lst) + (my-last (cdr lst)))) + +(my-last '(1 2 3)) @result{} 3 +@end example + +If the list has more than one element, @code{my-last} applies itself +to the @code{cdr}. This recursion is a tail call, there's no code +after it, and the return value is the return value from that call. In +Scheme this can be used on an arbitrarily long list argument. + +@sp 1 +A proper tail call is only available from certain contexts, namely the +following special form positions, + +@itemize @bullet +@item +@code{and} --- last expression + +@item +@code{begin} --- last expression + +@item +@code{case} --- last expression in each clause + +@item +@code{cond} --- last expression in each clause, and the call to a +@code{=>} procedure is a tail call + +@item +@code{do} --- last result expression + +@item +@code{if} --- ``true'' and ``false'' leg expressions + +@item +@code{lambda} --- last expression in body + +@item +@code{let}, @code{let*}, @code{letrec}, @code{let-syntax}, +@code{letrec-syntax} --- last expression in body + +@item +@code{or} --- last expression +@end itemize + +@noindent +The following core functions make tail calls, + +@itemize @bullet +@item +@code{apply} --- tail call to given procedure + +@item +@code{call-with-current-continuation} --- tail call to the procedure +receiving the new continuation + +@item +@code{call-with-values} --- tail call to the values-receiving +procedure + +@item +@code{eval} --- tail call to evaluate the form + +@item +@code{string-any}, @code{string-every} --- tail call to predicate on +the last character (if that point is reached) +@end itemize + +@sp 1 +The above are just core functions and special forms. Tail calls in +other modules are described with the relevant documentation, for +example SRFI-1 @code{any} and @code{every} (@pxref{SRFI-1 Searching}). + +It will be noted there are a lot of places which could potentially be +tail calls, for instance the last call in a @code{for-each}, but only +those explicitly described are guaranteed. + + +@node The REPL +@subsection Using the Guile REPL + +If you start Guile without specifying a particular program for it to +execute, Guile enters its standard Read Evaluate Print Loop --- or +@dfn{REPL} for short. In this mode, Guile repeatedly reads in the next +Scheme expression that the user types, evaluates it, and prints the +resulting value. + +The REPL is a useful mechanism for exploring the evaluation behaviour +described in the previous subsection. If you type @code{string-append}, +for example, the REPL replies @code{#<primitive-procedure +string-append>}, illustrating the relationship between the variable +@code{string-append} and the procedure value stored in that variable. + +In this manual, the notation @result{} is used to mean ``evaluates +to''. Wherever you see an example of the form + +@lisp +@var{expression} +@result{} +@var{result} +@end lisp + +@noindent +feel free to try it out yourself by typing @var{expression} into the +REPL and checking that it gives the expected @var{result}. + + +@node Syntax Summary +@subsection Summary of Common Syntax + +This subsection lists the most commonly used Scheme syntactic +expressions, simply so that you will recognize common special syntax +when you see it. For a full description of each of these syntaxes, +follow the appropriate reference. + +@code{lambda} (@pxref{Lambda}) is used to construct procedure objects. + +@code{define} (@pxref{Top Level}) is used to create a new variable and +set its initial value. + +@code{set!} (@pxref{Top Level}) is used to modify an existing variable's +value. + +@code{let}, @code{let*} and @code{letrec} (@pxref{Local Bindings}) +create an inner lexical environment for the evaluation of a sequence of +expressions, in which a specified set of local variables is bound to the +values of a corresponding set of expressions. For an introduction to +environments, see @xref{About Closure}. + +@code{begin} (@pxref{begin}) executes a sequence of expressions in order +and returns the value of the last expression. Note that this is not the +same as a procedure which returns its last argument, because the +evaluation of a procedure invocation expression does not guarantee to +evaluate the arguments in order. + +@code{if} and @code{cond} (@pxref{Conditionals}) provide conditional +evaluation of argument expressions depending on whether one or more +conditions evaluate to ``true'' or ``false''. + +@code{case} (@pxref{Conditionals}) provides conditional evaluation of +argument expressions depending on whether a variable has one of a +specified group of values. + +@code{and} (@pxref{and or}) executes a sequence of expressions in order +until either there are no expressions left, or one of them evaluates to +``false''. + +@code{or} (@pxref{and or}) executes a sequence of expressions in order +until either there are no expressions left, or one of them evaluates to +``true''. + + +@node About Closure +@section The Concept of Closure + +@cindex closure + +The concept of @dfn{closure} is the idea that a lambda expression +``captures'' the variable bindings that are in lexical scope at the +point where the lambda expression occurs. The procedure created by the +lambda expression can refer to and mutate the captured bindings, and the +values of those bindings persist between procedure calls. + +This section explains and explores the various parts of this idea in +more detail. + +@menu +* About Environments:: Names, locations, values and environments. +* Local Variables:: Local variables and local environments. +* Chaining:: Environment chaining. +* Lexical Scope:: The meaning of lexical scoping. +* Closure:: Explaining the concept of closure. +* Serial Number:: Example 1: a serial number generator. +* Shared Variable:: Example 2: a shared persistent variable. +* Callback Closure:: Example 3: the callback closure problem. +* OO Closure:: Example 4: object orientation. +@end menu + +@node About Environments +@subsection Names, Locations, Values and Environments + +@cindex location +@cindex environment +@cindex vcell +@cindex top level environment +@cindex environment, top level + +We said earlier that a variable name in a Scheme program is associated +with a location in which any kind of Scheme value may be stored. +(Incidentally, the term ``vcell'' is often used in Lisp and Scheme +circles as an alternative to ``location''.) Thus part of what we mean +when we talk about ``creating a variable'' is in fact establishing an +association between a name, or identifier, that is used by the Scheme +program code, and the variable location to which that name refers. +Although the value that is stored in that location may change, the +location to which a given name refers is always the same. + +We can illustrate this by breaking down the operation of the +@code{define} syntax into three parts: @code{define} + +@itemize @bullet +@item +creates a new location + +@item +establishes an association between that location and the name specified +as the first argument of the @code{define} expression + +@item +stores in that location the value obtained by evaluating the second +argument of the @code{define} expression. +@end itemize + +A collection of associations between names and locations is called an +@dfn{environment}. When you create a top level variable in a program +using @code{define}, the name-location association for that variable is +added to the ``top level'' environment. The ``top level'' environment +also includes name-location associations for all the procedures that are +supplied by standard Scheme. + +It is also possible to create environments other than the top level one, +and to create variable bindings, or name-location associations, in those +environments. This ability is a key ingredient in the concept of +closure; the next subsection shows how it is done. + + +@node Local Variables +@subsection Local Variables and Environments + +@cindex local variable +@cindex variable, local +@cindex local environment +@cindex environment, local + +We have seen how to create top level variables using the @code{define} +syntax (@pxref{Definition}). It is often useful to create variables +that are more limited in their scope, typically as part of a procedure +body. In Scheme, this is done using the @code{let} syntax, or one of +its modified forms @code{let*} and @code{letrec}. These syntaxes are +described in full later in the manual (@pxref{Local Bindings}). Here +our purpose is to illustrate their use just enough that we can see how +local variables work. + +For example, the following code uses a local variable @code{s} to +simplify the computation of the area of a triangle given the lengths of +its three sides. + +@lisp +(define a 5.3) +(define b 4.7) +(define c 2.8) + +(define area + (let ((s (/ (+ a b c) 2))) + (sqrt (* s (- s a) (- s b) (- s c))))) +@end lisp + +The effect of the @code{let} expression is to create a new environment +and, within this environment, an association between the name @code{s} +and a new location whose initial value is obtained by evaluating +@code{(/ (+ a b c) 2)}. The expressions in the body of the @code{let}, +namely @code{(sqrt (* s (- s a) (- s b) (- s c)))}, are then evaluated +in the context of the new environment, and the value of the last +expression evaluated becomes the value of the whole @code{let} +expression, and therefore the value of the variable @code{area}. + + +@node Chaining +@subsection Environment Chaining + +@cindex shadowing an imported variable binding +@cindex chaining environments + +In the example of the previous subsection, we glossed over an important +point. The body of the @code{let} expression in that example refers not +only to the local variable @code{s}, but also to the top level variables +@code{a}, @code{b}, @code{c} and @code{sqrt}. (@code{sqrt} is the +standard Scheme procedure for calculating a square root.) If the body +of the @code{let} expression is evaluated in the context of the +@emph{local} @code{let} environment, how does the evaluation get at the +values of these top level variables? + +The answer is that the local environment created by a @code{let} +expression automatically has a reference to its containing environment +--- in this case the top level environment --- and that the Scheme +interpreter automatically looks for a variable binding in the containing +environment if it doesn't find one in the local environment. More +generally, every environment except for the top level one has a +reference to its containing environment, and the interpreter keeps +searching back up the chain of environments --- from most local to top +level --- until it either finds a variable binding for the required +identifier or exhausts the chain. + +This description also determines what happens when there is more than +one variable binding with the same name. Suppose, continuing the +example of the previous subsection, that there was also a pre-existing +top level variable @code{s} created by the expression: + +@lisp +(define s "Some beans, my lord!") +@end lisp + +Then both the top level environment and the local @code{let} environment +would contain bindings for the name @code{s}. When evaluating code +within the @code{let} body, the interpreter looks first in the local +@code{let} environment, and so finds the binding for @code{s} created by +the @code{let} syntax. Even though this environment has a reference to +the top level environment, which also has a binding for @code{s}, the +interpreter doesn't get as far as looking there. When evaluating code +outside the @code{let} body, the interpreter looks up variable names in +the top level environment, so the name @code{s} refers to the top level +variable. + +Within the @code{let} body, the binding for @code{s} in the local +environment is said to @dfn{shadow} the binding for @code{s} in the top +level environment. + + +@node Lexical Scope +@subsection Lexical Scope + +The rules that we have just been describing are the details of how +Scheme implements ``lexical scoping''. This subsection takes a brief +diversion to explain what lexical scope means in general and to present +an example of non-lexical scoping. + +``Lexical scope'' in general is the idea that + +@itemize @bullet +@item +an identifier at a particular place in a program always refers to the +same variable location --- where ``always'' means ``every time that the +containing expression is executed'', and that + +@item +the variable location to which it refers can be determined by static +examination of the source code context in which that identifier appears, +without having to consider the flow of execution through the program as +a whole. +@end itemize + +In practice, lexical scoping is the norm for most programming languages, +and probably corresponds to what you would intuitively consider to be +``normal''. You may even be wondering how the situation could possibly +--- and usefully --- be otherwise. To demonstrate that another kind of +scoping is possible, therefore, and to compare it against lexical +scoping, the following subsection presents an example of non-lexical +scoping and examines in detail how its behavior differs from the +corresponding lexically scoped code. + +@menu +* Scoping Example:: An example of non-lexical scoping. +@end menu + + +@node Scoping Example +@subsubsection An Example of Non-Lexical Scoping + +To demonstrate that non-lexical scoping does exist and can be useful, we +present the following example from Emacs Lisp, which is a ``dynamically +scoped'' language. + +@lisp +(defvar currency-abbreviation "USD") + +(defun currency-string (units hundredths) + (concat currency-abbreviation + (number-to-string units) + "." + (number-to-string hundredths))) + +(defun french-currency-string (units hundredths) + (let ((currency-abbreviation "FRF")) + (currency-string units hundredths))) +@end lisp + +The question to focus on here is: what does the identifier +@code{currency-abbreviation} refer to in the @code{currency-string} +function? The answer, in Emacs Lisp, is that all variable bindings go +onto a single stack, and that @code{currency-abbreviation} refers to the +topmost binding from that stack which has the name +``currency-abbreviation''. The binding that is created by the +@code{defvar} form, to the value @code{"USD"}, is only relevant if none +of the code that calls @code{currency-string} rebinds the name +``currency-abbreviation'' in the meanwhile. + +The second function @code{french-currency-string} works precisely by +taking advantage of this behaviour. It creates a new binding for the +name ``currency-abbreviation'' which overrides the one established by +the @code{defvar} form. + +@lisp +;; Note! This is Emacs Lisp evaluation, not Scheme! +(french-currency-string 33 44) +@result{} +"FRF33.44" +@end lisp + +Now let's look at the corresponding, @emph{lexically scoped} Scheme +code: + +@lisp +(define currency-abbreviation "USD") + +(define (currency-string units hundredths) + (string-append currency-abbreviation + (number->string units) + "." + (number->string hundredths))) + +(define (french-currency-string units hundredths) + (let ((currency-abbreviation "FRF")) + (currency-string units hundredths))) +@end lisp + +According to the rules of lexical scoping, the +@code{currency-abbreviation} in @code{currency-string} refers to the +variable location in the innermost environment at that point in the code +which has a binding for @code{currency-abbreviation}, which is the +variable location in the top level environment created by the preceding +@code{(define currency-abbreviation @dots{})} expression. + +In Scheme, therefore, the @code{french-currency-string} procedure does +not work as intended. The variable binding that it creates for +``currency-abbreviation'' is purely local to the code that forms the +body of the @code{let} expression. Since this code doesn't directly use +the name ``currency-abbreviation'' at all, the binding is pointless. + +@lisp +(french-currency-string 33 44) +@result{} +"USD33.44" +@end lisp + +This begs the question of how the Emacs Lisp behaviour can be +implemented in Scheme. In general, this is a design question whose +answer depends upon the problem that is being addressed. In this case, +the best answer may be that @code{currency-string} should be +redesigned so that it can take an optional third argument. This third +argument, if supplied, is interpreted as a currency abbreviation that +overrides the default. + +It is possible to change @code{french-currency-string} so that it mostly +works without changing @code{currency-string}, but the fix is inelegant, +and susceptible to interrupts that could leave the +@code{currency-abbreviation} variable in the wrong state: + +@lisp +(define (french-currency-string units hundredths) + (set! currency-abbreviation "FRF") + (let ((result (currency-string units hundredths))) + (set! currency-abbreviation "USD") + result)) +@end lisp + +The key point here is that the code does not create any local binding +for the identifier @code{currency-abbreviation}, so all occurrences of +this identifier refer to the top level variable. + + +@node Closure +@subsection Closure + +Consider a @code{let} expression that doesn't contain any +@code{lambda}s: + +@lisp +(let ((s (/ (+ a b c) 2))) + (sqrt (* s (- s a) (- s b) (- s c)))) +@end lisp + +@noindent +When the Scheme interpreter evaluates this, it + +@itemize @bullet +@item +creates a new environment with a reference to the environment that was +current when it encountered the @code{let} + +@item +creates a variable binding for @code{s} in the new environment, with +value given by @code{(/ (+ a b c) 2)} + +@item +evaluates the expression in the body of the @code{let} in the context of +the new local environment, and remembers the value @code{V} + +@item +forgets the local environment + +@item +continues evaluating the expression that contained the @code{let}, using +the value @code{V} as the value of the @code{let} expression, in the +context of the containing environment. +@end itemize + +After the @code{let} expression has been evaluated, the local +environment that was created is simply forgotten, and there is no longer +any way to access the binding that was created in this environment. If +the same code is evaluated again, it will follow the same steps again, +creating a second new local environment that has no connection with the +first, and then forgetting this one as well. + +If the @code{let} body contains a @code{lambda} expression, however, the +local environment is @emph{not} forgotten. Instead, it becomes +associated with the procedure that is created by the @code{lambda} +expression, and is reinstated every time that that procedure is called. +In detail, this works as follows. + +@itemize @bullet +@item +When the Scheme interpreter evaluates a @code{lambda} expression, to +create a procedure object, it stores the current environment as part of +the procedure definition. + +@item +Then, whenever that procedure is called, the interpreter reinstates the +environment that is stored in the procedure definition and evaluates the +procedure body within the context of that environment. +@end itemize + +The result is that the procedure body is always evaluated in the context +of the environment that was current when the procedure was created. + +This is what is meant by @dfn{closure}. The next few subsections +present examples that explore the usefulness of this concept. + + +@node Serial Number +@subsection Example 1: A Serial Number Generator + +This example uses closure to create a procedure with a variable binding +that is private to the procedure, like a local variable, but whose value +persists between procedure calls. + +@lisp +(define (make-serial-number-generator) + (let ((current-serial-number 0)) + (lambda () + (set! current-serial-number (+ current-serial-number 1)) + current-serial-number))) + +(define entry-sn-generator (make-serial-number-generator)) + +(entry-sn-generator) +@result{} +1 + +(entry-sn-generator) +@result{} +2 +@end lisp + +When @code{make-serial-number-generator} is called, it creates a local +environment with a binding for @code{current-serial-number} whose +initial value is 0, then, within this environment, creates a procedure. +The local environment is stored within the created procedure object and +so persists for the lifetime of the created procedure. + +Every time the created procedure is invoked, it increments the value of +the @code{current-serial-number} binding in the captured environment and +then returns the current value. + +Note that @code{make-serial-number-generator} can be called again to +create a second serial number generator that is independent of the +first. Every new invocation of @code{make-serial-number-generator} +creates a new local @code{let} environment and returns a new procedure +object with an association to this environment. + + +@node Shared Variable +@subsection Example 2: A Shared Persistent Variable + +This example uses closure to create two procedures, @code{get-balance} +and @code{deposit}, that both refer to the same captured local +environment so that they can both access the @code{balance} variable +binding inside that environment. The value of this variable binding +persists between calls to either procedure. + +Note that the captured @code{balance} variable binding is private to +these two procedures: it is not directly accessible to any other code. +It can only be accessed indirectly via @code{get-balance} or +@code{deposit}, as illustrated by the @code{withdraw} procedure. + +@lisp +(define get-balance #f) +(define deposit #f) + +(let ((balance 0)) + (set! get-balance + (lambda () + balance)) + (set! deposit + (lambda (amount) + (set! balance (+ balance amount)) + balance))) + +(define (withdraw amount) + (deposit (- amount))) + +(get-balance) +@result{} +0 + +(deposit 50) +@result{} +50 + +(withdraw 75) +@result{} +-25 +@end lisp + +An important detail here is that the @code{get-balance} and +@code{deposit} variables must be set up by @code{define}ing them at top +level and then @code{set!}ing their values inside the @code{let} body. +Using @code{define} within the @code{let} body would not work: this +would create variable bindings within the local @code{let} environment +that would not be accessible at top level. + + +@node Callback Closure +@subsection Example 3: The Callback Closure Problem + +A frequently used programming model for library code is to allow an +application to register a callback function for the library to call when +some particular event occurs. It is often useful for the application to +make several such registrations using the same callback function, for +example if several similar library events can be handled using the same +application code, but the need then arises to distinguish the callback +function calls that are associated with one callback registration from +those that are associated with different callback registrations. + +In languages without the ability to create functions dynamically, this +problem is usually solved by passing a @code{user_data} parameter on the +registration call, and including the value of this parameter as one of +the parameters on the callback function. Here is an example of +declarations using this solution in C: + +@example +typedef void (event_handler_t) (int event_type, + void *user_data); + +void register_callback (int event_type, + event_handler_t *handler, + void *user_data); +@end example + +In Scheme, closure can be used to achieve the same functionality without +requiring the library code to store a @code{user-data} for each callback +registration. + +@lisp +;; In the library: + +(define (register-callback event-type handler-proc) + @dots{}) + +;; In the application: + +(define (make-handler event-type user-data) + (lambda () + @dots{} + <code referencing event-type and user-data> + @dots{})) + +(register-callback event-type + (make-handler event-type @dots{})) +@end lisp + +As far as the library is concerned, @code{handler-proc} is a procedure +with no arguments, and all the library has to do is call it when the +appropriate event occurs. From the application's point of view, though, +the handler procedure has used closure to capture an environment that +includes all the context that the handler code needs --- +@code{event-type} and @code{user-data} --- to handle the event +correctly. + + +@node OO Closure +@subsection Example 4: Object Orientation + +Closure is the capture of an environment, containing persistent variable +bindings, within the definition of a procedure or a set of related +procedures. This is rather similar to the idea in some object oriented +languages of encapsulating a set of related data variables inside an +``object'', together with a set of ``methods'' that operate on the +encapsulated data. The following example shows how closure can be used +to emulate the ideas of objects, methods and encapsulation in Scheme. + +@lisp +(define (make-account) + (let ((balance 0)) + (define (get-balance) + balance) + (define (deposit amount) + (set! balance (+ balance amount)) + balance) + (define (withdraw amount) + (deposit (- amount))) + + (lambda args + (apply + (case (car args) + ((get-balance) get-balance) + ((deposit) deposit) + ((withdraw) withdraw) + (else (error "Invalid method!"))) + (cdr args))))) +@end lisp + +Each call to @code{make-account} creates and returns a new procedure, +created by the expression in the example code that begins ``(lambda +args''. + +@lisp +(define my-account (make-account)) + +my-account +@result{} +#<procedure args> +@end lisp + +This procedure acts as an account object with methods +@code{get-balance}, @code{deposit} and @code{withdraw}. To apply one of +the methods to the account, you call the procedure with a symbol +indicating the required method as the first parameter, followed by any +other parameters that are required by that method. + +@lisp +(my-account 'get-balance) +@result{} +0 + +(my-account 'withdraw 5) +@result{} +-5 + +(my-account 'deposit 396) +@result{} +391 + +(my-account 'get-balance) +@result{} +391 +@end lisp + +Note how, in this example, both the current balance and the helper +procedures @code{get-balance}, @code{deposit} and @code{withdraw}, used +to implement the guts of the account object's methods, are all stored in +variable bindings within the private local environment captured by the +@code{lambda} expression that creates the account object procedure. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-indices.texi b/doc/ref/scheme-indices.texi new file mode 100644 index 000000000..bbb644cc5 --- /dev/null +++ b/doc/ref/scheme-indices.texi @@ -0,0 +1,16 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node R5RS Index +@unnumbered R5RS Index + +@printindex rn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-intro.texi b/doc/ref/scheme-intro.texi new file mode 100644 index 000000000..b8a502475 --- /dev/null +++ b/doc/ref/scheme-intro.texi @@ -0,0 +1,38 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Guile Scheme +@section Guile's Implementation of Scheme + +Guile's core language is Scheme, which is specified and described in the +series of reports known as @dfn{RnRS}. @dfn{RnRS} is shorthand for the +@iftex +@dfn{Revised@math{^n} Report on the Algorithmic Language Scheme}. +@end iftex +@ifnottex +@dfn{Revised^n Report on the Algorithmic Language Scheme}. +@end ifnottex +Guile complies fully with R5RS (@pxref{Top, +,Introduction,r5rs,R5RS}), and implements some aspects of R6RS. + +Guile also has many extensions that go beyond these reports. Some of +the areas where Guile extends R5RS are: + +@itemize @bullet +@item +Guile's interactive documentation system + +@item +Guile's support for POSIX-compliant network programming + +@item +GOOPS -- Guile's framework for object oriented programming. +@end itemize + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-reading.texi b/doc/ref/scheme-reading.texi new file mode 100644 index 000000000..f147ea00d --- /dev/null +++ b/doc/ref/scheme-reading.texi @@ -0,0 +1,34 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Further Reading +@section Further Reading + +@itemize @bullet + +@item +The website @url{http://www.schemers.org/} is a good starting point for +all things Scheme. + +@item +Dorai Sitaram's online Scheme tutorial, @dfn{Teach Yourself Scheme in +Fixnum Days}, at +@url{http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme.html}. +Includes a nice explanation of continuations. + +@item +The complete text of @dfn{Structure and Interpretation of Computer +Programs}, the classic introduction to computer science and Scheme by +Hal Abelson, Jerry Sussman and Julie Sussman, is now available online at +@url{http://mitpress.mit.edu/sicp/sicp.html}. This site also provides +teaching materials related to the book, and all the source code used in +the book, in a form suitable for loading and running. +@end itemize + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-scripts.texi b/doc/ref/scheme-scripts.texi new file mode 100644 index 000000000..221c8ba20 --- /dev/null +++ b/doc/ref/scheme-scripts.texi @@ -0,0 +1,487 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Guile Scripting +@section Guile Scripting + +Like AWK, Perl, or any shell, Guile can interpret script files. A Guile +script is simply a file of Scheme code with some extra information at +the beginning which tells the operating system how to invoke Guile, and +then tells Guile how to handle the Scheme code. + +@menu +* The Top of a Script File:: How to start a Guile script. +* The Meta Switch:: Passing complex argument lists to Guile + from shell scripts. +* Command Line Handling:: Accessing the command line from a script. +* Scripting Examples:: +@end menu + + +@node The Top of a Script File +@subsection The Top of a Script File + +The first line of a Guile script must tell the operating system to use +Guile to evaluate the script, and then tell Guile how to go about doing +that. Here is the simplest case: + +@itemize @bullet + +@item +The first two characters of the file must be @samp{#!}. + +The operating system interprets this to mean that the rest of the line +is the name of an executable that can interpret the script. Guile, +however, interprets these characters as the beginning of a multi-line +comment, terminated by the characters @samp{!#} on a line by themselves. +(This is an extension to the syntax described in R5RS, added to support +shell scripts.) + +@item +Immediately after those two characters must come the full pathname to +the Guile interpreter. On most systems, this would be +@samp{/usr/local/bin/guile}. + +@item +Then must come a space, followed by a command-line argument to pass to +Guile; this should be @samp{-s}. This switch tells Guile to run a +script, instead of soliciting the user for input from the terminal. +There are more elaborate things one can do here; see @ref{The Meta +Switch}. + +@item +Follow this with a newline. + +@item +The second line of the script should contain only the characters +@samp{!#} --- just like the top of the file, but reversed. The +operating system never reads this far, but Guile treats this as the end +of the comment begun on the first line by the @samp{#!} characters. + +@item +If this source code file is not ASCII or ISO-8859-1 encoded, a coding +declaration such as @code{coding: utf-8} should appear in a comment +somewhere in the first five lines of the file: see @ref{Character +Encoding of Source Files}. + +@item +The rest of the file should be a Scheme program. + +@end itemize + +Guile reads the program, evaluating expressions in the order that they +appear. Upon reaching the end of the file, Guile exits. + +@node The Meta Switch +@subsection The Meta Switch + +Guile's command-line switches allow the programmer to describe +reasonably complicated actions in scripts. Unfortunately, the POSIX +script invocation mechanism only allows one argument to appear on the +@samp{#!} line after the path to the Guile executable, and imposes +arbitrary limits on that argument's length. Suppose you wrote a script +starting like this: +@example +#!/usr/local/bin/guile -e main -s +!# +(define (main args) + (map (lambda (arg) (display arg) (display " ")) + (cdr args)) + (newline)) +@end example +The intended meaning is clear: load the file, and then call @code{main} +on the command-line arguments. However, the system will treat +everything after the Guile path as a single argument --- the string +@code{"-e main -s"} --- which is not what we want. + +As a workaround, the meta switch @code{\} allows the Guile programmer to +specify an arbitrary number of options without patching the kernel. If +the first argument to Guile is @code{\}, Guile will open the script file +whose name follows the @code{\}, parse arguments starting from the +file's second line (according to rules described below), and substitute +them for the @code{\} switch. + +Working in concert with the meta switch, Guile treats the characters +@samp{#!} as the beginning of a comment which extends through the next +line containing only the characters @samp{!#}. This sort of comment may +appear anywhere in a Guile program, but it is most useful at the top of +a file, meshing magically with the POSIX script invocation mechanism. + +Thus, consider a script named @file{/u/jimb/ekko} which starts like this: +@example +#!/usr/local/bin/guile \ +-e main -s +!# +(define (main args) + (map (lambda (arg) (display arg) (display " ")) + (cdr args)) + (newline)) +@end example + +Suppose a user invokes this script as follows: +@example +$ /u/jimb/ekko a b c +@end example + +Here's what happens: +@itemize @bullet + +@item +the operating system recognizes the @samp{#!} token at the top of the +file, and rewrites the command line to: +@example +/usr/local/bin/guile \ /u/jimb/ekko a b c +@end example +This is the usual behavior, prescribed by POSIX. + +@item +When Guile sees the first two arguments, @code{\ /u/jimb/ekko}, it opens +@file{/u/jimb/ekko}, parses the three arguments @code{-e}, @code{main}, +and @code{-s} from it, and substitutes them for the @code{\} switch. +Thus, Guile's command line now reads: +@example +/usr/local/bin/guile -e main -s /u/jimb/ekko a b c +@end example + +@item +Guile then processes these switches: it loads @file{/u/jimb/ekko} as a +file of Scheme code (treating the first three lines as a comment), and +then performs the application @code{(main "/u/jimb/ekko" "a" "b" "c")}. + +@end itemize + + +When Guile sees the meta switch @code{\}, it parses command-line +argument from the script file according to the following rules: +@itemize @bullet + +@item +Each space character terminates an argument. This means that two +spaces in a row introduce an argument @code{""}. + +@item +The tab character is not permitted (unless you quote it with the +backslash character, as described below), to avoid confusion. + +@item +The newline character terminates the sequence of arguments, and will +also terminate a final non-empty argument. (However, a newline +following a space will not introduce a final empty-string argument; +it only terminates the argument list.) + +@item +The backslash character is the escape character. It escapes backslash, +space, tab, and newline. The ANSI C escape sequences like @code{\n} and +@code{\t} are also supported. These produce argument constituents; the +two-character combination @code{\n} doesn't act like a terminating +newline. The escape sequence @code{\@var{NNN}} for exactly three octal +digits reads as the character whose ASCII code is @var{NNN}. As above, +characters produced this way are argument constituents. Backslash +followed by other characters is not allowed. + +@end itemize + + +@node Command Line Handling +@subsection Command Line Handling + +@c This section was written and contributed by Martin Grabmueller. + +The ability to accept and handle command line arguments is very +important when writing Guile scripts to solve particular problems, such +as extracting information from text files or interfacing with existing +command line applications. This chapter describes how Guile makes +command line arguments available to a Guile script, and the utilities +that Guile provides to help with the processing of command line +arguments. + +When a Guile script is invoked, Guile makes the command line arguments +accessible via the procedure @code{command-line}, which returns the +arguments as a list of strings. + +For example, if the script + +@example +#! /usr/local/bin/guile -s +!# +(write (command-line)) +(newline) +@end example + +@noindent +is saved in a file @file{cmdline-test.scm} and invoked using the command +line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}, the output +is + +@example +("./cmdline-test.scm" "bar.txt" "-o" "foo" "-frumple" "grob") +@end example + +If the script invocation includes a @code{-e} option, specifying a +procedure to call after loading the script, Guile will call that +procedure with @code{(command-line)} as its argument. So a script that +uses @code{-e} doesn't need to refer explicitly to @code{command-line} +in its code. For example, the script above would have identical +behaviour if it was written instead like this: + +@example +#! /usr/local/bin/guile \ +-e main -s +!# +(define (main args) + (write args) + (newline)) +@end example + +(Note the use of the meta switch @code{\} so that the script invocation +can include more than one Guile option: @xref{The Meta Switch}.) + +These scripts use the @code{#!} POSIX convention so that they can be +executed using their own file names directly, as in the example command +line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}. But they +can also be executed by typing out the implied Guile command line in +full, as in: + +@example +$ guile -s ./cmdline-test.scm bar.txt -o foo -frumple grob +@end example + +@noindent +or + +@example +$ guile -e main -s ./cmdline-test2.scm bar.txt -o foo -frumple grob +@end example + +Even when a script is invoked using this longer form, the arguments that +the script receives are the same as if it had been invoked using the +short form. Guile ensures that the @code{(command-line)} or @code{-e} +arguments are independent of how the script is invoked, by stripping off +the arguments that Guile itself processes. + +A script is free to parse and handle its command line arguments in any +way that it chooses. Where the set of possible options and arguments is +complex, however, it can get tricky to extract all the options, check +the validity of given arguments, and so on. This task can be greatly +simplified by taking advantage of the module @code{(ice-9 getopt-long)}, +which is distributed with Guile, @xref{getopt-long}. + + +@node Scripting Examples +@subsection Scripting Examples + +To start with, here are some examples of invoking Guile directly: + +@table @code + +@item guile -- a b c +Run Guile interactively; @code{(command-line)} will return @* +@code{("/usr/local/bin/guile" "a" "b" "c")}. + +@item guile -s /u/jimb/ex2 a b c +Load the file @file{/u/jimb/ex2}; @code{(command-line)} will return @* +@code{("/u/jimb/ex2" "a" "b" "c")}. + +@item guile -c '(write %load-path) (newline)' +Write the value of the variable @code{%load-path}, print a newline, +and exit. + +@item guile -e main -s /u/jimb/ex4 foo +Load the file @file{/u/jimb/ex4}, and then call the function +@code{main}, passing it the list @code{("/u/jimb/ex4" "foo")}. + +@item guile -e '(ex4)' -s /u/jimb/ex4.scm foo +Load the file @file{/u/jimb/ex4.scm}, and then call the function +@code{main} from the module '(ex4)', passing it the list +@code{("/u/jimb/ex4" "foo")}. + +@item guile -l first -ds -l last -s script +Load the files @file{first}, @file{script}, and @file{last}, in that +order. The @code{-ds} switch says when to process the @code{-s} +switch. For a more motivated example, see the scripts below. + +@end table + + +Here is a very simple Guile script: +@example +#!/usr/local/bin/guile -s +!# +(display "Hello, world!") +(newline) +@end example +The first line marks the file as a Guile script. When the user invokes +it, the system runs @file{/usr/local/bin/guile} to interpret the script, +passing @code{-s}, the script's filename, and any arguments given to the +script as command-line arguments. When Guile sees @code{-s +@var{script}}, it loads @var{script}. Thus, running this program +produces the output: +@example +Hello, world! +@end example + +Here is a script which prints the factorial of its argument: +@example +#!/usr/local/bin/guile -s +!# +(define (fact n) + (if (zero? n) 1 + (* n (fact (- n 1))))) + +(display (fact (string->number (cadr (command-line))))) +(newline) +@end example +In action: +@example +$ ./fact 5 +120 +$ +@end example + +However, suppose we want to use the definition of @code{fact} in this +file from another script. We can't simply @code{load} the script file, +and then use @code{fact}'s definition, because the script will try to +compute and display a factorial when we load it. To avoid this problem, +we might write the script this way: + +@example +#!/usr/local/bin/guile \ +-e main -s +!# +(define (fact n) + (if (zero? n) 1 + (* n (fact (- n 1))))) + +(define (main args) + (display (fact (string->number (cadr args)))) + (newline)) +@end example +This version packages the actions the script should perform in a +function, @code{main}. This allows us to load the file purely for its +definitions, without any extraneous computation taking place. Then we +used the meta switch @code{\} and the entry point switch @code{-e} to +tell Guile to call @code{main} after loading the script. +@example +$ ./fact 50 +30414093201713378043612608166064768844377641568960512000000000000 +@end example + +Suppose that we now want to write a script which computes the +@code{choose} function: given a set of @var{m} distinct objects, +@code{(choose @var{n} @var{m})} is the number of distinct subsets +containing @var{n} objects each. It's easy to write @code{choose} given +@code{fact}, so we might write the script this way: + +@example +#!/usr/local/bin/guile \ +-l fact -e main -s +!# +(define (choose n m) + (/ (fact m) (* (fact (- m n)) (fact n)))) + +(define (main args) + (let ((n (string->number (cadr args))) + (m (string->number (caddr args)))) + (display (choose n m)) + (newline))) +@end example + +The command-line arguments here tell Guile to first load the file +@file{fact}, and then run the script, with @code{main} as the entry +point. In other words, the @code{choose} script can use definitions +made in the @code{fact} script. Here are some sample runs: +@example +$ ./choose 0 4 +1 +$ ./choose 1 4 +4 +$ ./choose 2 4 +6 +$ ./choose 3 4 +4 +$ ./choose 4 4 +1 +$ ./choose 50 100 +100891344545564193334812497256 +@end example + +To call a specific procedure from a given module, we can use the special +form @code{(@@ (@var{module}) @var{procedure})}: + +@example +#!/usr/local/bin/guile \ +-l fact -e (@@ (fac) main) -s +!# +(define-module (fac) + #:export (main)) + +(define (choose n m) + (/ (fact m) (* (fact (- m n)) (fact n)))) + +(define (main args) + (let ((n (string->number (cadr args))) + (m (string->number (caddr args)))) + (display (choose n m)) + (newline))) +@end example + +We can use @code{@@@@} to invoke non-exported procedures. For exported +procedures, we can simplify this call with the shorthand +@code{(@var{module})}: + +@example +#!/usr/local/bin/guile \ +-l fact -e (fac) -s +!# +(define-module (fac) + #:export (main)) + +(define (choose n m) + (/ (fact m) (* (fact (- m n)) (fact n)))) + +(define (main args) + (let ((n (string->number (cadr args))) + (m (string->number (caddr args)))) + (display (choose n m)) + (newline))) +@end example + +For maximum portability, we can instead use the shell to execute +@command{guile} with specified command line arguments. Here we need to +take care to quote the command arguments correctly: + +@example +#!/usr/bin/env sh +exec guile -l fact -e '(@@ (fac) main)' -s "$0" "$@@" +!# +(define-module (fac) + #:export (main)) + +(define (choose n m) + (/ (fact m) (* (fact (- m n)) (fact n)))) + +(define (main args) + (let ((n (string->number (cadr args))) + (m (string->number (caddr args)))) + (display (choose n m)) + (newline))) +@end example + +Finally, seasoned scripters are probably missing a mention of +subprocesses. In Bash, for example, most shell scripts run other +programs like @code{sed} or the like to do the actual work. + +In Guile it's often possible get everything done within Guile itself, so +do give that a try first. But if you just need to run a program and +wait for it to finish, use @code{system*}. If you need to run a +sub-program and capture its output, or give it input, use +@code{open-pipe}. @xref{Processes}, and @xref{Pipes}, for more +information. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme-using.texi b/doc/ref/scheme-using.texi new file mode 100644 index 000000000..ac265fcca --- /dev/null +++ b/doc/ref/scheme-using.texi @@ -0,0 +1,809 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2006, 2010, 2011, 2012, 2013 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Using Guile Interactively +@section Using Guile Interactively + +When you start up Guile by typing just @code{guile}, without a +@code{-c} argument or the name of a script to execute, you get an +interactive interpreter where you can enter Scheme expressions, and +Guile will evaluate them and print the results for you. Here are some +simple examples. + +@lisp +scheme@@(guile-user)> (+ 3 4 5) +$1 = 12 +scheme@@(guile-user)> (display "Hello world!\n") +Hello world! +scheme@@(guile-user)> (values 'a 'b) +$2 = a +$3 = b +@end lisp + +@noindent +This mode of use is called a @dfn{REPL}, which is short for +``Read-Eval-Print Loop'', because the Guile interpreter first reads the +expression that you have typed, then evaluates it, and then prints the +result. + +The prompt shows you what language and module you are in. In this case, the +current language is @code{scheme}, and the current module is +@code{(guile-user)}. @xref{Other Languages}, for more information on Guile's +support for languages other than Scheme. + +@menu +* Init File:: +* Readline:: +* Value History:: +* REPL Commands:: +* Error Handling:: +* Interactive Debugging:: +@end menu + + +@node Init File +@subsection The Init File, @file{~/.guile} + +@cindex .guile +When run interactively, Guile will load a local initialization file from +@file{~/.guile}. This file should contain Scheme expressions for +evaluation. + +This facility lets the user customize their interactive Guile +environment, pulling in extra modules or parameterizing the REPL +implementation. + +To run Guile without loading the init file, use the @code{-q} +command-line option. + + +@node Readline +@subsection Readline + +To make it easier for you to repeat and vary previously entered +expressions, or to edit the expression that you're typing in, Guile +can use the GNU Readline library. This is not enabled by default +because of licensing reasons, but all you need to activate Readline is +the following pair of lines. + +@lisp +scheme@@(guile-user)> (use-modules (ice-9 readline)) +scheme@@(guile-user)> (activate-readline) +@end lisp + +It's a good idea to put these two lines (without the +@code{scheme@@(guile-user)>} prompts) in your @file{.guile} file. +@xref{Init File}, for more on @file{.guile}. + + +@node Value History +@subsection Value History + +Just as Readline helps you to reuse a previous input line, @dfn{value +history} allows you to use the @emph{result} of a previous evaluation in +a new expression. When value history is enabled, each evaluation result +is automatically assigned to the next in the sequence of variables +@code{$1}, @code{$2}, @dots{}. You can then use these variables in +subsequent expressions. + +@lisp +scheme@@(guile-user)> (iota 10) +$1 = (0 1 2 3 4 5 6 7 8 9) +scheme@@(guile-user)> (apply * (cdr $1)) +$2 = 362880 +scheme@@(guile-user)> (sqrt $2) +$3 = 602.3952191045344 +scheme@@(guile-user)> (cons $2 $1) +$4 = (362880 0 1 2 3 4 5 6 7 8 9) +@end lisp + +Value history is enabled by default, because Guile's REPL imports the +@code{(ice-9 history)} module. Value history may be turned off or on within the +repl, using the options interface: + +@lisp +scheme@@(guile-user)> ,option value-history #f +scheme@@(guile-user)> 'foo +foo +scheme@@(guile-user)> ,option value-history #t +scheme@@(guile-user)> 'bar +$5 = bar +@end lisp + +Note that previously recorded values are still accessible, even if value history +is off. In rare cases, these references to past computations can cause Guile to +use too much memory. One may clear these values, possibly enabling garbage +collection, via the @code{clear-value-history!} procedure, described below. + +The programmatic interface to value history is in a module: + +@lisp +(use-modules (ice-9 history)) +@end lisp + +@deffn {Scheme Procedure} value-history-enabled? +Return true if value history is enabled, or false otherwise. +@end deffn + +@deffn {Scheme Procedure} enable-value-history! +Turn on value history, if it was off. +@end deffn + +@deffn {Scheme Procedure} disable-value-history! +Turn off value history, if it was on. +@end deffn + +@deffn {Scheme Procedure} clear-value-history! +Clear the value history. If the stored values are not captured by some other +data structure or closure, they may then be reclaimed by the garbage collector. +@end deffn + + +@node REPL Commands +@subsection REPL Commands + +@cindex commands +The REPL exists to read expressions, evaluate them, and then print their +results. But sometimes one wants to tell the REPL to evaluate an +expression in a different way, or to do something else altogether. A +user can affect the way the REPL works with a @dfn{REPL command}. + +The previous section had an example of a command, in the form of +@code{,option}. + +@lisp +scheme@@(guile-user)> ,option value-history #t +@end lisp + +@noindent +Commands are distinguished from expressions by their initial comma +(@samp{,}). Since a comma cannot begin an expression in most languages, +it is an effective indicator to the REPL that the following text forms a +command, not an expression. + +REPL commands are convenient because they are always there. Even if the +current module doesn't have a binding for @code{pretty-print}, one can +always @code{,pretty-print}. + +The following sections document the various commands, grouped together +by functionality. Many of the commands have abbreviations; see the +online help (@code{,help}) for more information. + +@menu +* Help Commands:: +* Module Commands:: +* Language Commands:: +* Compile Commands:: +* Profile Commands:: +* Debug Commands:: +* Inspect Commands:: +* System Commands:: +@end menu + +@node Help Commands +@subsubsection Help Commands + +When Guile starts interactively, it notifies the user that help can be +had by typing @samp{,help}. Indeed, @code{help} is a command, and a +particularly useful one, as it allows the user to discover the rest of +the commands. + +@deffn {REPL Command} help [@code{all} | group | @code{[-c]} command] +Show help. + +With one argument, tries to look up the argument as a group name, giving +help on that group if successful. Otherwise tries to look up the +argument as a command, giving help on the command. + +If there is a command whose name is also a group name, use the @samp{-c +@var{command}} form to give help on the command instead of the group. + +Without any argument, a list of help commands and command groups +are displayed. +@end deffn + +@deffn {REPL Command} show [topic] +Gives information about Guile. + +With one argument, tries to show a particular piece of information; +currently supported topics are `warranty' (or `w'), `copying' (or `c'), +and `version' (or `v'). + +Without any argument, a list of topics is displayed. +@end deffn + +@deffn {REPL Command} apropos regexp +Find bindings/modules/packages. +@end deffn + +@deffn {REPL Command} describe obj +Show description/documentation. +@end deffn + +@node Module Commands +@subsubsection Module Commands + +@deffn {REPL Command} module [module] +Change modules / Show current module. +@end deffn + +@deffn {REPL Command} import module @dots{} +Import modules / List those imported. +@end deffn + +@deffn {REPL Command} load file +Load a file in the current module. +@end deffn + +@deffn {REPL Command} reload [module] +Reload the given module, or the current module if none was given. +@end deffn + +@deffn {REPL Command} binding +List current bindings. +@end deffn + +@deffn {REPL Command} in module expression +@deffnx {REPL Command} in module command arg @dots{} +Evaluate an expression, or alternatively, execute another meta-command +in the context of a module. For example, @samp{,in (foo bar) ,binding} +will show the bindings in the module @code{(foo bar)}. +@end deffn + +@node Language Commands +@subsubsection Language Commands + +@deffn {REPL Command} language language +Change languages. +@end deffn + +@node Compile Commands +@subsubsection Compile Commands + +@deffn {REPL Command} compile exp +Generate compiled code. +@end deffn + +@deffn {REPL Command} compile-file file +Compile a file. +@end deffn + +@deffn {REPL Command} expand exp +Expand any macros in a form. +@end deffn + +@deffn {REPL Command} optimize exp +Run the optimizer on a piece of code and print the result. +@end deffn + +@deffn {REPL Command} disassemble exp +Disassemble a compiled procedure. +@end deffn + +@deffn {REPL Command} disassemble-file file +Disassemble a file. +@end deffn + +@node Profile Commands +@subsubsection Profile Commands + +@deffn {REPL Command} time exp +Time execution. +@end deffn + +@deffn {REPL Command} profile exp [#:hz hz=100] @ + [#:count-calls? count-calls?=#f] [#:display-style display-style=list] +Profile execution of an expression. This command compiled @var{exp} and +then runs it within the statprof profiler, passing all keyword options +to the @code{statprof} procedure. For more on statprof and on the the +options available to this command, @xref{Statprof}. +@end deffn + +@deffn {REPL Command} trace exp [#:width w] [#:max-indent i] +Trace execution. + +By default, the trace will limit its width to the width of your +terminal, or @var{width} if specified. Nested procedure invocations +will be printed farther to the right, though if the width of the +indentation passes the @var{max-indent}, the indentation is abbreviated. +@end deffn + +@node Debug Commands +@subsubsection Debug Commands + +These debugging commands are only available within a recursive REPL; +they do not work at the top level. + +@deffn {REPL Command} backtrace [count] [#:width w] [#:full? f] +Print a backtrace. + +Print a backtrace of all stack frames, or innermost @var{count} frames. +If @var{count} is negative, the last @var{count} frames will be shown. +@end deffn + +@deffn {REPL Command} up [count] +Select a calling stack frame. + +Select and print stack frames that called this one. +An argument says how many frames up to go. +@end deffn + +@deffn {REPL Command} down [count] +Select a called stack frame. + +Select and print stack frames called by this one. +An argument says how many frames down to go. +@end deffn + +@deffn {REPL Command} frame [idx] +Show a frame. + +Show the selected frame. With an argument, select a frame by index, +then show it. +@end deffn + +@deffn {REPL Command} locals +Show local variables. + +Show locally-bound variables in the selected frame. +@end deffn + +@deffn {REPL Command} error-message +@deffnx {REPL Command} error +Show error message. + +Display the message associated with the error that started the current +debugging REPL. +@end deffn + +@deffn {REPL Command} registers +Show the VM registers associated with the current frame. + +@xref{Stack Layout}, for more information on VM stack frames. +@end deffn + +@deffn {REPL Command} width [cols] +Sets the number of display columns in the output of @code{,backtrace} +and @code{,locals} to @var{cols}. If @var{cols} is not given, the width +of the terminal is used. +@end deffn + +The next 3 commands work at any REPL. + +@deffn {REPL Command} break proc +Set a breakpoint at @var{proc}. +@end deffn + +@deffn {REPL Command} break-at-source file line +Set a breakpoint at the given source location. +@end deffn + +@deffn {REPL Command} tracepoint proc +Set a tracepoint on the given procedure. This will cause all calls to +the procedure to print out a tracing message. @xref{Tracing Traps}, for +more information. +@end deffn + +The rest of the commands in this subsection all apply only when the +stack is @dfn{continuable} --- in other words when it makes sense for +the program that the stack comes from to continue running. Usually this +means that the program stopped because of a trap or a breakpoint. + +@deffn {REPL Command} step +Tell the debugged program to step to the next source location. +@end deffn + +@deffn {REPL Command} next +Tell the debugged program to step to the next source location in the +same frame. (See @ref{Traps} for the details of how this works.) +@end deffn + +@deffn {REPL Command} finish +Tell the program being debugged to continue running until the completion +of the current stack frame, and at that time to print the result and +reenter the REPL. +@end deffn + + +@node Inspect Commands +@subsubsection Inspect Commands + +@deffn {REPL Command} inspect exp +Inspect the result(s) of evaluating @var{exp}. +@end deffn + +@deffn {REPL Command} pretty-print exp +Pretty-print the result(s) of evaluating @var{exp}. +@end deffn + +@node System Commands +@subsubsection System Commands + +@deffn {REPL Command} gc +Garbage collection. +@end deffn + +@deffn {REPL Command} statistics +Display statistics. +@end deffn + +@deffn {REPL Command} option [name] [exp] +With no arguments, lists all options. With one argument, shows the +current value of the @var{name} option. With two arguments, sets the +@var{name} option to the result of evaluating the Scheme expression +@var{exp}. +@end deffn + +@deffn {REPL Command} quit +Quit this session. +@end deffn + +Current REPL options include: + +@table @code +@item compile-options +The options used when compiling expressions entered at the REPL. +@xref{Compilation}, for more on compilation options. +@item interp +Whether to interpret or compile expressions given at the REPL, if such a +choice is available. Off by default (indicating compilation). +@item prompt +A customized REPL prompt. @code{#f} by default, indicating the default +prompt. +@item print +A procedure of two arguments used to print the result of evaluating each +expression. The arguments are the current REPL and the value to print. +By default, @code{#f}, to use the default procedure. +@item value-history +Whether value history is on or not. @xref{Value History}. +@item on-error +What to do when an error happens. By default, @code{debug}, meaning to +enter the debugger. Other values include @code{backtrace}, to show a +backtrace without entering the debugger, or @code{report}, to simply +show a short error printout. +@end table + +Default values for REPL options may be set using +@code{repl-default-option-set!} from @code{(system repl common)}: + +@deffn {Scheme Procedure} repl-default-option-set! key value +Set the default value of a REPL option. This function is particularly +useful in a user's init file. @xref{Init File}. +@end deffn + + +@node Error Handling +@subsection Error Handling + +When code being evaluated from the REPL hits an error, Guile enters a +new prompt, allowing you to inspect the context of the error. + +@lisp +scheme@@(guile-user)> (map string-append '("a" "b") '("c" #\d)) +ERROR: In procedure string-append: +ERROR: Wrong type (expecting string): #\d +Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. +scheme@@(guile-user) [1]> +@end lisp + +The new prompt runs inside the old one, in the dynamic context of the +error. It is a recursive REPL, augmented with a reified representation +of the stack, ready for debugging. + +@code{,backtrace} (abbreviated @code{,bt}) displays the Scheme call +stack at the point where the error occurred: + +@lisp +scheme@@(guile-user) [1]> ,bt + 1 (map #<procedure string-append _> ("a" "b") ("c" #\d)) + 0 (string-append "b" #\d) +@end lisp + +In the above example, the backtrace doesn't have much source +information, as @code{map} and @code{string-append} are both +primitives. But in the general case, the space on the left of the +backtrace indicates the line and column in which a given procedure calls +another. + +You can exit a recursive REPL in the same way that you exit any REPL: +via @samp{(quit)}, @samp{,quit} (abbreviated @samp{,q}), or +@kbd{C-d}, among other options. + + +@node Interactive Debugging +@subsection Interactive Debugging + +A recursive debugging REPL exposes a number of other meta-commands that +inspect the state of the computation at the time of the error. These +commands allow you to + +@itemize @bullet +@item +display the Scheme call stack at the point where the error occurred; + +@item +move up and down the call stack, to see in detail the expression being +evaluated, or the procedure being applied, in each @dfn{frame}; and + +@item +examine the values of variables and expressions in the context of each +frame. +@end itemize + +@noindent +@xref{Debug Commands}, for documentation of the individual +commands. This section aims to give more of a walkthrough of a typical +debugging session. + +First, we're going to need a good error. Let's try to macroexpand the +expression @code{(unquote foo)}, outside of a @code{quasiquote} form, +and see how the macroexpander reports this error. + +@lisp +scheme@@(guile-user)> (macroexpand '(unquote foo)) +ERROR: In procedure macroexpand: +ERROR: unquote: expression not valid outside of quasiquote in (unquote foo) +Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. +scheme@@(guile-user) [1]> +@end lisp + +The @code{backtrace} command, which can also be invoked as @code{bt}, +displays the call stack (aka backtrace) at the point where the debugger +was entered: + +@lisp +scheme@@(guile-user) [1]> ,bt +In ice-9/psyntax.scm: + 1130:21 3 (chi-top (unquote foo) () ((top)) e (eval) (hygiene #)) + 1071:30 2 (syntax-type (unquote foo) () ((top)) #f #f (# #) #f) + 1368:28 1 (chi-macro #<procedure de9360 at ice-9/psyntax.scm...> ...) +In unknown file: + 0 (scm-error syntax-error macroexpand "~a: ~a in ~a" # #f) +@end lisp + +A call stack consists of a sequence of stack @dfn{frames}, with each +frame describing one procedure which is waiting to do something with the +values returned by another. Here we see that there are four frames on +the stack. + +Note that @code{macroexpand} is not on the stack -- it must have made a +tail call to @code{chi-top}, as indeed we would find if we searched +@code{ice-9/psyntax.scm} for its definition. + +When you enter the debugger, the innermost frame is selected, which +means that the commands for getting information about the ``current'' +frame, or for evaluating expressions in the context of the current +frame, will do so by default with respect to the innermost frame. To +select a different frame, so that these operations will apply to it +instead, use the @code{up}, @code{down} and @code{frame} commands like +this: + +@lisp +scheme@@(guile-user) [1]> ,up +In ice-9/psyntax.scm: + 1368:28 1 (chi-macro #<procedure de9360 at ice-9/psyntax.scm...> ...) +scheme@@(guile-user) [1]> ,frame 3 +In ice-9/psyntax.scm: + 1130:21 3 (chi-top (unquote foo) () ((top)) e (eval) (hygiene #)) +scheme@@(guile-user) [1]> ,down +In ice-9/psyntax.scm: + 1071:30 2 (syntax-type (unquote foo) () ((top)) #f #f (# #) #f) +@end lisp + +Perhaps we're interested in what's going on in frame 2, so we take a +look at its local variables: + +@lisp +scheme@@(guile-user) [1]> ,locals + Local variables: + $1 = e = (unquote foo) + $2 = r = () + $3 = w = ((top)) + $4 = s = #f + $5 = rib = #f + $6 = mod = (hygiene guile-user) + $7 = for-car? = #f + $8 = first = unquote + $9 = ftype = macro + $10 = fval = #<procedure de9360 at ice-9/psyntax.scm:2817:2 (x)> + $11 = fe = unquote + $12 = fw = ((top)) + $13 = fs = #f + $14 = fmod = (hygiene guile-user) +@end lisp + +All of the values are accessible by their value-history names +(@code{$@var{n}}): + +@lisp +scheme@@(guile-user) [1]> $10 +$15 = #<procedure de9360 at ice-9/psyntax.scm:2817:2 (x)> +@end lisp + +We can even invoke the procedure at the REPL directly: + +@lisp +scheme@@(guile-user) [1]> ($10 'not-going-to-work) +ERROR: In procedure macroexpand: +ERROR: source expression failed to match any pattern in not-going-to-work +Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. +@end lisp + +Well at this point we've caused an error within an error. Let's just +quit back to the top level: + +@lisp +scheme@@(guile-user) [2]> ,q +scheme@@(guile-user) [1]> ,q +scheme@@(guile-user)> +@end lisp + +Finally, as a word to the wise: hackers close their REPL prompts with +@kbd{C-d}. + + +@node Using Guile in Emacs +@section Using Guile in Emacs + +@cindex Emacs +Any text editor can edit Scheme, but some are better than others. Emacs +is the best, of course, and not just because it is a fine text editor. +Emacs has good support for Scheme out of the box, with sensible +indentation rules, parenthesis-matching, syntax highlighting, and even a +set of keybindings for structural editing, allowing navigation, +cut-and-paste, and transposition operations that work on balanced +S-expressions. + +As good as it is, though, two things will vastly improve your experience +with Emacs and Guile. + +@cindex Paredit +The first is Taylor Campbell's +@uref{http://www.emacswiki.org/emacs/ParEdit, Paredit}. You should not +code in any dialect of Lisp without Paredit. (They say that +unopinionated writing is boring---hence this tone---but it's the +truth, regardless.) Paredit is the bee's knees. + +@cindex Geiser +The second is +@iftex +Jos@'e +@end iftex +@ifnottex +José +@end ifnottex +Antonio Ortega Ruiz's +@uref{http://www.nongnu.org/geiser/, Geiser}. Geiser complements Emacs' +@code{scheme-mode} with tight integration to running Guile processes via +a @code{comint-mode} REPL buffer. + +Of course there are keybindings to switch to the REPL, and a good REPL +environment, but Geiser goes beyond that, providing: + +@itemize @bullet +@item +Form evaluation in the context of the current file's module. +@item +Macro expansion. +@item +File/module loading and/or compilation. +@item +Namespace-aware identifier completion (including local bindings, names +visible in the current module, and module names). +@item +Autodoc: the echo area shows information about the signature of the +procedure/macro around point automatically. +@item +Jump to definition of identifier at point. +@item +Access to documentation (including docstrings when the implementation +provides it). +@item +Listings of identifiers exported by a given module. +@item +Listings of callers/callees of procedures. +@item +Rudimentary support for debugging and error navigation. +@item +Support for multiple, simultaneous REPLs. +@end itemize + +See Geiser's web page at @uref{http://www.nongnu.org/geiser/}, for more +information. + + +@node Using Guile Tools +@section Using Guile Tools + +@cindex guild +@cindex guile-tools +@cindex wizards +Guile also comes with a growing number of command-line utilities: a +compiler, a disassembler, some module inspectors, and in the future, a +system to install Guile packages from the internet. These tools may be +invoked using the @code{guild} program. + +@example +$ guild compile -o foo.go foo.scm +wrote `foo.go' +@end example + +This program used to be called @code{guile-tools} up to +Guile version 2.0.1, and for backward +compatibility it still may be called as such. However we changed the +name to @code{guild}, not only because it is pleasantly shorter and +easier to read, but also because this tool will serve to bind Guile +wizards together, by allowing hackers to share code with each other +using a CPAN-like system. + +@xref{Compilation}, for more on @code{guild compile}. + +A complete list of guild scripts can be had by invoking @code{guild +list}, or simply @code{guild}. + + +@node Installing Site Packages +@section Installing Site Packages + +@cindex site +@cindex site path +@cindex load path +@findex %site-dir +@findex %site-ccache-dir + +At some point, you will probably want to share your code with other +people. To do so effectively, it is important to follow a set of common +conventions, to make it easy for the user to install and use your +package. + +The first thing to do is to install your Scheme files where Guile can +find them. When Guile goes to find a Scheme file, it will search a +@dfn{load path} to find the file: first in Guile's own path, then in +paths for @dfn{site packages}. A site package is any Scheme code that +is installed and not part of Guile itself. @xref{Load Paths}, for more +on load paths. + +There are several site paths, for historical reasons, but the one that +should generally be used can be obtained by invoking the +@code{%site-dir} procedure. @xref{Build Config}. If Guile +@value{EFFECTIVE-VERSION} is installed on your system in @code{/usr/}, +then @code{(%site-dir)} will be +@code{/usr/share/guile/site/@value{EFFECTIVE-VERSION}}. Scheme files +should be installed there. + +If you do not install compiled @code{.go} files, Guile will compile your +modules and programs when they are first used, and cache them in the +user's home directory. @xref{Compilation}, for more on +auto-compilation. However, it is better to compile the files before +they are installed, and to just copy the files to a place that Guile can +find them. + +As with Scheme files, Guile searches a path to find compiled @code{.go} +files, the @code{%load-compiled-path}. By default, this path has two +entries: a path for Guile's files, and a path for site packages. You +should install your @code{.go} files into the latter directory, whose +value is returned by invoking the @code{%site-ccache-dir} procedure. As +in the previous example, if Guile @value{EFFECTIVE-VERSION} is installed +on your system in @code{/usr/}, then @code{(%site-ccache-dir)} site +packages will be +@code{/usr/lib/guile/@value{EFFECTIVE-VERSION}/site-ccache}. + +Note that a @code{.go} file will only be loaded in preference to a +@code{.scm} file if it is newer. For that reason, you should install +your Scheme files first, and your compiled files second. @xref{Load +Paths}, for more on the loading process. + +Finally, although this section is only about Scheme, sometimes you need +to install C extensions too. Shared libraries should be installed in +the @dfn{extensions dir}. This value can be had from the build config +(@pxref{Build Config}). Again, if Guile @value{EFFECTIVE-VERSION} is +installed on your system in @code{/usr/}, then the extensions dir will +be @code{/usr/lib/guile/@value{EFFECTIVE-VERSION}/extensions}. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/scheme.dia b/doc/ref/scheme.dia Binary files differnew file mode 100644 index 000000000..30f9cc2bf --- /dev/null +++ b/doc/ref/scheme.dia diff --git a/doc/ref/scheme.eps b/doc/ref/scheme.eps new file mode 100644 index 000000000..9481b9c53 --- /dev/null +++ b/doc/ref/scheme.eps @@ -0,0 +1,457 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: /home/bjg/guile/doc/ref/scheme.dia +%%Creator: Dia v0.95-1 +%%CreationDate: Tue Dec 8 14:22:51 2009 +%%For: bjg +%%Orientation: Portrait +%%Magnification: 1.0000 +%%BoundingBox: 0 0 576 445 +%%BeginSetup +%%EndSetup +%%EndComments +%%BeginProlog +[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright +/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E +/F /G /H /I /J /K /L /M /N /O +/P /Q /R /S /T /U /V /W /X /Y +/Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c +/d /e /f /g /h /i /j /k /l /m +/n /o /p /q /r /s /t /u /v /w +/x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright +/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior +/acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf +/threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla +/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde +/Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex +/Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring +/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis +/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave +/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def +/cp {closepath} bind def +/c {curveto} bind def +/f {fill} bind def +/a {arc} bind def +/ef {eofill} bind def +/ex {exch} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth pop} bind def +/tr {translate} bind def + +/ellipsedict 8 dict def +ellipsedict /mtrx matrix put +/ellipse +{ ellipsedict begin + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def /savematrix mtrx currentmatrix def + x y tr xrad yrad sc + 0 0 1 startangle endangle arc + savematrix setmatrix + end +} def + +/mergeprocs { +dup length +3 -1 roll +dup +length +dup +5 1 roll +3 -1 roll +add +array cvx +dup +3 -1 roll +0 exch +putinterval +dup +4 2 roll +putinterval +} bind def +/Times-Roman-latin1 + /Times-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-Italic-latin1 + /Times-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-Bold-latin1 + /Times-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Times-BoldItalic-latin1 + /Times-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-Book-latin1 + /AvantGarde-Book findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-BookOblique-latin1 + /AvantGarde-BookOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-Demi-latin1 + /AvantGarde-Demi findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/AvantGarde-DemiOblique-latin1 + /AvantGarde-DemiOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-Light-latin1 + /Bookman-Light findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-LightItalic-latin1 + /Bookman-LightItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-Demi-latin1 + /Bookman-Demi findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Bookman-DemiItalic-latin1 + /Bookman-DemiItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-latin1 + /Courier findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-Oblique-latin1 + /Courier-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-Bold-latin1 + /Courier-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Courier-BoldOblique-latin1 + /Courier-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-latin1 + /Helvetica findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Oblique-latin1 + /Helvetica-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Bold-latin1 + /Helvetica-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-BoldOblique-latin1 + /Helvetica-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-latin1 + /Helvetica-Narrow findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-Oblique-latin1 + /Helvetica-Narrow-Oblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-Bold-latin1 + /Helvetica-Narrow-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Helvetica-Narrow-BoldOblique-latin1 + /Helvetica-Narrow-BoldOblique findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Roman-latin1 + /NewCenturySchoolbook-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Italic-latin1 + /NewCenturySchoolbook-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-Bold-latin1 + /NewCenturySchoolbook-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/NewCenturySchoolbook-BoldItalic-latin1 + /NewCenturySchoolbook-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Roman-latin1 + /Palatino-Roman findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Italic-latin1 + /Palatino-Italic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-Bold-latin1 + /Palatino-Bold findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Palatino-BoldItalic-latin1 + /Palatino-BoldItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/Symbol-latin1 + /Symbol findfont +definefont pop +/ZapfChancery-MediumItalic-latin1 + /ZapfChancery-MediumItalic findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +/ZapfDingbats-latin1 + /ZapfDingbats findfont + dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding isolatin1encoding def + currentdict end +definefont pop +28.346000 -28.346000 scale +-17.174517 -10.811080 translate +%%EndProlog + + +0.010000 slw +[] 0 sd +[] 0 sd +0 slj +1.000000 1.000000 1.000000 srgb +n 17.174517 -4.886690 m 37.468481 -4.886690 l s +n 17.174517 10.811080 m 37.468481 10.811080 l s +n 17.174517 -4.886690 0.000000 0.000000 180.000000 270.000000 ellipse s +n 37.468481 -4.886690 0.000000 0.000000 270.000000 360.000000 ellipse s +n 17.174517 -4.886690 m 17.174517 10.811080 l s +n 37.468481 -4.886690 m 37.468481 10.811080 l s +n 17.174517 10.811080 0.000000 0.000000 90.000000 180.000000 ellipse s +n 37.468481 10.811080 0.000000 0.000000 0.000000 90.000000 ellipse s +0.100000 slw +[] 0 sd +n 20.050000 7.950000 m 20.050000 9.350000 l 23.050000 9.350000 l 23.050000 7.950000 l f +0.000000 0.000000 0.000000 srgb +n 20.050000 7.950000 m 20.050000 9.350000 l 23.050000 9.350000 l 23.050000 7.950000 l cp s +/Helvetica-Bold-latin1 ff 0.700000 scf sf +(Quack) dup sw 2 div 21.550000 ex sub 8.950000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +1.000000 1.000000 1.000000 srgb +n 25.900000 7.950000 m 25.900000 9.350000 l 28.050000 9.350000 l 28.050000 7.950000 l f +0.000000 0.000000 0.000000 srgb +n 25.900000 7.950000 m 25.900000 9.350000 l 28.050000 9.350000 l 28.050000 7.950000 l cp s +/Helvetica-Bold-latin1 ff 0.700000 scf sf +(GDS) dup sw 2 div 26.975000 ex sub 8.950000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +1.000000 1.000000 1.000000 srgb +n 21.450000 2.200000 m 21.450000 3.600000 l 26.800000 3.600000 l 26.800000 2.200000 l f +0.000000 0.000000 0.000000 srgb +n 21.450000 2.200000 m 21.450000 3.600000 l 26.800000 3.600000 l 26.800000 2.200000 l cp s +/Helvetica-Bold-latin1 ff 0.700000 scf sf +(cmuscheme) dup sw 2 div 24.125000 ex sub 3.200000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +0 slj +0 slc +n 24.357500 4.511803 m 24.357500 5.775000 l 27.098800 5.775000 l 27.098800 7.950000 l s +0 slj +1.000000 1.000000 1.000000 srgb +n 24.757500 4.511803 m 24.357500 3.711803 l 23.957500 4.511803 l ef +0.100000 slw +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 24.757500 4.511803 m 24.357500 3.711803 l 23.957500 4.511803 l cp s +/Courier-latin1 ff 0.560000 scf sf +0.100000 slw +[] 0 sd +0 slj +0 slc +n 24.357500 4.511803 m 24.357500 5.775000 l 21.698800 5.775000 l 21.698800 7.950000 l s +0 slj +1.000000 1.000000 1.000000 srgb +n 24.757500 4.511803 m 24.357500 3.711803 l 23.957500 4.511803 l ef +0.100000 slw +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 24.757500 4.511803 m 24.357500 3.711803 l 23.957500 4.511803 l cp s +/Courier-latin1 ff 0.560000 scf sf +0.100000 slw +[] 0 sd +1.000000 1.000000 1.000000 srgb +n 30.300000 2.200000 m 30.300000 3.600000 l 34.400000 3.600000 l 34.400000 2.200000 l f +0.000000 0.000000 0.000000 srgb +n 30.300000 2.200000 m 30.300000 3.600000 l 34.400000 3.600000 l 34.400000 2.200000 l cp s +/Helvetica-Bold-latin1 ff 0.700000 scf sf +(xscheme) dup sw 2 div 32.350000 ex sub 3.200000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +1.000000 1.000000 1.000000 srgb +n 27.400000 -3.500000 m 27.400000 -2.100000 l 31.050000 -2.100000 l 31.050000 -3.500000 l f +0.000000 0.000000 0.000000 srgb +n 27.400000 -3.500000 m 27.400000 -2.100000 l 31.050000 -2.100000 l 31.050000 -3.500000 l cp s +/Helvetica-Bold-latin1 ff 0.700000 scf sf +(scheme) dup sw 2 div 29.225000 ex sub -2.500000 m gs 1 -1 sc sh gr +0.100000 slw +[] 0 sd +0 slj +0 slc +n 29.368800 -1.188197 m 29.368800 0.050000 l 32.526300 0.050000 l 32.526300 2.200000 l s +0 slj +1.000000 1.000000 1.000000 srgb +n 29.768800 -1.188197 m 29.368800 -1.988197 l 28.968800 -1.188197 l ef +0.100000 slw +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 29.768800 -1.188197 m 29.368800 -1.988197 l 28.968800 -1.188197 l cp s +/Courier-latin1 ff 0.560000 scf sf +0.100000 slw +[] 0 sd +0 slj +0 slc +n 29.368800 -1.188197 m 29.368800 0.050000 l 24.357500 0.050000 l 24.357500 2.200000 l s +0 slj +1.000000 1.000000 1.000000 srgb +n 29.768800 -1.188197 m 29.368800 -1.988197 l 28.968800 -1.188197 l ef +0.100000 slw +[] 0 sd +0 slj +0.000000 0.000000 0.000000 srgb +n 29.768800 -1.188197 m 29.368800 -1.988197 l 28.968800 -1.188197 l cp s +/Courier-latin1 ff 0.560000 scf sf +/Helvetica-latin1 ff 0.560000 scf sf +showpage diff --git a/doc/ref/scheme.pdf b/doc/ref/scheme.pdf Binary files differnew file mode 100644 index 000000000..fff74f432 --- /dev/null +++ b/doc/ref/scheme.pdf diff --git a/doc/ref/scheme.txt b/doc/ref/scheme.txt new file mode 100644 index 000000000..64ae05204 --- /dev/null +++ b/doc/ref/scheme.txt @@ -0,0 +1,11 @@ + scheme + ^ + | + .-----+-----. + | | + cmuscheme xscheme + ^ + | + .-----+-----. + | | + Quack GDS diff --git a/doc/ref/scsh.texi b/doc/ref/scsh.texi new file mode 100644 index 000000000..b4ddcba3c --- /dev/null +++ b/doc/ref/scsh.texi @@ -0,0 +1,24 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node The Scheme shell (scsh) +@section The Scheme shell (scsh) +@cindex SCSH +@cindex Scheme Shell + +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 +@url{http://cvs.savannah.gnu.org/viewvc/guile/guile-scsh/?root=guile}. + +For information about scsh see +@url{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. diff --git a/doc/ref/slib.texi b/doc/ref/slib.texi new file mode 100644 index 000000000..388dae1f6 --- /dev/null +++ b/doc/ref/slib.texi @@ -0,0 +1,128 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node SLIB +@section SLIB +@cindex SLIB + +SLIB is a portable library of Scheme packages which can be used with +Guile and other Scheme implementations. SLIB is not included in the +Guile distribution, but can be installed separately (@pxref{SLIB +installation}). It is available from +@url{http://people.csail.mit.edu/jaffer/SLIB.html}. + +After SLIB is installed, the following Scheme expression must be +executed before the SLIB facilities can be used: + +@lisp +(use-modules (ice-9 slib)) +@end lisp + +@findex require +@noindent +@code{require} can then be used in the usual way (@pxref{Require,,, +slib, The SLIB Manual}). For example, + +@example +(use-modules (ice-9 slib)) +(require 'primes) +(prime? 13) +@result{} #t +@end example + +A few Guile core functions are overridden by the SLIB setups; for +example the SLIB version of @code{delete-file} returns a boolean +indicating success or failure, whereas the Guile core version throws +an error for failure. In general (and as might be expected) when SLIB +is loaded it's the SLIB specifications that are followed. + +@menu +* SLIB installation:: +* JACAL:: +@end menu + +@node SLIB installation +@subsection SLIB installation + +The following procedure works, e.g., with SLIB version 3a3 +(@pxref{Installation, SLIB installation,, slib, The SLIB Portable Scheme +Library}): + +@enumerate +@item +Unpack SLIB and install it using @code{make install} from its directory. +By default, this will install SLIB in @file{/usr/local/lib/slib/}. +Running @code{make install-info} installs its documentation, by default +under @file{/usr/local/info/}. + +@item +Define the @code{SCHEME_LIBRARY_PATH} environment variable: + +@example +$ SCHEME_LIBRARY_PATH=/usr/local/lib/slib/ +$ export SCHEME_LIBRARY_PATH +@end example + +Alternatively, you can create a symlink in the Guile directory to SLIB, +e.g.: + +@example +ln -s /usr/local/lib/slib /usr/local/share/guile/@value{EFFECTIVE-VERSION}/slib +@end example + +@item +Use Guile to create the catalog file, e.g.,: + +@example +# guile +guile> (use-modules (ice-9 slib)) +guile> (require 'new-catalog) +guile> (quit) +@end example + +The catalog data should now be in +@file{/usr/local/share/guile/@value{EFFECTIVE-VERSION}/slibcat}. + +If instead you get an error such as: + +@example +Unbound variable: scheme-implementation-type +@end example + +then a solution is to get a newer version of Guile, +or to modify @file{ice-9/slib.scm} to use @code{define-public} for the +offending variables. + +@end enumerate + +@node JACAL +@subsection JACAL +@cindex JACAL + +@cindex Jaffer, Aubrey +@cindex symbolic math +@cindex math -- symbolic +Jacal is a symbolic math package written in Scheme by Aubrey Jaffer. +It is usually installed as an extra package in SLIB. + +You can use Guile's interface to SLIB to invoke Jacal: + +@lisp +(use-modules (ice-9 slib)) +(slib:load "math") +(math) +@end lisp + +@noindent +For complete documentation on Jacal, please read the Jacal manual. If +it has been installed on line, you can look at @ref{Top, , Jacal, jacal, +JACAL Symbolic Mathematics System}. Otherwise you can find it on the web at +@url{http://www-swiss.ai.mit.edu/~jaffer/JACAL.html} + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi new file mode 100644 index 000000000..f3caa4375 --- /dev/null +++ b/doc/ref/srfi-modules.texi @@ -0,0 +1,5579 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000-2004, 2006, 2007-2014, 2017, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node SRFI Support +@section SRFI Support Modules +@cindex SRFI + +SRFI is an acronym for Scheme Request For Implementation. The SRFI +documents define a lot of syntactic and procedure extensions to standard +Scheme as defined in R5RS. + +Guile has support for a number of SRFIs. This chapter gives an overview +over the available SRFIs and some usage hints. For complete +documentation, design rationales and further examples, we advise you to +get the relevant SRFI documents from the SRFI home page +@url{http://srfi.schemers.org/}. + +@menu +* About SRFI Usage:: What to know about Guile's SRFI support. +* SRFI-0:: cond-expand +* SRFI-1:: List library. +* SRFI-2:: and-let*. +* SRFI-4:: Homogeneous numeric vector datatypes. +* SRFI-6:: Basic String Ports. +* SRFI-8:: receive. +* SRFI-9:: define-record-type. +* SRFI-10:: Hash-Comma Reader Extension. +* SRFI-11:: let-values and let*-values. +* SRFI-13:: String library. +* SRFI-14:: Character-set library. +* SRFI-16:: case-lambda +* SRFI-17:: Generalized set! +* SRFI-18:: Multithreading support +* SRFI-19:: Time/Date library. +* SRFI-23:: Error reporting +* SRFI-26:: Specializing parameters +* SRFI-27:: Sources of Random Bits +* SRFI-28:: Basic format strings. +* SRFI-30:: Nested multi-line block comments +* SRFI-31:: A special form `rec' for recursive evaluation +* SRFI-34:: Exception handling. +* SRFI-35:: Conditions. +* SRFI-37:: args-fold program argument processor +* SRFI-38:: External Representation for Data With Shared Structure +* SRFI-39:: Parameter objects +* SRFI-41:: Streams. +* SRFI-42:: Eager comprehensions +* SRFI-43:: Vector Library. +* SRFI-45:: Primitives for expressing iterative lazy algorithms +* SRFI-46:: Basic syntax-rules Extensions. +* SRFI-55:: Requiring Features. +* SRFI-60:: Integers as bits. +* SRFI-61:: A more general `cond' clause +* SRFI-62:: S-expression comments. +* SRFI-64:: A Scheme API for test suites. +* SRFI-67:: Compare procedures +* SRFI-69:: Basic hash tables. +* SRFI-71:: Extended let-syntax for multiple values. +* SRFI-87:: => in case clauses. +* SRFI-88:: Keyword objects. +* SRFI-98:: Accessing environment variables. +* SRFI-105:: Curly-infix expressions. +* SRFI-111:: Boxes. +@end menu + + +@node About SRFI Usage +@subsection About SRFI Usage + +@c FIXME::martin: Review me! + +SRFI support in Guile is currently implemented partly in the core +library, and partly as add-on modules. That means that some SRFIs are +automatically available when the interpreter is started, whereas the +other SRFIs require you to use the appropriate support module +explicitly. + +There are several reasons for this inconsistency. First, the feature +checking syntactic form @code{cond-expand} (@pxref{SRFI-0}) must be +available immediately, because it must be there when the user wants to +check for the Scheme implementation, that is, before she can know that +it is safe to use @code{use-modules} to load SRFI support modules. The +second reason is that some features defined in SRFIs had been +implemented in Guile before the developers started to add SRFI +implementations as modules (for example SRFI-13 (@pxref{SRFI-13})). In +the future, it is possible that SRFIs in the core library might be +factored out into separate modules, requiring explicit module loading +when they are needed. So you should be prepared to have to use +@code{use-modules} someday in the future to access SRFI-13 bindings. If +you want, you can do that already. We have included the module +@code{(srfi srfi-13)} in the distribution, which currently does nothing, +but ensures that you can write future-safe code. + +Generally, support for a specific SRFI is made available by using +modules named @code{(srfi srfi-@var{number})}, where @var{number} is the +number of the SRFI needed. Another possibility is to use the command +line option @code{--use-srfi}, which will load the necessary modules +automatically (@pxref{Invoking Guile}). + + +@node SRFI-0 +@subsection SRFI-0 - cond-expand +@cindex SRFI-0 + +This SRFI lets a portable Scheme program test for the presence of +certain features, and adapt itself by using different blocks of code, +or fail if the necessary features are not available. There's no +module to load, this is in the Guile core. + +A program designed only for Guile will generally not need this +mechanism, such a program can of course directly use the various +documented parts of Guile. + +@deffn syntax cond-expand (feature body@dots{}) @dots{} +Expand to the @var{body} of the first clause whose @var{feature} +specification is satisfied. It is an error if no @var{feature} is +satisfied. + +Features are symbols such as @code{srfi-1}, and a feature +specification can use @code{and}, @code{or} and @code{not} forms to +test combinations. The last clause can be an @code{else}, to be used +if no other passes. + +For example, define a private version of @code{alist-cons} if SRFI-1 +is not available. + +@example +(cond-expand (srfi-1 + ) + (else + (define (alist-cons key val alist) + (cons (cons key val) alist)))) +@end example + +Or demand a certain set of SRFIs (list operations, string ports, +@code{receive} and string operations), failing if they're not +available. + +@example +(cond-expand ((and srfi-1 srfi-6 srfi-8 srfi-13) + )) +@end example +@end deffn + +@noindent +The Guile core has the following features, + +@example +guile +guile-2 ;; starting from Guile 2.x +guile-2.2 ;; starting from Guile 2.2 +guile-3.0 ;; starting from Guile 3.0 +r5rs +srfi-0 +srfi-4 +srfi-6 +srfi-13 +srfi-14 +srfi-16 +srfi-23 +srfi-30 +srfi-39 +srfi-46 +srfi-55 +srfi-61 +srfi-62 +srfi-87 +srfi-105 +@end example + +Other SRFI feature symbols are defined once their code has been loaded +with @code{use-modules}, since only then are their bindings available. + +The @samp{--use-srfi} command line option (@pxref{Invoking Guile}) is +a good way to load SRFIs to satisfy @code{cond-expand} when running a +portable program. + +Testing the @code{guile} feature allows a program to adapt itself to +the Guile module system, but still run on other Scheme systems. For +example the following demands SRFI-8 (@code{receive}), but also knows +how to load it with the Guile mechanism. + +@example +(cond-expand (srfi-8 + ) + (guile + (use-modules (srfi srfi-8)))) +@end example + +@cindex @code{guile-2} SRFI-0 feature +@cindex portability between 2.0 and older versions +Likewise, testing the @code{guile-2} feature allows code to be portable +between Guile 2.@var{x} and previous versions of Guile. For instance, it +makes it possible to write code that accounts for Guile 2.@var{x}'s compiler, +yet be correctly interpreted on 1.8 and earlier versions: + +@example +(cond-expand (guile-2 (eval-when (compile) + ;; This must be evaluated at compile time. + (fluid-set! current-reader my-reader))) + (guile + ;; Earlier versions of Guile do not have a + ;; separate compilation phase. + (fluid-set! current-reader my-reader))) +@end example + +It should be noted that @code{cond-expand} is separate from the +@code{*features*} mechanism (@pxref{Feature Tracking}), feature +symbols in one are unrelated to those in the other. + + +@node SRFI-1 +@subsection SRFI-1 - List library +@cindex SRFI-1 +@cindex list + +@c FIXME::martin: Review me! + +The list library defined in SRFI-1 contains a lot of useful list +processing procedures for construction, examining, destructuring and +manipulating lists and pairs. + +Since SRFI-1 also defines some procedures which are already contained +in R5RS and thus are supported by the Guile core library, some list +and pair procedures which appear in the SRFI-1 document may not appear +in this section. So when looking for a particular list/pair +processing procedure, you should also have a look at the sections +@ref{Lists} and @ref{Pairs}. + +@menu +* SRFI-1 Constructors:: Constructing new lists. +* SRFI-1 Predicates:: Testing list for specific properties. +* SRFI-1 Selectors:: Selecting elements from lists. +* SRFI-1 Length Append etc:: Length calculation and list appending. +* SRFI-1 Fold and Map:: Higher-order list processing. +* SRFI-1 Filtering and Partitioning:: Filter lists based on predicates. +* SRFI-1 Searching:: Search for elements. +* SRFI-1 Deleting:: Delete elements from lists. +* SRFI-1 Association Lists:: Handle association lists. +* SRFI-1 Set Operations:: Use lists for representing sets. +@end menu + +@node SRFI-1 Constructors +@subsubsection Constructors +@cindex list constructor + +@c FIXME::martin: Review me! + +New lists can be constructed by calling one of the following +procedures. + +@deffn {Scheme Procedure} xcons d a +Like @code{cons}, but with interchanged arguments. Useful mostly when +passed to higher-order procedures. +@end deffn + +@deffn {Scheme Procedure} list-tabulate n init-proc +Return an @var{n}-element list, where each list element is produced by +applying the procedure @var{init-proc} to the corresponding list +index. The order in which @var{init-proc} is applied to the indices +is not specified. +@end deffn + +@deffn {Scheme Procedure} list-copy lst +Return a new list containing the elements of the list @var{lst}. + +This function differs from the core @code{list-copy} (@pxref{List +Constructors}) in accepting improper lists too. And if @var{lst} is +not a pair at all then it's treated as the final tail of an improper +list and simply returned. +@end deffn + +@deffn {Scheme Procedure} circular-list elt1 elt2 @dots{} +Return a circular list containing the given arguments @var{elt1} +@var{elt2} @dots{}. +@end deffn + +@deffn {Scheme Procedure} iota count [start step] +Return a list containing @var{count} numbers, starting from +@var{start} and adding @var{step} each time. The default @var{start} +is 0, the default @var{step} is 1. For example, + +@example +(iota 6) @result{} (0 1 2 3 4 5) +(iota 4 2.5 -2) @result{} (2.5 0.5 -1.5 -3.5) +@end example + +This function takes its name from the corresponding primitive in the +APL language. +@end deffn + + +@node SRFI-1 Predicates +@subsubsection Predicates +@cindex list predicate + +@c FIXME::martin: Review me! + +The procedures in this section test specific properties of lists. + +@deffn {Scheme Procedure} proper-list? obj +Return @code{#t} if @var{obj} is a proper list, or @code{#f} +otherwise. This is the same as the core @code{list?} (@pxref{List +Predicates}). + +A proper list is a list which ends with the empty list @code{()} in +the usual way. The empty list @code{()} itself is a proper list too. + +@example +(proper-list? '(1 2 3)) @result{} #t +(proper-list? '()) @result{} #t +@end example +@end deffn + +@deffn {Scheme Procedure} circular-list? obj +Return @code{#t} if @var{obj} is a circular list, or @code{#f} +otherwise. + +A circular list is a list where at some point the @code{cdr} refers +back to a previous pair in the list (either the start or some later +point), so that following the @code{cdr}s takes you around in a +circle, with no end. + +@example +(define x (list 1 2 3 4)) +(set-cdr! (last-pair x) (cddr x)) +x @result{} (1 2 3 4 3 4 3 4 ...) +(circular-list? x) @result{} #t +@end example +@end deffn + +@deffn {Scheme Procedure} dotted-list? obj +Return @code{#t} if @var{obj} is a dotted list, or @code{#f} +otherwise. + +A dotted list is a list where the @code{cdr} of the last pair is not +the empty list @code{()}. Any non-pair @var{obj} is also considered a +dotted list, with length zero. + +@example +(dotted-list? '(1 2 . 3)) @result{} #t +(dotted-list? 99) @result{} #t +@end example +@end deffn + +It will be noted that any Scheme object passes exactly one of the +above three tests @code{proper-list?}, @code{circular-list?} and +@code{dotted-list?}. Non-lists are @code{dotted-list?}, finite lists +are either @code{proper-list?} or @code{dotted-list?}, and infinite +lists are @code{circular-list?}. + +@sp 1 +@deffn {Scheme Procedure} null-list? lst +Return @code{#t} if @var{lst} is the empty list @code{()}, @code{#f} +otherwise. If something else than a proper or circular list is passed +as @var{lst}, an error is signalled. This procedure is recommended +for checking for the end of a list in contexts where dotted lists are +not allowed. +@end deffn + +@deffn {Scheme Procedure} not-pair? obj +Return @code{#t} is @var{obj} is not a pair, @code{#f} otherwise. +This is shorthand notation @code{(not (pair? @var{obj}))} and is +supposed to be used for end-of-list checking in contexts where dotted +lists are allowed. +@end deffn + +@deffn {Scheme Procedure} list= elt= list1 @dots{} +Return @code{#t} if all argument lists are equal, @code{#f} otherwise. +List equality is determined by testing whether all lists have the same +length and the corresponding elements are equal in the sense of the +equality predicate @var{elt=}. If no or only one list is given, +@code{#t} is returned. +@end deffn + + +@node SRFI-1 Selectors +@subsubsection Selectors +@cindex list selector + +@c FIXME::martin: Review me! + +@deffn {Scheme Procedure} first pair +@deffnx {Scheme Procedure} second pair +@deffnx {Scheme Procedure} third pair +@deffnx {Scheme Procedure} fourth pair +@deffnx {Scheme Procedure} fifth pair +@deffnx {Scheme Procedure} sixth pair +@deffnx {Scheme Procedure} seventh pair +@deffnx {Scheme Procedure} eighth pair +@deffnx {Scheme Procedure} ninth pair +@deffnx {Scheme Procedure} tenth pair +These are synonyms for @code{car}, @code{cadr}, @code{caddr}, @dots{}. +@end deffn + +@deffn {Scheme Procedure} car+cdr pair +Return two values, the @sc{car} and the @sc{cdr} of @var{pair}. +@end deffn + +@deffn {Scheme Procedure} take lst i +@deffnx {Scheme Procedure} take! lst i +Return a list containing the first @var{i} elements of @var{lst}. + +@code{take!} may modify the structure of the argument list @var{lst} +in order to produce the result. +@end deffn + +@deffn {Scheme Procedure} drop lst i +Return a list containing all but the first @var{i} elements of +@var{lst}. +@end deffn + +@deffn {Scheme Procedure} take-right lst i +Return a list containing the @var{i} last elements of @var{lst}. +The return shares a common tail with @var{lst}. +@end deffn + +@deffn {Scheme Procedure} drop-right lst i +@deffnx {Scheme Procedure} drop-right! lst i +Return a list containing all but the @var{i} last elements of +@var{lst}. + +@code{drop-right} always returns a new list, even when @var{i} is +zero. @code{drop-right!} may modify the structure of the argument +list @var{lst} in order to produce the result. +@end deffn + +@deffn {Scheme Procedure} split-at lst i +@deffnx {Scheme Procedure} split-at! lst i +Return two values, a list containing the first @var{i} elements of the +list @var{lst} and a list containing the remaining elements. + +@code{split-at!} may modify the structure of the argument list +@var{lst} in order to produce the result. +@end deffn + +@deffn {Scheme Procedure} last lst +Return the last element of the non-empty, finite list @var{lst}. +@end deffn + + +@node SRFI-1 Length Append etc +@subsubsection Length, Append, Concatenate, etc. + +@c FIXME::martin: Review me! + +@deffn {Scheme Procedure} length+ lst +Return the length of the argument list @var{lst}. When @var{lst} is a +circular list, @code{#f} is returned. +@end deffn + +@deffn {Scheme Procedure} concatenate list-of-lists +@deffnx {Scheme Procedure} concatenate! list-of-lists +Construct a list by appending all lists in @var{list-of-lists}. + +@code{concatenate!} may modify the structure of the given lists in +order to produce the result. + +@code{concatenate} is the same as @code{(apply append +@var{list-of-lists})}. It exists because some Scheme implementations +have a limit on the number of arguments a function takes, which the +@code{apply} might exceed. In Guile there is no such limit. +@end deffn + +@deffn {Scheme Procedure} append-reverse rev-head tail +@deffnx {Scheme Procedure} append-reverse! rev-head tail +Reverse @var{rev-head}, append @var{tail} to it, and return the +result. This is equivalent to @code{(append (reverse @var{rev-head}) +@var{tail})}, but its implementation is more efficient. + +@example +(append-reverse '(1 2 3) '(4 5 6)) @result{} (3 2 1 4 5 6) +@end example + +@code{append-reverse!} may modify @var{rev-head} in order to produce +the result. +@end deffn + +@deffn {Scheme Procedure} zip lst1 lst2 @dots{} +Return a list as long as the shortest of the argument lists, where +each element is a list. The first list contains the first elements of +the argument lists, the second list contains the second elements, and +so on. +@end deffn + +@deffn {Scheme Procedure} unzip1 lst +@deffnx {Scheme Procedure} unzip2 lst +@deffnx {Scheme Procedure} unzip3 lst +@deffnx {Scheme Procedure} unzip4 lst +@deffnx {Scheme Procedure} unzip5 lst +@code{unzip1} takes a list of lists, and returns a list containing the +first elements of each list, @code{unzip2} returns two lists, the +first containing the first elements of each lists and the second +containing the second elements of each lists, and so on. +@end deffn + +@deffn {Scheme Procedure} count pred lst1 lst2 @dots{} +Return a count of the number of times @var{pred} returns true when +called on elements from the given lists. + +@var{pred} is called with @var{N} parameters @code{(@var{pred} +@var{elem1} @dots{} @var{elemN} )}, each element being from the +corresponding list. The first call is with the first element of each +list, the second with the second element from each, and so on. + +Counting stops when the end of the shortest list is reached. At least +one list must be non-circular. +@end deffn + + +@node SRFI-1 Fold and Map +@subsubsection Fold, Unfold & Map +@cindex list fold +@cindex list map + +@c FIXME::martin: Review me! + +@deffn {Scheme Procedure} fold proc init lst1 lst2 @dots{} +@deffnx {Scheme Procedure} fold-right proc init lst1 lst2 @dots{} +Apply @var{proc} to the elements of @var{lst1} @var{lst2} @dots{} to +build a result, and return that result. + +Each @var{proc} call is @code{(@var{proc} @var{elem1} @var{elem2} +@dots{} @var{previous})}, where @var{elem1} is from @var{lst1}, +@var{elem2} is from @var{lst2}, and so on. @var{previous} is the return +from the previous call to @var{proc}, or the given @var{init} for the +first call. If any list is empty, just @var{init} is returned. + +@code{fold} works through the list elements from first to last. The +following shows a list reversal and the calls it makes, + +@example +(fold cons '() '(1 2 3)) + +(cons 1 '()) +(cons 2 '(1)) +(cons 3 '(2 1) +@result{} (3 2 1) +@end example + +@code{fold-right} works through the list elements from last to first, +ie.@: from the right. So for example the following finds the longest +string, and the last among equal longest, + +@example +(fold-right (lambda (str prev) + (if (> (string-length str) (string-length prev)) + str + prev)) + "" + '("x" "abc" "xyz" "jk")) +@result{} "xyz" +@end example + +If @var{lst1} @var{lst2} @dots{} have different lengths, @code{fold} +stops when the end of the shortest is reached; @code{fold-right} +commences at the last element of the shortest. Ie.@: elements past the +length of the shortest are ignored in the other @var{lst}s. At least +one @var{lst} must be non-circular. + +@code{fold} should be preferred over @code{fold-right} if the order of +processing doesn't matter, or can be arranged either way, since +@code{fold} is a little more efficient. + +The way @code{fold} builds a result from iterating is quite general, +it can do more than other iterations like say @code{map} or +@code{filter}. The following for example removes adjacent duplicate +elements from a list, + +@example +(define (delete-adjacent-duplicates lst) + (fold-right (lambda (elem ret) + (if (equal? elem (first ret)) + ret + (cons elem ret))) + (list (last lst)) + lst)) +(delete-adjacent-duplicates '(1 2 3 3 4 4 4 5)) +@result{} (1 2 3 4 5) +@end example + +Clearly the same sort of thing can be done with a @code{for-each} and +a variable in which to build the result, but a self-contained +@var{proc} can be re-used in multiple contexts, where a +@code{for-each} would have to be written out each time. +@end deffn + +@deffn {Scheme Procedure} pair-fold proc init lst1 lst2 @dots{} +@deffnx {Scheme Procedure} pair-fold-right proc init lst1 lst2 @dots{} +The same as @code{fold} and @code{fold-right}, but apply @var{proc} to +the pairs of the lists instead of the list elements. +@end deffn + +@deffn {Scheme Procedure} reduce proc default lst +@deffnx {Scheme Procedure} reduce-right proc default lst +@code{reduce} is a variant of @code{fold}, where the first call to +@var{proc} is on two elements from @var{lst}, rather than one element +and a given initial value. + +If @var{lst} is empty, @code{reduce} returns @var{default} (this is +the only use for @var{default}). If @var{lst} has just one element +then that's the return value. Otherwise @var{proc} is called on the +elements of @var{lst}. + +Each @var{proc} call is @code{(@var{proc} @var{elem} @var{previous})}, +where @var{elem} is from @var{lst} (the second and subsequent elements +of @var{lst}), and @var{previous} is the return from the previous call +to @var{proc}. The first element of @var{lst} is the @var{previous} +for the first call to @var{proc}. + +For example, the following adds a list of numbers, the calls made to +@code{+} are shown. (Of course @code{+} accepts multiple arguments +and can add a list directly, with @code{apply}.) + +@example +(reduce + 0 '(5 6 7)) @result{} 18 + +(+ 6 5) @result{} 11 +(+ 7 11) @result{} 18 +@end example + +@code{reduce} can be used instead of @code{fold} where the @var{init} +value is an ``identity'', meaning a value which under @var{proc} +doesn't change the result, in this case 0 is an identity since +@code{(+ 5 0)} is just 5. @code{reduce} avoids that unnecessary call. + +@code{reduce-right} is a similar variation on @code{fold-right}, +working from the end (ie.@: the right) of @var{lst}. The last element +of @var{lst} is the @var{previous} for the first call to @var{proc}, +and the @var{elem} values go from the second last. + +@code{reduce} should be preferred over @code{reduce-right} if the +order of processing doesn't matter, or can be arranged either way, +since @code{reduce} is a little more efficient. +@end deffn + +@deffn {Scheme Procedure} unfold p f g seed [tail-gen] +@code{unfold} is defined as follows: + +@lisp +(unfold p f g seed) = + (if (p seed) (tail-gen seed) + (cons (f seed) + (unfold p f g (g seed)))) +@end lisp + +@table @var +@item p +Determines when to stop unfolding. + +@item f +Maps each seed value to the corresponding list element. + +@item g +Maps each seed value to next seed value. + +@item seed +The state value for the unfold. + +@item tail-gen +Creates the tail of the list; defaults to @code{(lambda (x) '())}. +@end table + +@var{g} produces a series of seed values, which are mapped to list +elements by @var{f}. These elements are put into a list in +left-to-right order, and @var{p} tells when to stop unfolding. +@end deffn + +@deffn {Scheme Procedure} unfold-right p f g seed [tail] +Construct a list with the following loop. + +@lisp +(let lp ((seed seed) (lis tail)) + (if (p seed) lis + (lp (g seed) + (cons (f seed) lis)))) +@end lisp + +@table @var +@item p +Determines when to stop unfolding. + +@item f +Maps each seed value to the corresponding list element. + +@item g +Maps each seed value to next seed value. + +@item seed +The state value for the unfold. + +@item tail +The tail of the list; defaults to @code{'()}. +@end table + +@end deffn + +@deffn {Scheme Procedure} map f lst1 lst2 @dots{} +Map the procedure over the list(s) @var{lst1}, @var{lst2}, @dots{} and +return a list containing the results of the procedure applications. +This procedure is extended with respect to R5RS, because the argument +lists may have different lengths. The result list will have the same +length as the shortest argument lists. The order in which @var{f} +will be applied to the list element(s) is not specified. +@end deffn + +@deffn {Scheme Procedure} for-each f lst1 lst2 @dots{} +Apply the procedure @var{f} to each pair of corresponding elements of +the list(s) @var{lst1}, @var{lst2}, @dots{}. The return value is not +specified. This procedure is extended with respect to R5RS, because +the argument lists may have different lengths. The shortest argument +list determines the number of times @var{f} is called. @var{f} will +be applied to the list elements in left-to-right order. + +@end deffn + +@deffn {Scheme Procedure} append-map f lst1 lst2 @dots{} +@deffnx {Scheme Procedure} append-map! f lst1 lst2 @dots{} +Equivalent to + +@lisp +(apply append (map f clist1 clist2 ...)) +@end lisp + +and + +@lisp +(apply append! (map f clist1 clist2 ...)) +@end lisp + +Map @var{f} over the elements of the lists, just as in the @code{map} +function. However, the results of the applications are appended +together to make the final result. @code{append-map} uses +@code{append} to append the results together; @code{append-map!} uses +@code{append!}. + +The dynamic order in which the various applications of @var{f} are +made is not specified. +@end deffn + +@deffn {Scheme Procedure} map! f lst1 lst2 @dots{} +Linear-update variant of @code{map} -- @code{map!} is allowed, but not +required, to alter the cons cells of @var{lst1} to construct the +result list. + +The dynamic order in which the various applications of @var{f} are +made is not specified. In the n-ary case, @var{lst2}, @var{lst3}, +@dots{} must have at least as many elements as @var{lst1}. +@end deffn + +@deffn {Scheme Procedure} pair-for-each f lst1 lst2 @dots{} +Like @code{for-each}, but applies the procedure @var{f} to the pairs +from which the argument lists are constructed, instead of the list +elements. The return value is not specified. +@end deffn + +@deffn {Scheme Procedure} filter-map f lst1 lst2 @dots{} +Like @code{map}, but only results from the applications of @var{f} +which are true are saved in the result list. +@end deffn + + +@node SRFI-1 Filtering and Partitioning +@subsubsection Filtering and Partitioning +@cindex list filter +@cindex list partition + +@c FIXME::martin: Review me! + +Filtering means to collect all elements from a list which satisfy a +specific condition. Partitioning a list means to make two groups of +list elements, one which contains the elements satisfying a condition, +and the other for the elements which don't. + +The @code{filter} and @code{filter!} functions are implemented in the +Guile core, @xref{List Modification}. + +@deffn {Scheme Procedure} partition pred lst +@deffnx {Scheme Procedure} partition! pred lst +Split @var{lst} into those elements which do and don't satisfy the +predicate @var{pred}. + +The return is two values (@pxref{Multiple Values}), the first being a +list of all elements from @var{lst} which satisfy @var{pred}, the +second a list of those which do not. + +The elements in the result lists are in the same order as in @var{lst} +but the order in which the calls @code{(@var{pred} elem)} are made on +the list elements is unspecified. + +@code{partition} does not change @var{lst}, but one of the returned +lists may share a tail with it. @code{partition!} may modify +@var{lst} to construct its return. +@end deffn + +@deffn {Scheme Procedure} remove pred lst +@deffnx {Scheme Procedure} remove! pred lst +Return a list containing all elements from @var{lst} which do not +satisfy the predicate @var{pred}. The elements in the result list +have the same order as in @var{lst}. The order in which @var{pred} is +applied to the list elements is not specified. + +@code{remove!} is allowed, but not required to modify the structure of +the input list. +@end deffn + + +@node SRFI-1 Searching +@subsubsection Searching +@cindex list search + +@c FIXME::martin: Review me! + +The procedures for searching elements in lists either accept a +predicate or a comparison object for determining which elements are to +be searched. + +@deffn {Scheme Procedure} find pred lst +Return the first element of @var{lst} which satisfies the predicate +@var{pred} and @code{#f} if no such element is found. +@end deffn + +@deffn {Scheme Procedure} find-tail pred lst +Return the first pair of @var{lst} whose @sc{car} satisfies the +predicate @var{pred} and @code{#f} if no such element is found. +@end deffn + +@deffn {Scheme Procedure} take-while pred lst +@deffnx {Scheme Procedure} take-while! pred lst +Return the longest initial prefix of @var{lst} whose elements all +satisfy the predicate @var{pred}. + +@code{take-while!} is allowed, but not required to modify the input +list while producing the result. +@end deffn + +@deffn {Scheme Procedure} drop-while pred lst +Drop the longest initial prefix of @var{lst} whose elements all +satisfy the predicate @var{pred}. +@end deffn + +@deffn {Scheme Procedure} span pred lst +@deffnx {Scheme Procedure} span! pred lst +@deffnx {Scheme Procedure} break pred lst +@deffnx {Scheme Procedure} break! pred lst +@code{span} splits the list @var{lst} into the longest initial prefix +whose elements all satisfy the predicate @var{pred}, and the remaining +tail. @code{break} inverts the sense of the predicate. + +@code{span!} and @code{break!} are allowed, but not required to modify +the structure of the input list @var{lst} in order to produce the +result. + +Note that the name @code{break} conflicts with the @code{break} +binding established by @code{while} (@pxref{while do}). Applications +wanting to use @code{break} from within a @code{while} loop will need +to make a new define under a different name. +@end deffn + +@deffn {Scheme Procedure} any pred lst1 lst2 @dots{} +Test whether any set of elements from @var{lst1} @var{lst2} @dots{} +satisfies @var{pred}. If so, the return value is the return value from +the successful @var{pred} call, or if not, the return value is +@code{#f}. + +If there are n list arguments, then @var{pred} must be a predicate +taking n arguments. Each @var{pred} call is @code{(@var{pred} +@var{elem1} @var{elem2} @dots{} )} taking an element from each +@var{lst}. The calls are made successively for the first, second, etc. +elements of the lists, stopping when @var{pred} returns non-@code{#f}, +or when the end of the shortest list is reached. + +The @var{pred} call on the last set of elements (i.e., when the end of +the shortest list has been reached), if that point is reached, is a +tail call. +@end deffn + +@deffn {Scheme Procedure} every pred lst1 lst2 @dots{} +Test whether every set of elements from @var{lst1} @var{lst2} @dots{} +satisfies @var{pred}. If so, the return value is the return from the +final @var{pred} call, or if not, the return value is @code{#f}. + +If there are n list arguments, then @var{pred} must be a predicate +taking n arguments. Each @var{pred} call is @code{(@var{pred} +@var{elem1} @var{elem2 @dots{}})} taking an element from each +@var{lst}. The calls are made successively for the first, second, etc. +elements of the lists, stopping if @var{pred} returns @code{#f}, or when +the end of any of the lists is reached. + +The @var{pred} call on the last set of elements (i.e., when the end of +the shortest list has been reached) is a tail call. + +If one of @var{lst1} @var{lst2} @dots{}is empty then no calls to +@var{pred} are made, and the return value is @code{#t}. +@end deffn + +@deffn {Scheme Procedure} list-index pred lst1 lst2 @dots{} +Return the index of the first set of elements, one from each of +@var{lst1} @var{lst2} @dots{}, which satisfies @var{pred}. + +@var{pred} is called as @code{(@var{elem1} @var{elem2 @dots{}})}. +Searching stops when the end of the shortest @var{lst} is reached. +The return index starts from 0 for the first set of elements. If no +set of elements pass, then the return value is @code{#f}. + +@example +(list-index odd? '(2 4 6 9)) @result{} 3 +(list-index = '(1 2 3) '(3 1 2)) @result{} #f +@end example +@end deffn + +@deffn {Scheme Procedure} member x lst [=] +Return the first sublist of @var{lst} whose @sc{car} is equal to +@var{x}. If @var{x} does not appear in @var{lst}, return @code{#f}. + +Equality is determined by @code{equal?}, or by the equality predicate +@var{=} if given. @var{=} is called @code{(= @var{x} elem)}, +ie.@: with the given @var{x} first, so for example to find the first +element greater than 5, + +@example +(member 5 '(3 5 1 7 2 9) <) @result{} (7 2 9) +@end example + +This version of @code{member} extends the core @code{member} +(@pxref{List Searching}) by accepting an equality predicate. +@end deffn + + +@node SRFI-1 Deleting +@subsubsection Deleting +@cindex list delete + +@deffn {Scheme Procedure} delete x lst [=] +@deffnx {Scheme Procedure} delete! x lst [=] +Return a list containing the elements of @var{lst} but with those +equal to @var{x} deleted. The returned elements will be in the same +order as they were in @var{lst}. + +Equality is determined by the @var{=} predicate, or @code{equal?} if +not given. An equality call is made just once for each element, but +the order in which the calls are made on the elements is unspecified. + +The equality calls are always @code{(= x elem)}, ie.@: the given @var{x} +is first. This means for instance elements greater than 5 can be +deleted with @code{(delete 5 lst <)}. + +@code{delete} does not modify @var{lst}, but the return might share a +common tail with @var{lst}. @code{delete!} may modify the structure +of @var{lst} to construct its return. + +These functions extend the core @code{delete} and @code{delete!} +(@pxref{List Modification}) in accepting an equality predicate. See +also @code{lset-difference} (@pxref{SRFI-1 Set Operations}) for +deleting multiple elements from a list. +@end deffn + +@deffn {Scheme Procedure} delete-duplicates lst [=] +@deffnx {Scheme Procedure} delete-duplicates! lst [=] +Return a list containing the elements of @var{lst} but without +duplicates. + +When elements are equal, only the first in @var{lst} is retained. +Equal elements can be anywhere in @var{lst}, they don't have to be +adjacent. The returned list will have the retained elements in the +same order as they were in @var{lst}. + +Equality is determined by the @var{=} predicate, or @code{equal?} if +not given. Calls @code{(= x y)} are made with element @var{x} being +before @var{y} in @var{lst}. A call is made at most once for each +combination, but the sequence of the calls across the elements is +unspecified. + +@code{delete-duplicates} does not modify @var{lst}, but the return +might share a common tail with @var{lst}. @code{delete-duplicates!} +may modify the structure of @var{lst} to construct its return. + +In the worst case, this is an @math{O(N^2)} algorithm because it must +check each element against all those preceding it. For long lists it +is more efficient to sort and then compare only adjacent elements. +@end deffn + + +@node SRFI-1 Association Lists +@subsubsection Association Lists +@cindex association list +@cindex alist + +@c FIXME::martin: Review me! + +Association lists are described in detail in section @ref{Association +Lists}. The present section only documents the additional procedures +for dealing with association lists defined by SRFI-1. + +@deffn {Scheme Procedure} assoc key alist [=] +Return the pair from @var{alist} which matches @var{key}. This +extends the core @code{assoc} (@pxref{Retrieving Alist Entries}) by +taking an optional @var{=} comparison procedure. + +The default comparison is @code{equal?}. If an @var{=} parameter is +given it's called @code{(@var{=} @var{key} @var{alistcar})}, i.e.@: the +given target @var{key} is the first argument, and a @code{car} from +@var{alist} is second. + +For example a case-insensitive string lookup, + +@example +(assoc "yy" '(("XX" . 1) ("YY" . 2)) string-ci=?) +@result{} ("YY" . 2) +@end example +@end deffn + +@deffn {Scheme Procedure} alist-cons key datum alist +Cons a new association @var{key} and @var{datum} onto @var{alist} and +return the result. This is equivalent to + +@lisp +(cons (cons @var{key} @var{datum}) @var{alist}) +@end lisp + +@code{acons} (@pxref{Adding or Setting Alist Entries}) in the Guile +core does the same thing. +@end deffn + +@deffn {Scheme Procedure} alist-copy alist +Return a newly allocated copy of @var{alist}, that means that the +spine of the list as well as the pairs are copied. +@end deffn + +@deffn {Scheme Procedure} alist-delete key alist [=] +@deffnx {Scheme Procedure} alist-delete! key alist [=] +Return a list containing the elements of @var{alist} but with those +elements whose keys are equal to @var{key} deleted. The returned +elements will be in the same order as they were in @var{alist}. + +Equality is determined by the @var{=} predicate, or @code{equal?} if +not given. The order in which elements are tested is unspecified, but +each equality call is made @code{(= key alistkey)}, i.e.@: the given +@var{key} parameter is first and the key from @var{alist} second. +This means for instance all associations with a key greater than 5 can +be removed with @code{(alist-delete 5 alist <)}. + +@code{alist-delete} does not modify @var{alist}, but the return might +share a common tail with @var{alist}. @code{alist-delete!} may modify +the list structure of @var{alist} to construct its return. +@end deffn + + +@node SRFI-1 Set Operations +@subsubsection Set Operations on Lists +@cindex list set operation + +Lists can be used to represent sets of objects. The procedures in +this section operate on such lists as sets. + +Note that lists are not an efficient way to implement large sets. The +procedures here typically take time @math{@var{m}@cross{}@var{n}} when +operating on @var{m} and @var{n} element lists. Other data structures +like trees, bitsets (@pxref{Bit Vectors}) or hash tables (@pxref{Hash +Tables}) are faster. + +All these procedures take an equality predicate as the first argument. +This predicate is used for testing the objects in the list sets for +sameness. This predicate must be consistent with @code{eq?} +(@pxref{Equality}) in the sense that if two list elements are +@code{eq?} then they must also be equal under the predicate. This +simply means a given object must be equal to itself. + +@deffn {Scheme Procedure} lset<= = list @dots{} +Return @code{#t} if each list is a subset of the one following it. +I.e., @var{list1} is a subset of @var{list2}, @var{list2} is a subset of +@var{list3}, etc., for as many lists as given. If only one list or no +lists are given, the return value is @code{#t}. + +A list @var{x} is a subset of @var{y} if each element of @var{x} is +equal to some element in @var{y}. Elements are compared using the +given @var{=} procedure, called as @code{(@var{=} xelem yelem)}. + +@example +(lset<= eq?) @result{} #t +(lset<= eqv? '(1 2 3) '(1)) @result{} #f +(lset<= eqv? '(1 3 2) '(4 3 1 2)) @result{} #t +@end example +@end deffn + +@deffn {Scheme Procedure} lset= = list @dots{} +Return @code{#t} if all argument lists are set-equal. @var{list1} is +compared to @var{list2}, @var{list2} to @var{list3}, etc., for as many +lists as given. If only one list or no lists are given, the return +value is @code{#t}. + +Two lists @var{x} and @var{y} are set-equal if each element of @var{x} +is equal to some element of @var{y} and conversely each element of +@var{y} is equal to some element of @var{x}. The order of the +elements in the lists doesn't matter. Element equality is determined +with the given @var{=} procedure, called as @code{(@var{=} xelem +yelem)}, but exactly which calls are made is unspecified. + +@example +(lset= eq?) @result{} #t +(lset= eqv? '(1 2 3) '(3 2 1)) @result{} #t +(lset= string-ci=? '("a" "A" "b") '("B" "b" "a")) @result{} #t +@end example +@end deffn + +@deffn {Scheme Procedure} lset-adjoin = list elem @dots{} +Add to @var{list} any of the given @var{elem}s not already in the list. +@var{elem}s are @code{cons}ed onto the start of @var{list} (so the +return value shares a common tail with @var{list}), but the order that +the @var{elem}s are added is unspecified. + +The given @var{=} procedure is used for comparing elements, called as +@code{(@var{=} listelem elem)}, i.e., the second argument is one of +the given @var{elem} parameters. + +@example +(lset-adjoin eqv? '(1 2 3) 4 1 5) @result{} (5 4 1 2 3) +@end example +@end deffn + +@deffn {Scheme Procedure} lset-union = list @dots{} +@deffnx {Scheme Procedure} lset-union! = list @dots{} +Return the union of the argument list sets. The result is built by +taking the union of @var{list1} and @var{list2}, then the union of +that with @var{list3}, etc., for as many lists as given. For one list +argument that list itself is the result, for no list arguments the +result is the empty list. + +The union of two lists @var{x} and @var{y} is formed as follows. If +@var{x} is empty then the result is @var{y}. Otherwise start with +@var{x} as the result and consider each @var{y} element (from first to +last). A @var{y} element not equal to something already in the result +is @code{cons}ed onto the result. + +The given @var{=} procedure is used for comparing elements, called as +@code{(@var{=} relem yelem)}. The first argument is from the result +accumulated so far, and the second is from the list being union-ed in. +But exactly which calls are made is otherwise unspecified. + +Notice that duplicate elements in @var{list1} (or the first non-empty +list) are preserved, but that repeated elements in subsequent lists +are only added once. + +@example +(lset-union eqv?) @result{} () +(lset-union eqv? '(1 2 3)) @result{} (1 2 3) +(lset-union eqv? '(1 2 1 3) '(2 4 5) '(5)) @result{} (5 4 1 2 1 3) +@end example + +@code{lset-union} doesn't change the given lists but the result may +share a tail with the first non-empty list. @code{lset-union!} can +modify all of the given lists to form the result. +@end deffn + +@deffn {Scheme Procedure} lset-intersection = list1 list2 @dots{} +@deffnx {Scheme Procedure} lset-intersection! = list1 list2 @dots{} +Return the intersection of @var{list1} with the other argument lists, +meaning those elements of @var{list1} which are also in all of +@var{list2} etc. For one list argument, just that list is returned. + +The test for an element of @var{list1} to be in the return is simply +that it's equal to some element in each of @var{list2} etc. Notice +this means an element appearing twice in @var{list1} but only once in +each of @var{list2} etc will go into the return twice. The return has +its elements in the same order as they were in @var{list1}. + +The given @var{=} procedure is used for comparing elements, called as +@code{(@var{=} elem1 elemN)}. The first argument is from @var{list1} +and the second is from one of the subsequent lists. But exactly which +calls are made and in what order is unspecified. + +@example +(lset-intersection eqv? '(x y)) @result{} (x y) +(lset-intersection eqv? '(1 2 3) '(4 3 2)) @result{} (2 3) +(lset-intersection eqv? '(1 1 2 2) '(1 2) '(2 1) '(2)) @result{} (2 2) +@end example + +The return from @code{lset-intersection} may share a tail with +@var{list1}. @code{lset-intersection!} may modify @var{list1} to form +its result. +@end deffn + +@deffn {Scheme Procedure} lset-difference = list1 list2 @dots{} +@deffnx {Scheme Procedure} lset-difference! = list1 list2 @dots{} +Return @var{list1} with any elements in @var{list2}, @var{list3} etc +removed (ie.@: subtracted). For one list argument, just that list is +returned. + +The given @var{=} procedure is used for comparing elements, called as +@code{(@var{=} elem1 elemN)}. The first argument is from @var{list1} +and the second from one of the subsequent lists. But exactly which +calls are made and in what order is unspecified. + +@example +(lset-difference eqv? '(x y)) @result{} (x y) +(lset-difference eqv? '(1 2 3) '(3 1)) @result{} (2) +(lset-difference eqv? '(1 2 3) '(3) '(2)) @result{} (1) +@end example + +The return from @code{lset-difference} may share a tail with +@var{list1}. @code{lset-difference!} may modify @var{list1} to form +its result. +@end deffn + +@deffn {Scheme Procedure} lset-diff+intersection = list1 list2 @dots{} +@deffnx {Scheme Procedure} lset-diff+intersection! = list1 list2 @dots{} +Return two values (@pxref{Multiple Values}), the difference and +intersection of the argument lists as per @code{lset-difference} and +@code{lset-intersection} above. + +For two list arguments this partitions @var{list1} into those elements +of @var{list1} which are in @var{list2} and not in @var{list2}. (But +for more than two arguments there can be elements of @var{list1} which +are neither part of the difference nor the intersection.) + +One of the return values from @code{lset-diff+intersection} may share +a tail with @var{list1}. @code{lset-diff+intersection!} may modify +@var{list1} to form its results. +@end deffn + +@deffn {Scheme Procedure} lset-xor = list @dots{} +@deffnx {Scheme Procedure} lset-xor! = list @dots{} +Return an XOR of the argument lists. For two lists this means those +elements which are in exactly one of the lists. For more than two +lists it means those elements which appear in an odd number of the +lists. + +To be precise, the XOR of two lists @var{x} and @var{y} is formed by +taking those elements of @var{x} not equal to any element of @var{y}, +plus those elements of @var{y} not equal to any element of @var{x}. +Equality is determined with the given @var{=} procedure, called as +@code{(@var{=} e1 e2)}. One argument is from @var{x} and the other +from @var{y}, but which way around is unspecified. Exactly which +calls are made is also unspecified, as is the order of the elements in +the result. + +@example +(lset-xor eqv? '(x y)) @result{} (x y) +(lset-xor eqv? '(1 2 3) '(4 3 2)) @result{} (4 1) +@end example + +The return from @code{lset-xor} may share a tail with one of the list +arguments. @code{lset-xor!} may modify @var{list1} to form its +result. +@end deffn + + +@node SRFI-2 +@subsection SRFI-2 - and-let* +@cindex SRFI-2 + +@noindent +The following syntax can be obtained with + +@lisp +(use-modules (srfi srfi-2)) +@end lisp + +or alternatively + +@lisp +(use-modules (ice-9 and-let-star)) +@end lisp + +@deffn {library syntax} and-let* (clause @dots{}) body @dots{} +A combination of @code{and} and @code{let*}. + +Each @var{clause} is evaluated in turn, and if @code{#f} is obtained +then evaluation stops and @code{#f} is returned. If all are +non-@code{#f} then @var{body} is evaluated and the last form gives the +return value, or if @var{body} is empty then the result is @code{#t}. +Each @var{clause} should be one of the following, + +@table @code +@item (symbol expr) +Evaluate @var{expr}, check for @code{#f}, and bind it to @var{symbol}. +Like @code{let*}, that binding is available to subsequent clauses. +@item (expr) +Evaluate @var{expr} and check for @code{#f}. +@item symbol +Get the value bound to @var{symbol} and check for @code{#f}. +@end table + +Notice that @code{(expr)} has an ``extra'' pair of parentheses, for +instance @code{((eq? x y))}. One way to remember this is to imagine +the @code{symbol} in @code{(symbol expr)} is omitted. + +@code{and-let*} is good for calculations where a @code{#f} value means +termination, but where a non-@code{#f} value is going to be needed in +subsequent expressions. + +The following illustrates this, it returns text between brackets +@samp{[...]} in a string, or @code{#f} if there are no such brackets +(ie.@: either @code{string-index} gives @code{#f}). + +@example +(define (extract-brackets str) + (and-let* ((start (string-index str #\[)) + (end (string-index str #\] start))) + (substring str (1+ start) end))) +@end example + +The following shows plain variables and expressions tested too. +@code{diagnostic-levels} is taken to be an alist associating a +diagnostic type with a level. @code{str} is printed only if the type +is known and its level is high enough. + +@example +(define (show-diagnostic type str) + (and-let* (want-diagnostics + (level (assq-ref diagnostic-levels type)) + ((>= level current-diagnostic-level))) + (display str))) +@end example + +The advantage of @code{and-let*} is that an extended sequence of +expressions and tests doesn't require lots of nesting as would arise +from separate @code{and} and @code{let*}, or from @code{cond} with +@code{=>}. + +@end deffn + + +@node SRFI-4 +@subsection SRFI-4 - Homogeneous numeric vector datatypes +@cindex SRFI-4 + +SRFI-4 provides an interface to uniform numeric vectors: vectors whose elements +are all of a single numeric type. Guile offers uniform numeric vectors for +signed and unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of +floating point values, and, as an extension to SRFI-4, complex floating-point +numbers of these two sizes. + +The standard SRFI-4 procedures and data types may be included via loading the +appropriate module: + +@example +(use-modules (srfi srfi-4)) +@end example + +This module is currently a part of the default Guile environment, but it is a +good practice to explicitly import the module. In the future, using SRFI-4 +procedures without importing the SRFI-4 module will cause a deprecation message +to be printed. (Of course, one may call the C functions at any time. Would that +C had modules!) + +@menu +* SRFI-4 Overview:: The warp and weft of uniform numeric vectors. +* SRFI-4 API:: Uniform vectors, from Scheme and from C. +* SRFI-4 and Bytevectors:: SRFI-4 vectors are backed by bytevectors. +* SRFI-4 Extensions:: Guile-specific extensions to the standard. +@end menu + +@node SRFI-4 Overview +@subsubsection SRFI-4 - Overview + +Uniform numeric vectors can be useful since they consume less memory +than the non-uniform, general vectors. Also, since the types they can +store correspond directly to C types, it is easier to work with them +efficiently on a low level. Consider image processing as an example, +where you want to apply a filter to some image. While you could store +the pixels of an image in a general vector and write a general +convolution function, things are much more efficient with uniform +vectors: the convolution function knows that all pixels are unsigned +8-bit values (say), and can use a very tight inner loop. + +This is implemented in Scheme by having the compiler notice calls to the SRFI-4 +accessors, and inline them to appropriate compiled code. From C you have access +to the raw array; functions for efficiently working with uniform numeric vectors +from C are listed at the end of this section. + +Uniform numeric vectors are the special case of one dimensional uniform +numeric arrays. + +There are 12 standard kinds of uniform numeric vectors, and they all have their +own complement of constructors, accessors, and so on. Procedures that operate on +a specific kind of uniform numeric vector have a ``tag'' in their name, +indicating the element type. + +@table @nicode +@item u8 +unsigned 8-bit integers + +@item s8 +signed 8-bit integers + +@item u16 +unsigned 16-bit integers + +@item s16 +signed 16-bit integers + +@item u32 +unsigned 32-bit integers + +@item s32 +signed 32-bit integers + +@item u64 +unsigned 64-bit integers + +@item s64 +signed 64-bit integers + +@item f32 +the C type @code{float} + +@item f64 +the C type @code{double} + +@end table + +In addition, Guile supports uniform arrays of complex numbers, with the +nonstandard tags: + +@table @nicode + +@item c32 +complex numbers in rectangular form with the real and imaginary part +being a @code{float} + +@item c64 +complex numbers in rectangular form with the real and imaginary part +being a @code{double} + +@end table + +The external representation (ie.@: read syntax) for these vectors is +similar to normal Scheme vectors, but with an additional tag from the +tables above indicating the vector's type. For example, + +@lisp +#u16(1 2 3) +#f64(3.1415 2.71) +@end lisp + +Note that the read syntax for floating-point here conflicts with +@code{#f} for false. In Standard Scheme one can write @code{(1 #f3)} +for a three element list @code{(1 #f 3)}, but for Guile @code{(1 #f3)} +is invalid. @code{(1 #f 3)} is almost certainly what one should write +anyway to make the intention clear, so this is rarely a problem. + + +@node SRFI-4 API +@subsubsection SRFI-4 - API + +Note that the @nicode{c32} and @nicode{c64} functions are only available from +@nicode{(srfi srfi-4 gnu)}. + +@deffn {Scheme Procedure} u8vector? obj +@deffnx {Scheme Procedure} s8vector? obj +@deffnx {Scheme Procedure} u16vector? obj +@deffnx {Scheme Procedure} s16vector? obj +@deffnx {Scheme Procedure} u32vector? obj +@deffnx {Scheme Procedure} s32vector? obj +@deffnx {Scheme Procedure} u64vector? obj +@deffnx {Scheme Procedure} s64vector? obj +@deffnx {Scheme Procedure} f32vector? obj +@deffnx {Scheme Procedure} f64vector? obj +@deffnx {Scheme Procedure} c32vector? obj +@deffnx {Scheme Procedure} c64vector? obj +@deffnx {C Function} scm_u8vector_p (obj) +@deffnx {C Function} scm_s8vector_p (obj) +@deffnx {C Function} scm_u16vector_p (obj) +@deffnx {C Function} scm_s16vector_p (obj) +@deffnx {C Function} scm_u32vector_p (obj) +@deffnx {C Function} scm_s32vector_p (obj) +@deffnx {C Function} scm_u64vector_p (obj) +@deffnx {C Function} scm_s64vector_p (obj) +@deffnx {C Function} scm_f32vector_p (obj) +@deffnx {C Function} scm_f64vector_p (obj) +@deffnx {C Function} scm_c32vector_p (obj) +@deffnx {C Function} scm_c64vector_p (obj) +Return @code{#t} if @var{obj} is a homogeneous numeric vector of the +indicated type. +@end deffn + +@deffn {Scheme Procedure} make-u8vector n [value] +@deffnx {Scheme Procedure} make-s8vector n [value] +@deffnx {Scheme Procedure} make-u16vector n [value] +@deffnx {Scheme Procedure} make-s16vector n [value] +@deffnx {Scheme Procedure} make-u32vector n [value] +@deffnx {Scheme Procedure} make-s32vector n [value] +@deffnx {Scheme Procedure} make-u64vector n [value] +@deffnx {Scheme Procedure} make-s64vector n [value] +@deffnx {Scheme Procedure} make-f32vector n [value] +@deffnx {Scheme Procedure} make-f64vector n [value] +@deffnx {Scheme Procedure} make-c32vector n [value] +@deffnx {Scheme Procedure} make-c64vector n [value] +@deffnx {C Function} scm_make_u8vector (n, value) +@deffnx {C Function} scm_make_s8vector (n, value) +@deffnx {C Function} scm_make_u16vector (n, value) +@deffnx {C Function} scm_make_s16vector (n, value) +@deffnx {C Function} scm_make_u32vector (n, value) +@deffnx {C Function} scm_make_s32vector (n, value) +@deffnx {C Function} scm_make_u64vector (n, value) +@deffnx {C Function} scm_make_s64vector (n, value) +@deffnx {C Function} scm_make_f32vector (n, value) +@deffnx {C Function} scm_make_f64vector (n, value) +@deffnx {C Function} scm_make_c32vector (n, value) +@deffnx {C Function} scm_make_c64vector (n, value) +Return a newly allocated homogeneous numeric vector holding @var{n} +elements of the indicated type. If @var{value} is given, the vector +is initialized with that value, otherwise the contents are +unspecified. +@end deffn + +@deffn {Scheme Procedure} u8vector value @dots{} +@deffnx {Scheme Procedure} s8vector value @dots{} +@deffnx {Scheme Procedure} u16vector value @dots{} +@deffnx {Scheme Procedure} s16vector value @dots{} +@deffnx {Scheme Procedure} u32vector value @dots{} +@deffnx {Scheme Procedure} s32vector value @dots{} +@deffnx {Scheme Procedure} u64vector value @dots{} +@deffnx {Scheme Procedure} s64vector value @dots{} +@deffnx {Scheme Procedure} f32vector value @dots{} +@deffnx {Scheme Procedure} f64vector value @dots{} +@deffnx {Scheme Procedure} c32vector value @dots{} +@deffnx {Scheme Procedure} c64vector value @dots{} +@deffnx {C Function} scm_u8vector (values) +@deffnx {C Function} scm_s8vector (values) +@deffnx {C Function} scm_u16vector (values) +@deffnx {C Function} scm_s16vector (values) +@deffnx {C Function} scm_u32vector (values) +@deffnx {C Function} scm_s32vector (values) +@deffnx {C Function} scm_u64vector (values) +@deffnx {C Function} scm_s64vector (values) +@deffnx {C Function} scm_f32vector (values) +@deffnx {C Function} scm_f64vector (values) +@deffnx {C Function} scm_c32vector (values) +@deffnx {C Function} scm_c64vector (values) +Return a newly allocated homogeneous numeric vector of the indicated +type, holding the given parameter @var{value}s. The vector length is +the number of parameters given. +@end deffn + +@deffn {Scheme Procedure} u8vector-length vec +@deffnx {Scheme Procedure} s8vector-length vec +@deffnx {Scheme Procedure} u16vector-length vec +@deffnx {Scheme Procedure} s16vector-length vec +@deffnx {Scheme Procedure} u32vector-length vec +@deffnx {Scheme Procedure} s32vector-length vec +@deffnx {Scheme Procedure} u64vector-length vec +@deffnx {Scheme Procedure} s64vector-length vec +@deffnx {Scheme Procedure} f32vector-length vec +@deffnx {Scheme Procedure} f64vector-length vec +@deffnx {Scheme Procedure} c32vector-length vec +@deffnx {Scheme Procedure} c64vector-length vec +@deffnx {C Function} scm_u8vector_length (vec) +@deffnx {C Function} scm_s8vector_length (vec) +@deffnx {C Function} scm_u16vector_length (vec) +@deffnx {C Function} scm_s16vector_length (vec) +@deffnx {C Function} scm_u32vector_length (vec) +@deffnx {C Function} scm_s32vector_length (vec) +@deffnx {C Function} scm_u64vector_length (vec) +@deffnx {C Function} scm_s64vector_length (vec) +@deffnx {C Function} scm_f32vector_length (vec) +@deffnx {C Function} scm_f64vector_length (vec) +@deffnx {C Function} scm_c32vector_length (vec) +@deffnx {C Function} scm_c64vector_length (vec) +Return the number of elements in @var{vec}. +@end deffn + +@deffn {Scheme Procedure} u8vector-ref vec i +@deffnx {Scheme Procedure} s8vector-ref vec i +@deffnx {Scheme Procedure} u16vector-ref vec i +@deffnx {Scheme Procedure} s16vector-ref vec i +@deffnx {Scheme Procedure} u32vector-ref vec i +@deffnx {Scheme Procedure} s32vector-ref vec i +@deffnx {Scheme Procedure} u64vector-ref vec i +@deffnx {Scheme Procedure} s64vector-ref vec i +@deffnx {Scheme Procedure} f32vector-ref vec i +@deffnx {Scheme Procedure} f64vector-ref vec i +@deffnx {Scheme Procedure} c32vector-ref vec i +@deffnx {Scheme Procedure} c64vector-ref vec i +@deffnx {C Function} scm_u8vector_ref (vec, i) +@deffnx {C Function} scm_s8vector_ref (vec, i) +@deffnx {C Function} scm_u16vector_ref (vec, i) +@deffnx {C Function} scm_s16vector_ref (vec, i) +@deffnx {C Function} scm_u32vector_ref (vec, i) +@deffnx {C Function} scm_s32vector_ref (vec, i) +@deffnx {C Function} scm_u64vector_ref (vec, i) +@deffnx {C Function} scm_s64vector_ref (vec, i) +@deffnx {C Function} scm_f32vector_ref (vec, i) +@deffnx {C Function} scm_f64vector_ref (vec, i) +@deffnx {C Function} scm_c32vector_ref (vec, i) +@deffnx {C Function} scm_c64vector_ref (vec, i) +Return the element at index @var{i} in @var{vec}. The first element +in @var{vec} is index 0. +@end deffn + +@deffn {Scheme Procedure} u8vector-set! vec i value +@deffnx {Scheme Procedure} s8vector-set! vec i value +@deffnx {Scheme Procedure} u16vector-set! vec i value +@deffnx {Scheme Procedure} s16vector-set! vec i value +@deffnx {Scheme Procedure} u32vector-set! vec i value +@deffnx {Scheme Procedure} s32vector-set! vec i value +@deffnx {Scheme Procedure} u64vector-set! vec i value +@deffnx {Scheme Procedure} s64vector-set! vec i value +@deffnx {Scheme Procedure} f32vector-set! vec i value +@deffnx {Scheme Procedure} f64vector-set! vec i value +@deffnx {Scheme Procedure} c32vector-set! vec i value +@deffnx {Scheme Procedure} c64vector-set! vec i value +@deffnx {C Function} scm_u8vector_set_x (vec, i, value) +@deffnx {C Function} scm_s8vector_set_x (vec, i, value) +@deffnx {C Function} scm_u16vector_set_x (vec, i, value) +@deffnx {C Function} scm_s16vector_set_x (vec, i, value) +@deffnx {C Function} scm_u32vector_set_x (vec, i, value) +@deffnx {C Function} scm_s32vector_set_x (vec, i, value) +@deffnx {C Function} scm_u64vector_set_x (vec, i, value) +@deffnx {C Function} scm_s64vector_set_x (vec, i, value) +@deffnx {C Function} scm_f32vector_set_x (vec, i, value) +@deffnx {C Function} scm_f64vector_set_x (vec, i, value) +@deffnx {C Function} scm_c32vector_set_x (vec, i, value) +@deffnx {C Function} scm_c64vector_set_x (vec, i, value) +Set the element at index @var{i} in @var{vec} to @var{value}. The +first element in @var{vec} is index 0. The return value is +unspecified. +@end deffn + +@deffn {Scheme Procedure} u8vector->list vec +@deffnx {Scheme Procedure} s8vector->list vec +@deffnx {Scheme Procedure} u16vector->list vec +@deffnx {Scheme Procedure} s16vector->list vec +@deffnx {Scheme Procedure} u32vector->list vec +@deffnx {Scheme Procedure} s32vector->list vec +@deffnx {Scheme Procedure} u64vector->list vec +@deffnx {Scheme Procedure} s64vector->list vec +@deffnx {Scheme Procedure} f32vector->list vec +@deffnx {Scheme Procedure} f64vector->list vec +@deffnx {Scheme Procedure} c32vector->list vec +@deffnx {Scheme Procedure} c64vector->list vec +@deffnx {C Function} scm_u8vector_to_list (vec) +@deffnx {C Function} scm_s8vector_to_list (vec) +@deffnx {C Function} scm_u16vector_to_list (vec) +@deffnx {C Function} scm_s16vector_to_list (vec) +@deffnx {C Function} scm_u32vector_to_list (vec) +@deffnx {C Function} scm_s32vector_to_list (vec) +@deffnx {C Function} scm_u64vector_to_list (vec) +@deffnx {C Function} scm_s64vector_to_list (vec) +@deffnx {C Function} scm_f32vector_to_list (vec) +@deffnx {C Function} scm_f64vector_to_list (vec) +@deffnx {C Function} scm_c32vector_to_list (vec) +@deffnx {C Function} scm_c64vector_to_list (vec) +Return a newly allocated list holding all elements of @var{vec}. +@end deffn + +@deffn {Scheme Procedure} list->u8vector lst +@deffnx {Scheme Procedure} list->s8vector lst +@deffnx {Scheme Procedure} list->u16vector lst +@deffnx {Scheme Procedure} list->s16vector lst +@deffnx {Scheme Procedure} list->u32vector lst +@deffnx {Scheme Procedure} list->s32vector lst +@deffnx {Scheme Procedure} list->u64vector lst +@deffnx {Scheme Procedure} list->s64vector lst +@deffnx {Scheme Procedure} list->f32vector lst +@deffnx {Scheme Procedure} list->f64vector lst +@deffnx {Scheme Procedure} list->c32vector lst +@deffnx {Scheme Procedure} list->c64vector lst +@deffnx {C Function} scm_list_to_u8vector (lst) +@deffnx {C Function} scm_list_to_s8vector (lst) +@deffnx {C Function} scm_list_to_u16vector (lst) +@deffnx {C Function} scm_list_to_s16vector (lst) +@deffnx {C Function} scm_list_to_u32vector (lst) +@deffnx {C Function} scm_list_to_s32vector (lst) +@deffnx {C Function} scm_list_to_u64vector (lst) +@deffnx {C Function} scm_list_to_s64vector (lst) +@deffnx {C Function} scm_list_to_f32vector (lst) +@deffnx {C Function} scm_list_to_f64vector (lst) +@deffnx {C Function} scm_list_to_c32vector (lst) +@deffnx {C Function} scm_list_to_c64vector (lst) +Return a newly allocated homogeneous numeric vector of the indicated type, +initialized with the elements of the list @var{lst}. +@end deffn + +@deftypefn {C Function} SCM scm_take_u8vector (const scm_t_uint8 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_s8vector (const scm_t_int8 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_u16vector (const scm_t_uint16 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_s16vector (const scm_t_int16 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_u32vector (const scm_t_uint32 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_s32vector (const scm_t_int32 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_u64vector (const scm_t_uint64 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_s64vector (const scm_t_int64 *data, size_t len) +@deftypefnx {C Function} SCM scm_take_f32vector (const float *data, size_t len) +@deftypefnx {C Function} SCM scm_take_f64vector (const double *data, size_t len) +@deftypefnx {C Function} SCM scm_take_c32vector (const float *data, size_t len) +@deftypefnx {C Function} SCM scm_take_c64vector (const double *data, size_t len) +Return a new uniform numeric vector of the indicated type and length +that uses the memory pointed to by @var{data} to store its elements. +This memory will eventually be freed with @code{free}. The argument +@var{len} specifies the number of elements in @var{data}, not its size +in bytes. + +The @code{c32} and @code{c64} variants take a pointer to a C array of +@code{float}s or @code{double}s. The real parts of the complex numbers +are at even indices in that array, the corresponding imaginary parts are +at the following odd index. +@end deftypefn + +@deftypefn {C Function} {const scm_t_uint8 *} scm_u8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_int8 *} scm_s8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_uint16 *} scm_u16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_int16 *} scm_s16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_uint32 *} scm_u32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_int32 *} scm_s32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_uint64 *} scm_u64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const scm_t_int64 *} scm_s64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const float *} scm_f32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const double *} scm_f64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const float *} scm_c32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {const double *} scm_c64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +Like @code{scm_vector_elements} (@pxref{Vector Accessing from C}), but +returns a pointer to the elements of a uniform numeric vector of the +indicated kind. +@end deftypefn + +@deftypefn {C Function} {scm_t_uint8 *} scm_u8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_int8 *} scm_s8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_uint16 *} scm_u16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_int16 *} scm_s16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_uint32 *} scm_u32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_int32 *} scm_s32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_uint64 *} scm_u64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {scm_t_int64 *} scm_s64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {float *} scm_f32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {double *} scm_f64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {float *} scm_c32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +@deftypefnx {C Function} {double *} scm_c64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp) +Like @code{scm_vector_writable_elements} (@pxref{Vector Accessing from +C}), but returns a pointer to the elements of a uniform numeric vector +of the indicated kind. +@end deftypefn + +@node SRFI-4 and Bytevectors +@subsubsection SRFI-4 - Relation to bytevectors + +Guile implements SRFI-4 vectors using bytevectors (@pxref{Bytevectors}). Often +when you have a numeric vector, you end up wanting to write its bytes somewhere, +or have access to the underlying bytes, or read in bytes from somewhere else. +Bytevectors are very good at this sort of thing. But the SRFI-4 APIs are nicer +to use when doing number-crunching, because they are addressed by element and +not by byte. + +So as a compromise, Guile allows all bytevector functions to operate on numeric +vectors. They address the underlying bytes in the native endianness, as one +would expect. + +Following the same reasoning, that it's just bytes underneath, Guile also allows +uniform vectors of a given type to be accessed as if they were of any type. One +can fill a @nicode{u32vector}, and access its elements with +@nicode{u8vector-ref}. One can use @nicode{f64vector-ref} on bytevectors. It's +all the same to Guile. + +In this way, uniform numeric vectors may be written to and read from +input/output ports using the procedures that operate on bytevectors. + +@xref{Bytevectors}, for more information. + + +@node SRFI-4 Extensions +@subsubsection SRFI-4 - Guile extensions + +Guile defines some useful extensions to SRFI-4, which are not available in the +default Guile environment. They may be imported by loading the extensions +module: + +@example +(use-modules (srfi srfi-4 gnu)) +@end example + +@deffn {Scheme Procedure} any->u8vector obj +@deffnx {Scheme Procedure} any->s8vector obj +@deffnx {Scheme Procedure} any->u16vector obj +@deffnx {Scheme Procedure} any->s16vector obj +@deffnx {Scheme Procedure} any->u32vector obj +@deffnx {Scheme Procedure} any->s32vector obj +@deffnx {Scheme Procedure} any->u64vector obj +@deffnx {Scheme Procedure} any->s64vector obj +@deffnx {Scheme Procedure} any->f32vector obj +@deffnx {Scheme Procedure} any->f64vector obj +@deffnx {Scheme Procedure} any->c32vector obj +@deffnx {Scheme Procedure} any->c64vector obj +@deffnx {C Function} scm_any_to_u8vector (obj) +@deffnx {C Function} scm_any_to_s8vector (obj) +@deffnx {C Function} scm_any_to_u16vector (obj) +@deffnx {C Function} scm_any_to_s16vector (obj) +@deffnx {C Function} scm_any_to_u32vector (obj) +@deffnx {C Function} scm_any_to_s32vector (obj) +@deffnx {C Function} scm_any_to_u64vector (obj) +@deffnx {C Function} scm_any_to_s64vector (obj) +@deffnx {C Function} scm_any_to_f32vector (obj) +@deffnx {C Function} scm_any_to_f64vector (obj) +@deffnx {C Function} scm_any_to_c32vector (obj) +@deffnx {C Function} scm_any_to_c64vector (obj) +Return a (maybe newly allocated) uniform numeric vector of the indicated +type, initialized with the elements of @var{obj}, which must be a list, +a vector, or a uniform vector. When @var{obj} is already a suitable +uniform numeric vector, it is returned unchanged. +@end deffn + + +@node SRFI-6 +@subsection SRFI-6 - Basic String Ports +@cindex SRFI-6 + +SRFI-6 defines the procedures @code{open-input-string}, +@code{open-output-string} and @code{get-output-string}. These +procedures are included in the Guile core, so using this module does not +make any difference at the moment. But it is possible that support for +SRFI-6 will be factored out of the core library in the future, so using +this module does not hurt, after all. + +@node SRFI-8 +@subsection SRFI-8 - receive +@cindex SRFI-8 + +@code{receive} is a syntax for making the handling of multiple-value +procedures easier. It is documented in @xref{Multiple Values}. + + +@node SRFI-9 +@subsection SRFI-9 - define-record-type + +This SRFI is a syntax for defining new record types and creating +predicate, constructor, and field getter and setter functions. It is +documented in the ``Data Types'' section of the manual (@pxref{SRFI-9 +Records}). + + +@node SRFI-10 +@subsection SRFI-10 - Hash-Comma Reader Extension +@cindex SRFI-10 + +@cindex hash-comma +@cindex #,() +This SRFI implements a reader extension @code{#,()} called hash-comma. +It allows the reader to give new kinds of objects, for use both in data +and as constants or literals in source code. This feature is available +with + +@example +(use-modules (srfi srfi-10)) +@end example + +@noindent +The new read syntax is of the form + +@example +#,(@var{tag} @var{arg}@dots{}) +@end example + +@noindent +where @var{tag} is a symbol and the @var{arg}s are objects taken as +parameters. @var{tag}s are registered with the following procedure. + +@deffn {Scheme Procedure} define-reader-ctor tag proc +Register @var{proc} as the constructor for a hash-comma read syntax +starting with symbol @var{tag}, i.e.@: @nicode{#,(@var{tag} arg@dots{})}. +@var{proc} is called with the given arguments @code{(@var{proc} +arg@dots{})} and the object it returns is the result of the read. +@end deffn + +@noindent +For example, a syntax giving a list of @var{N} copies of an object. + +@example +(define-reader-ctor 'repeat + (lambda (obj reps) + (make-list reps obj))) + +(display '#,(repeat 99 3)) +@print{} (99 99 99) +@end example + +Notice the quote @nicode{'} when the @nicode{#,( )} is used. The +@code{repeat} handler returns a list and the program must quote to use +it literally, the same as any other list. Ie. + +@example +(display '#,(repeat 99 3)) +@result{} +(display '(99 99 99)) +@end example + +When a handler returns an object which is self-evaluating, like a +number or a string, then there's no need for quoting, just as there's +no need when giving those directly as literals. For example an +addition, + +@example +(define-reader-ctor 'sum + (lambda (x y) + (+ x y))) +(display #,(sum 123 456)) @print{} 579 +@end example + +Once @code{(srfi srfi-10)} has loaded, @nicode{#,()} is available +globally, there's no need to use @code{(srfi srfi-10)} in later +modules. Similarly the tags registered are global and can be used +anywhere once registered. + +We do not recommend @nicode{#,()} reader extensions, however, and for +three reasons. + +First of all, this SRFI is not modular: the tag is matched by name, not +as an identifier within a scope. Defining a reader extension in one +part of a program can thus affect unrelated parts of a program because +the tag is not scoped. + +Secondly, reader extensions can be hard to manage from a time +perspective: when does the reader extension take effect? @xref{Eval +When}, for more discussion. + +Finally, reader extensions can easily produce objects that can't be +reified to an object file by the compiler. For example if you define a +reader extension that makes a hash table (@pxref{Hash Tables}), then it +will work fine when run with the interpreter, and you think you have a +neat hack. But then if you try to compile your program, after wrangling +with the @code{eval-when} concerns mentioned above, the compiler will +carp that it doesn't know how to serialize a hash table to disk. + +In the specific case of hash tables, it would be possible for Guile to +know how to pack hash tables into compiled files, but this doesn't work +in general. What if the object you produce is an instance of a record +type? Guile would then have to serialize the record type to disk too, +and then what happens if the program independently loads the code that +defines the record type? Does it define the same type or a different +type? Guile's record types are nominal, not structural, so the answer +is not clear at all. + +For all of these reasons we recommend macros over reader extensions. +Macros fulfill many of the same needs while preserving modular +composition, and their interaction with @code{eval-when} is well-known. +If you need brevity, instead use @code{read-hash-extend} and make your +reader extension expand to a macro invocation. In that way we preserve +scoping as much as possible. @xref{Reader Extensions}. + + +@node SRFI-11 +@subsection SRFI-11 - let-values +@cindex SRFI-11 + +@findex let-values +@findex let*-values +This module implements the binding forms for multiple values +@code{let-values} and @code{let*-values}. These forms are similar to +@code{let} and @code{let*} (@pxref{Local Bindings}), but they support +binding of the values returned by multiple-valued expressions. + +Write @code{(use-modules (srfi srfi-11))} to make the bindings +available. + +@lisp +(let-values (((x y) (values 1 2)) + ((z f) (values 3 4))) + (+ x y z f)) +@result{} +10 +@end lisp + +@code{let-values} performs all bindings simultaneously, which means that +no expression in the binding clauses may refer to variables bound in the +same clause list. @code{let*-values}, on the other hand, performs the +bindings sequentially, just like @code{let*} does for single-valued +expressions. + + +@node SRFI-13 +@subsection SRFI-13 - String Library +@cindex SRFI-13 + +The SRFI-13 procedures are always available, @xref{Strings}. + +@node SRFI-14 +@subsection SRFI-14 - Character-set Library +@cindex SRFI-14 + +The SRFI-14 data type and procedures are always available, +@xref{Character Sets}. + +@node SRFI-16 +@subsection SRFI-16 - case-lambda +@cindex SRFI-16 +@cindex variable arity +@cindex arity, variable + +SRFI-16 defines a variable-arity @code{lambda} form, +@code{case-lambda}. This form is available in the default Guile +environment. @xref{Case-lambda}, for more information. + +@node SRFI-17 +@subsection SRFI-17 - Generalized set! +@cindex SRFI-17 + +This SRFI implements a generalized @code{set!}, allowing some +``referencing'' functions to be used as the target location of a +@code{set!}. This feature is available from + +@example +(use-modules (srfi srfi-17)) +@end example + +@noindent +For example @code{vector-ref} is extended so that + +@example +(set! (vector-ref vec idx) new-value) +@end example + +@noindent +is equivalent to + +@example +(vector-set! vec idx new-value) +@end example + +The idea is that a @code{vector-ref} expression identifies a location, +which may be either fetched or stored. The same form is used for the +location in both cases, encouraging visual clarity. This is similar +to the idea of an ``lvalue'' in C. + +The mechanism for this kind of @code{set!} is in the Guile core +(@pxref{Procedures with Setters}). This module adds definitions of +the following functions as procedures with setters, allowing them to +be targets of a @code{set!}, + +@quotation +@nicode{car}, @nicode{cdr}, @nicode{caar}, @nicode{cadr}, +@nicode{cdar}, @nicode{cddr}, @nicode{caaar}, @nicode{caadr}, +@nicode{cadar}, @nicode{caddr}, @nicode{cdaar}, @nicode{cdadr}, +@nicode{cddar}, @nicode{cdddr}, @nicode{caaaar}, @nicode{caaadr}, +@nicode{caadar}, @nicode{caaddr}, @nicode{cadaar}, @nicode{cadadr}, +@nicode{caddar}, @nicode{cadddr}, @nicode{cdaaar}, @nicode{cdaadr}, +@nicode{cdadar}, @nicode{cdaddr}, @nicode{cddaar}, @nicode{cddadr}, +@nicode{cdddar}, @nicode{cddddr} + +@nicode{string-ref}, @nicode{vector-ref} +@end quotation + +The SRFI specifies @code{setter} (@pxref{Procedures with Setters}) as +a procedure with setter, allowing the setter for a procedure to be +changed, eg.@: @code{(set! (setter foo) my-new-setter-handler)}. +Currently Guile does not implement this, a setter can only be +specified on creation (@code{getter-with-setter} below). + +@defun getter-with-setter +The same as the Guile core @code{make-procedure-with-setter} +(@pxref{Procedures with Setters}). +@end defun + + +@node SRFI-18 +@subsection SRFI-18 - Multithreading support +@cindex SRFI-18 + +This is an implementation of the SRFI-18 threading and synchronization +library. The functions and variables described here are provided by + +@example +(use-modules (srfi srfi-18)) +@end example + +SRFI-18 defines facilities for threads, mutexes, condition variables, +time, and exception handling. Because these facilities are at a higher +level than Guile's primitives, they are implemented as a layer on top of +what Guile provides. In particular this means that a Guile mutex is not +a SRFI-18 mutex, and a Guile thread is not a SRFI-18 thread, and so on. +Guile provides a set of primitives and SRFI-18 is one of the systems built in terms of those primitives. + +@menu +* SRFI-18 Threads:: Executing code +* SRFI-18 Mutexes:: Mutual exclusion devices +* SRFI-18 Condition variables:: Synchronizing of groups of threads +* SRFI-18 Time:: Representation of times and durations +* SRFI-18 Exceptions:: Signalling and handling errors +@end menu + +@node SRFI-18 Threads +@subsubsection SRFI-18 Threads + +Threads created by SRFI-18 differ in two ways from threads created by +Guile's built-in thread functions. First, a thread created by SRFI-18 +@code{make-thread} begins in a blocked state and will not start +execution until @code{thread-start!} is called on it. Second, SRFI-18 +threads are constructed with a top-level exception handler that +captures any exceptions that are thrown on thread exit. + +SRFI-18 threads are disjoint from Guile's primitive threads. +@xref{Threads}, for more on Guile's primitive facility. + +@defun current-thread +Returns the thread that called this function. This is the same +procedure as the same-named built-in procedure @code{current-thread} +(@pxref{Threads}). +@end defun + +@defun thread? obj +Returns @code{#t} if @var{obj} is a thread, @code{#f} otherwise. This +is the same procedure as the same-named built-in procedure +@code{thread?} (@pxref{Threads}). +@end defun + +@defun make-thread thunk [name] +Call @code{thunk} in a new thread and with a new dynamic state, +returning the new thread and optionally assigning it the object name +@var{name}, which may be any Scheme object. + +Note that the name @code{make-thread} conflicts with the +@code{(ice-9 threads)} function @code{make-thread}. Applications +wanting to use both of these functions will need to refer to them by +different names. +@end defun + +@defun thread-name thread +Returns the name assigned to @var{thread} at the time of its creation, +or @code{#f} if it was not given a name. +@end defun + +@defun thread-specific thread +@defunx thread-specific-set! thread obj +Get or set the ``object-specific'' property of @var{thread}. In +Guile's implementation of SRFI-18, this value is stored as an object +property, and will be @code{#f} if not set. +@end defun + +@defun thread-start! thread +Unblocks @var{thread} and allows it to begin execution if it has not +done so already. +@end defun + +@defun thread-yield! +If one or more threads are waiting to execute, calling +@code{thread-yield!} forces an immediate context switch to one of them. +Otherwise, @code{thread-yield!} has no effect. @code{thread-yield!} +behaves identically to the Guile built-in function @code{yield}. +@end defun + +@defun thread-sleep! timeout +The current thread waits until the point specified by the time object +@var{timeout} is reached (@pxref{SRFI-18 Time}). This blocks the +thread only if @var{timeout} represents a point in the future. it is +an error for @var{timeout} to be @code{#f}. +@end defun + +@defun thread-terminate! thread +Causes an abnormal termination of @var{thread}. If @var{thread} is +not already terminated, all mutexes owned by @var{thread} become +unlocked/abandoned. If @var{thread} is the current thread, +@code{thread-terminate!} does not return. Otherwise +@code{thread-terminate!} returns an unspecified value; the termination +of @var{thread} will occur before @code{thread-terminate!} returns. +Subsequent attempts to join on @var{thread} will cause a ``terminated +thread exception'' to be raised. + +@code{thread-terminate!} is compatible with the thread cancellation +procedures in the core threads API (@pxref{Threads}) in that if a +cleanup handler has been installed for the target thread, it will be +called before the thread exits and its return value (or exception, if +any) will be stored for later retrieval via a call to +@code{thread-join!}. +@end defun + +@defun thread-join! thread [timeout [timeout-val]] +Wait for @var{thread} to terminate and return its exit value. When a +time value @var{timeout} is given, it specifies a point in time where +the waiting should be aborted. When the waiting is aborted, +@var{timeout-val} is returned if it is specified; otherwise, a +@code{join-timeout-exception} exception is raised +(@pxref{SRFI-18 Exceptions}). Exceptions may also be raised if the +thread was terminated by a call to @code{thread-terminate!} +(@code{terminated-thread-exception} will be raised) or if the thread +exited by raising an exception that was handled by the top-level +exception handler (@code{uncaught-exception} will be raised; the +original exception can be retrieved using +@code{uncaught-exception-reason}). +@end defun + + +@node SRFI-18 Mutexes +@subsubsection SRFI-18 Mutexes + +SRFI-18 mutexes are disjoint from Guile's primitive mutexes. +@xref{Mutexes and Condition Variables}, for more on Guile's primitive +facility. + +@defun make-mutex [name] +Returns a new mutex, optionally assigning it the object name @var{name}, +which may be any Scheme object. The returned mutex will be created with +the configuration described above. +@end defun + +@defun mutex-name mutex +Returns the name assigned to @var{mutex} at the time of its creation, or +@code{#f} if it was not given a name. +@end defun + +@defun mutex-specific mutex +Return the ``object-specific'' property of @var{mutex}, or @code{#f} if +none is set. +@end defun + +@defun mutex-specific-set! mutex obj +Set the ``object-specific'' property of @var{mutex}. +@end defun + +@defun mutex-state mutex +Returns information about the state of @var{mutex}. Possible values +are: +@itemize @bullet +@item +thread @var{t}: the mutex is in the locked/owned state and thread +@var{t} is the owner of the mutex +@item +symbol @code{not-owned}: the mutex is in the locked/not-owned state +@item +symbol @code{abandoned}: the mutex is in the unlocked/abandoned state +@item +symbol @code{not-abandoned}: the mutex is in the +unlocked/not-abandoned state +@end itemize +@end defun + +@defun mutex-lock! mutex [timeout [thread]] +Lock @var{mutex}, optionally specifying a time object @var{timeout} +after which to abort the lock attempt and a thread @var{thread} giving +a new owner for @var{mutex} different than the current thread. +@end defun + +@defun mutex-unlock! mutex [condition-variable [timeout]] +Unlock @var{mutex}, optionally specifying a condition variable +@var{condition-variable} on which to wait, either indefinitely or, +optionally, until the time object @var{timeout} has passed, to be +signalled. +@end defun + + +@node SRFI-18 Condition variables +@subsubsection SRFI-18 Condition variables + +SRFI-18 does not specify a ``wait'' function for condition variables. +Waiting on a condition variable can be simulated using the SRFI-18 +@code{mutex-unlock!} function described in the previous section. + +SRFI-18 condition variables are disjoint from Guile's primitive +condition variables. @xref{Mutexes and Condition Variables}, for more +on Guile's primitive facility. + +@defun condition-variable? obj +Returns @code{#t} if @var{obj} is a condition variable, @code{#f} +otherwise. +@end defun + +@defun make-condition-variable [name] +Returns a new condition variable, optionally assigning it the object +name @var{name}, which may be any Scheme object. +@end defun + +@defun condition-variable-name condition-variable +Returns the name assigned to @var{condition-variable} at the time of its +creation, or @code{#f} if it was not given a name. +@end defun + +@defun condition-variable-specific condition-variable +Return the ``object-specific'' property of @var{condition-variable}, or +@code{#f} if none is set. +@end defun + +@defun condition-variable-specific-set! condition-variable obj +Set the ``object-specific'' property of @var{condition-variable}. +@end defun + +@defun condition-variable-signal! condition-variable +@defunx condition-variable-broadcast! condition-variable +Wake up one thread that is waiting for @var{condition-variable}, in +the case of @code{condition-variable-signal!}, or all threads waiting +for it, in the case of @code{condition-variable-broadcast!}. +@end defun + + +@node SRFI-18 Time +@subsubsection SRFI-18 Time + +The SRFI-18 time functions manipulate time in two formats: a +``time object'' type that represents an absolute point in time in some +implementation-specific way; and the number of seconds since some +unspecified ``epoch''. In Guile's implementation, the epoch is the +Unix epoch, 00:00:00 UTC, January 1, 1970. + +@defun current-time +Return the current time as a time object. This procedure replaces +the procedure of the same name in the core library, which returns the +current time in seconds since the epoch. +@end defun + +@defun time? obj +Returns @code{#t} if @var{obj} is a time object, @code{#f} otherwise. +@end defun + +@defun time->seconds time +@defunx seconds->time seconds +Convert between time objects and numerical values representing the +number of seconds since the epoch. When converting from a time object +to seconds, the return value is the number of seconds between +@var{time} and the epoch. When converting from seconds to a time +object, the return value is a time object that represents a time +@var{seconds} seconds after the epoch. +@end defun + + +@node SRFI-18 Exceptions +@subsubsection SRFI-18 Exceptions + +SRFI-18 exceptions are identical to the exceptions provided by +Guile's implementation of SRFI-34. The behavior of exception +handlers invoked to handle exceptions thrown from SRFI-18 functions, +however, differs from the conventional behavior of SRFI-34 in that +the continuation of the handler is the same as that of the call to +the function. Handlers are called in a tail-recursive manner; the +exceptions do not ``bubble up''. + +@defun current-exception-handler +Returns the current exception handler. +@end defun + +@defun with-exception-handler handler thunk +Installs @var{handler} as the current exception handler and calls the +procedure @var{thunk} with no arguments, returning its value as the +value of the exception. @var{handler} must be a procedure that accepts +a single argument. The current exception handler at the time this +procedure is called will be restored after the call returns. +@end defun + +@defun raise obj +Raise @var{obj} as an exception. This is the same procedure as the +same-named procedure defined in SRFI 34. +@end defun + +@defun join-timeout-exception? obj +Returns @code{#t} if @var{obj} is an exception raised as the result of +performing a timed join on a thread that does not exit within the +specified timeout, @code{#f} otherwise. +@end defun + +@defun abandoned-mutex-exception? obj +Returns @code{#t} if @var{obj} is an exception raised as the result of +attempting to lock a mutex that has been abandoned by its owner thread, +@code{#f} otherwise. +@end defun + +@defun terminated-thread-exception? obj +Returns @code{#t} if @var{obj} is an exception raised as the result of +joining on a thread that exited as the result of a call to +@code{thread-terminate!}. +@end defun + +@defun uncaught-exception? obj +@defunx uncaught-exception-reason exc +@code{uncaught-exception?} returns @code{#t} if @var{obj} is an +exception thrown as the result of joining a thread that exited by +raising an exception that was handled by the top-level exception +handler installed by @code{make-thread}. When this occurs, the +original exception is preserved as part of the exception thrown by +@code{thread-join!} and can be accessed by calling +@code{uncaught-exception-reason} on that exception. Note that +because this exception-preservation mechanism is a side-effect of +@code{make-thread}, joining on threads that exited as described above +but were created by other means will not raise this +@code{uncaught-exception} error. +@end defun + + +@node SRFI-19 +@subsection SRFI-19 - Time/Date Library +@cindex SRFI-19 +@cindex time +@cindex date + +This is an implementation of the SRFI-19 time/date library. The +functions and variables described here are provided by + +@example +(use-modules (srfi srfi-19)) +@end example + +@menu +* SRFI-19 Introduction:: +* SRFI-19 Time:: +* SRFI-19 Date:: +* SRFI-19 Time/Date conversions:: +* SRFI-19 Date to string:: +* SRFI-19 String to date:: +@end menu + +@node SRFI-19 Introduction +@subsubsection SRFI-19 Introduction + +@cindex universal time +@cindex atomic time +@cindex UTC +@cindex TAI +This module implements time and date representations and calculations, +in various time systems, including universal time (UTC) and atomic +time (TAI). + +For those not familiar with these time systems, TAI is based on a +fixed length second derived from oscillations of certain atoms. UTC +differs from TAI by an integral number of seconds, which is increased +or decreased at announced times to keep UTC aligned to a mean solar +day (the orbit and rotation of the earth are not quite constant). + +@cindex leap second +So far, only increases in the TAI +@tex +$\leftrightarrow$ +@end tex +@ifnottex +<-> +@end ifnottex +UTC difference have been needed. Such an increase is a ``leap +second'', an extra second of TAI introduced at the end of a UTC day. +When working entirely within UTC this is never seen, every day simply +has 86400 seconds. But when converting from TAI to a UTC date, an +extra 23:59:60 is present, where normally a day would end at 23:59:59. +Effectively the UTC second from 23:59:59 to 00:00:00 has taken two TAI +seconds. + +@cindex system clock +In the current implementation, the system clock is assumed to be UTC, +and a table of leap seconds in the code converts to TAI. See comments +in @file{srfi-19.scm} for how to update this table. + +@cindex julian day +@cindex modified julian day +Also, for those not familiar with the terminology, a @dfn{Julian Day} +is a real number which is a count of days and fraction of a day, in +UTC, starting from -4713-01-01T12:00:00Z, ie.@: midday Monday 1 Jan +4713 B.C. A @dfn{Modified Julian Day} is the same, but starting from +1858-11-17T00:00:00Z, ie.@: midnight 17 November 1858 UTC. That time +is julian day 2400000.5. + +@c The SRFI-1 spec says -4714-11-24T12:00:00Z (November 24, -4714 at +@c noon, UTC), but this is incorrect. It looks like it might have +@c arisen from the code incorrectly treating years a multiple of 100 +@c but not 400 prior to 1582 as non-leap years, where instead the Julian +@c calendar should be used so all multiples of 4 before 1582 are leap +@c years. + + +@node SRFI-19 Time +@subsubsection SRFI-19 Time +@cindex time + +A @dfn{time} object has type, seconds and nanoseconds fields +representing a point in time starting from some epoch. This is an +arbitrary point in time, not just a time of day. Although times are +represented in nanoseconds, the actual resolution may be lower. + +The following variables hold the possible time types. For instance +@code{(current-time time-process)} would give the current CPU process +time. + +@defvar time-utc +Universal Coordinated Time (UTC). +@cindex UTC +@end defvar + +@defvar time-tai +International Atomic Time (TAI). +@cindex TAI +@end defvar + +@defvar time-monotonic +Monotonic time, meaning a monotonically increasing time starting from +an unspecified epoch. + +Note that in the current implementation @code{time-monotonic} is the +same as @code{time-tai}, and unfortunately is therefore affected by +adjustments to the system clock. Perhaps this will change in the +future. +@end defvar + +@defvar time-duration +A duration, meaning simply a difference between two times. +@end defvar + +@defvar time-process +CPU time spent in the current process, starting from when the process +began. +@cindex process time +@end defvar + +@defvar time-thread +CPU time spent in the current thread. Not currently implemented. +@cindex thread time +@end defvar + +@sp 1 +@defun time? obj +Return @code{#t} if @var{obj} is a time object, or @code{#f} if not. +@end defun + +@defun make-time type nanoseconds seconds +Create a time object with the given @var{type}, @var{seconds} and +@var{nanoseconds}. +@end defun + +@defun time-type time +@defunx time-nanosecond time +@defunx time-second time +@defunx set-time-type! time type +@defunx set-time-nanosecond! time nsec +@defunx set-time-second! time sec +Get or set the type, seconds or nanoseconds fields of a time object. + +@code{set-time-type!} merely changes the field, it doesn't convert the +time value. For conversions, see @ref{SRFI-19 Time/Date conversions}. +@end defun + +@defun copy-time time +Return a new time object, which is a copy of the given @var{time}. +@end defun + +@defun current-time [type] +Return the current time of the given @var{type}. The default +@var{type} is @code{time-utc}. + +Note that the name @code{current-time} conflicts with the Guile core +@code{current-time} function (@pxref{Time}) as well as the SRFI-18 +@code{current-time} function (@pxref{SRFI-18 Time}). Applications +wanting to use more than one of these functions will need to refer to +them by different names. +@end defun + +@defun time-resolution [type] +Return the resolution, in nanoseconds, of the given time @var{type}. +The default @var{type} is @code{time-utc}. +@end defun + +@defun time<=? t1 t2 +@defunx time<? t1 t2 +@defunx time=? t1 t2 +@defunx time>=? t1 t2 +@defunx time>? t1 t2 +Return @code{#t} or @code{#f} according to the respective relation +between time objects @var{t1} and @var{t2}. @var{t1} and @var{t2} +must be the same time type. +@end defun + +@defun time-difference t1 t2 +@defunx time-difference! t1 t2 +Return a time object of type @code{time-duration} representing the +period between @var{t1} and @var{t2}. @var{t1} and @var{t2} must be +the same time type. + +@code{time-difference} returns a new time object, +@code{time-difference!} may modify @var{t1} to form its return. +@end defun + +@defun add-duration time duration +@defunx add-duration! time duration +@defunx subtract-duration time duration +@defunx subtract-duration! time duration +Return a time object which is @var{time} with the given @var{duration} +added or subtracted. @var{duration} must be a time object of type +@code{time-duration}. + +@code{add-duration} and @code{subtract-duration} return a new time +object. @code{add-duration!} and @code{subtract-duration!} may modify +the given @var{time} to form their return. +@end defun + + +@node SRFI-19 Date +@subsubsection SRFI-19 Date +@cindex date + +A @dfn{date} object represents a date in the Gregorian calendar and a +time of day on that date in some timezone. + +The fields are year, month, day, hour, minute, second, nanoseconds and +timezone. A date object is immutable, its fields can be read but they +cannot be modified once the object is created. + +Historically, the Gregorian calendar was only used from the latter part +of the year 1582 onwards, and not until even later in many countries. +Prior to that most countries used the Julian calendar. SRFI-19 does +not deal with the Julian calendar at all, and so does not reflect this +historical calendar reform. Instead it projects the Gregorian calendar +back proleptically as far as necessary. When dealing with historical +data, especially prior to the British Empire's adoption of the Gregorian +calendar in 1752, one should be mindful of which calendar is used in +each context, and apply non-SRFI-19 facilities to convert where necessary. + +@defun date? obj +Return @code{#t} if @var{obj} is a date object, or @code{#f} if not. +@end defun + +@defun make-date nsecs seconds minutes hours date month year zone-offset +Create a new date object. +@c +@c FIXME: What can we say about the ranges of the values. The +@c current code looks it doesn't normalize, but expects then in their +@c usual range already. +@c +@end defun + +@defun date-nanosecond date +Nanoseconds, 0 to 999999999. +@end defun + +@defun date-second date +Seconds, 0 to 59, or 60 for a leap second. 60 is never seen when working +entirely within UTC, it's only when converting to or from TAI. +@end defun + +@defun date-minute date +Minutes, 0 to 59. +@end defun + +@defun date-hour date +Hour, 0 to 23. +@end defun + +@defun date-day date +Day of the month, 1 to 31 (or less, according to the month). +@end defun + +@defun date-month date +Month, 1 to 12. +@end defun + +@defun date-year date +Year, eg.@: 2003. Dates B.C.@: are negative, eg.@: @math{-46} is 46 +B.C. There is no year 0, year @math{-1} is followed by year 1. +@end defun + +@defun date-zone-offset date +Time zone, an integer number of seconds east of Greenwich. +@end defun + +@defun date-year-day date +Day of the year, starting from 1 for 1st January. +@end defun + +@defun date-week-day date +Day of the week, starting from 0 for Sunday. +@end defun + +@defun date-week-number date dstartw +Week of the year, ignoring a first partial week. @var{dstartw} is the +day of the week which is taken to start a week, 0 for Sunday, 1 for +Monday, etc. +@c +@c FIXME: The spec doesn't say whether numbering starts at 0 or 1. +@c The code looks like it's 0, if that's the correct intention. +@c +@end defun + +@c The SRFI text doesn't actually give the default for tz-offset, but +@c the reference implementation has the local timezone and the +@c conversions functions all specify that, so it should be ok to +@c document it here. +@c +@defun current-date [tz-offset] +Return a date object representing the current date/time, in UTC offset +by @var{tz-offset}. @var{tz-offset} is seconds east of Greenwich and +defaults to the local timezone. +@end defun + +@defun current-julian-day +@cindex julian day +Return the current Julian Day. +@end defun + +@defun current-modified-julian-day +@cindex modified julian day +Return the current Modified Julian Day. +@end defun + + +@node SRFI-19 Time/Date conversions +@subsubsection SRFI-19 Time/Date conversions +@cindex time conversion +@cindex date conversion + +@defun date->julian-day date +@defunx date->modified-julian-day date +@defunx date->time-monotonic date +@defunx date->time-tai date +@defunx date->time-utc date +@end defun +@defun julian-day->date jdn [tz-offset] +@defunx julian-day->time-monotonic jdn +@defunx julian-day->time-tai jdn +@defunx julian-day->time-utc jdn +@end defun +@defun modified-julian-day->date jdn [tz-offset] +@defunx modified-julian-day->time-monotonic jdn +@defunx modified-julian-day->time-tai jdn +@defunx modified-julian-day->time-utc jdn +@end defun +@defun time-monotonic->date time [tz-offset] +@defunx time-monotonic->time-tai time +@defunx time-monotonic->time-tai! time +@defunx time-monotonic->time-utc time +@defunx time-monotonic->time-utc! time +@end defun +@defun time-tai->date time [tz-offset] +@defunx time-tai->julian-day time +@defunx time-tai->modified-julian-day time +@defunx time-tai->time-monotonic time +@defunx time-tai->time-monotonic! time +@defunx time-tai->time-utc time +@defunx time-tai->time-utc! time +@end defun +@defun time-utc->date time [tz-offset] +@defunx time-utc->julian-day time +@defunx time-utc->modified-julian-day time +@defunx time-utc->time-monotonic time +@defunx time-utc->time-monotonic! time +@defunx time-utc->time-tai time +@defunx time-utc->time-tai! time +@sp 1 +Convert between dates, times and days of the respective types. For +instance @code{time-tai->time-utc} accepts a @var{time} object of type +@code{time-tai} and returns an object of type @code{time-utc}. + +The @code{!} variants may modify their @var{time} argument to form +their return. The plain functions create a new object. + +For conversions to dates, @var{tz-offset} is seconds east of +Greenwich. The default is the local timezone, at the given time, as +provided by the system, using @code{localtime} (@pxref{Time}). + +On 32-bit systems, @code{localtime} is limited to a 32-bit +@code{time_t}, so a default @var{tz-offset} is only available for +times between Dec 1901 and Jan 2038. For prior dates an application +might like to use the value in 1902, though some locations have zone +changes prior to that. For future dates an application might like to +assume today's rules extend indefinitely. But for correct daylight +savings transitions it will be necessary to take an offset for the +same day and time but a year in range and which has the same starting +weekday and same leap/non-leap (to support rules like last Sunday in +October). +@end defun + +@node SRFI-19 Date to string +@subsubsection SRFI-19 Date to string +@cindex date to string +@cindex string, from date + +@defun date->string date [format] +Convert a date to a string under the control of a format. +@var{format} should be a string containing @samp{~} escapes, which +will be expanded as per the following conversion table. The default +@var{format} is @samp{~c}, a locale-dependent date and time. + +Many of these conversion characters are the same as POSIX +@code{strftime} (@pxref{Time}), but there are some extras and some +variations. + +@multitable {MMMM} {MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM} +@item @nicode{~~} @tab literal ~ +@item @nicode{~a} @tab locale abbreviated weekday, eg.@: @samp{Sun} +@item @nicode{~A} @tab locale full weekday, eg.@: @samp{Sunday} +@item @nicode{~b} @tab locale abbreviated month, eg.@: @samp{Jan} +@item @nicode{~B} @tab locale full month, eg.@: @samp{January} +@item @nicode{~c} @tab locale date and time, eg.@: @* +@samp{Fri Jul 14 20:28:42-0400 2000} +@item @nicode{~d} @tab day of month, zero padded, @samp{01} to @samp{31} + +@c Spec says d/m/y, reference implementation says m/d/y. +@c Apparently the reference code was the intention, but would like to +@c see an errata published for the spec before contradicting it here. +@c +@c @item @nicode{~D} @tab date @nicode{~d/~m/~y} + +@item @nicode{~e} @tab day of month, blank padded, @samp{ 1} to @samp{31} +@item @nicode{~f} @tab seconds and fractional seconds, +with locale decimal point, eg.@: @samp{5.2} +@item @nicode{~h} @tab same as @nicode{~b} +@item @nicode{~H} @tab hour, 24-hour clock, zero padded, @samp{00} to @samp{23} +@item @nicode{~I} @tab hour, 12-hour clock, zero padded, @samp{01} to @samp{12} +@item @nicode{~j} @tab day of year, zero padded, @samp{001} to @samp{366} +@item @nicode{~k} @tab hour, 24-hour clock, blank padded, @samp{ 0} to @samp{23} +@item @nicode{~l} @tab hour, 12-hour clock, blank padded, @samp{ 1} to @samp{12} +@item @nicode{~m} @tab month, zero padded, @samp{01} to @samp{12} +@item @nicode{~M} @tab minute, zero padded, @samp{00} to @samp{59} +@item @nicode{~n} @tab newline +@item @nicode{~N} @tab nanosecond, zero padded, @samp{000000000} to @samp{999999999} +@item @nicode{~p} @tab locale AM or PM +@item @nicode{~r} @tab time, 12 hour clock, @samp{~I:~M:~S ~p} +@item @nicode{~s} @tab number of full seconds since ``the epoch'' in UTC +@item @nicode{~S} @tab second, zero padded @samp{00} to @samp{60} @* +(usual limit is 59, 60 is a leap second) +@item @nicode{~t} @tab horizontal tab character +@item @nicode{~T} @tab time, 24 hour clock, @samp{~H:~M:~S} +@item @nicode{~U} @tab week of year, Sunday first day of week, +@samp{00} to @samp{52} +@item @nicode{~V} @tab week of year, Monday first day of week, +@samp{01} to @samp{53} +@item @nicode{~w} @tab day of week, 0 for Sunday, @samp{0} to @samp{6} +@item @nicode{~W} @tab week of year, Monday first day of week, +@samp{00} to @samp{52} + +@c The spec has ~x as an apparent duplicate of ~W, and ~X as a locale +@c date. The reference code has ~x as the locale date and ~X as a +@c locale time. The rule is apparently that the code should be +@c believed, but would like to see an errata for the spec before +@c contradicting it here. +@c +@c @item @nicode{~x} @tab week of year, Monday as first day of week, +@c @samp{00} to @samp{53} +@c @item @nicode{~X} @tab locale date, eg.@: @samp{07/31/00} + +@item @nicode{~y} @tab year, two digits, @samp{00} to @samp{99} +@item @nicode{~Y} @tab year, full, eg.@: @samp{2003} +@item @nicode{~z} @tab time zone, RFC-822 style +@item @nicode{~Z} @tab time zone symbol (not currently implemented) +@item @nicode{~1} @tab ISO-8601 date, @samp{~Y-~m-~d} +@item @nicode{~2} @tab ISO-8601 time+zone, @samp{~H:~M:~S~z} +@item @nicode{~3} @tab ISO-8601 time, @samp{~H:~M:~S} +@item @nicode{~4} @tab ISO-8601 date/time+zone, @samp{~Y-~m-~dT~H:~M:~S~z} +@item @nicode{~5} @tab ISO-8601 date/time, @samp{~Y-~m-~dT~H:~M:~S} +@end multitable +@end defun + +Conversions @samp{~D}, @samp{~x} and @samp{~X} are not currently +described here, since the specification and reference implementation +differ. + +Conversion is locale-dependent on systems that support it +(@pxref{Accessing Locale Information}). @xref{Locales, +@code{setlocale}}, for information on how to change the current +locale. + + +@node SRFI-19 String to date +@subsubsection SRFI-19 String to date +@cindex string to date +@cindex date, from string + +@c FIXME: Can we say what happens when an incomplete date is +@c converted? I.e. fields left as 0, or what? The spec seems to be +@c silent on this. + +@defun string->date input template +Convert an @var{input} string to a date under the control of a +@var{template} string. Return a newly created date object. + +Literal characters in @var{template} must match characters in +@var{input} and @samp{~} escapes must match the input forms described +in the table below. ``Skip to'' means characters up to one of the +given type are ignored, or ``no skip'' for no skipping. ``Read'' is +what's then read, and ``Set'' is the field affected in the date +object. + +For example @samp{~Y} skips input characters until a digit is reached, +at which point it expects a year and stores that to the year field of +the date. + +@multitable {MMMM} {@nicode{char-alphabetic?}} {MMMMMMMMMMMMMMMMMMMMMMMMM} {@nicode{date-zone-offset}} +@item +@tab Skip to +@tab Read +@tab Set + +@item @nicode{~~} +@tab no skip +@tab literal ~ +@tab nothing + +@item @nicode{~a} +@tab @nicode{char-alphabetic?} +@tab locale abbreviated weekday name +@tab nothing + +@item @nicode{~A} +@tab @nicode{char-alphabetic?} +@tab locale full weekday name +@tab nothing + +@c Note that the SRFI spec says that ~b and ~B don't set anything, +@c but that looks like a mistake. The reference implementation sets +@c the month field, which seems sensible and is what we describe +@c here. + +@item @nicode{~b} +@tab @nicode{char-alphabetic?} +@tab locale abbreviated month name +@tab @nicode{date-month} + +@item @nicode{~B} +@tab @nicode{char-alphabetic?} +@tab locale full month name +@tab @nicode{date-month} + +@item @nicode{~d} +@tab @nicode{char-numeric?} +@tab day of month +@tab @nicode{date-day} + +@item @nicode{~e} +@tab no skip +@tab day of month, blank padded +@tab @nicode{date-day} + +@item @nicode{~h} +@tab same as @samp{~b} + +@item @nicode{~H} +@tab @nicode{char-numeric?} +@tab hour +@tab @nicode{date-hour} + +@item @nicode{~k} +@tab no skip +@tab hour, blank padded +@tab @nicode{date-hour} + +@item @nicode{~m} +@tab @nicode{char-numeric?} +@tab month +@tab @nicode{date-month} + +@item @nicode{~M} +@tab @nicode{char-numeric?} +@tab minute +@tab @nicode{date-minute} + +@item @nicode{~S} +@tab @nicode{char-numeric?} +@tab second +@tab @nicode{date-second} + +@item @nicode{~y} +@tab no skip +@tab 2-digit year +@tab @nicode{date-year} within 50 years + +@item @nicode{~Y} +@tab @nicode{char-numeric?} +@tab year +@tab @nicode{date-year} + +@item @nicode{~z} +@tab no skip +@tab time zone +@tab date-zone-offset +@end multitable + +Notice that the weekday matching forms don't affect the date object +returned, instead the weekday will be derived from the day, month and +year. + +Conversion is locale-dependent on systems that support it +(@pxref{Accessing Locale Information}). @xref{Locales, +@code{setlocale}}, for information on how to change the current +locale. +@end defun + +@node SRFI-23 +@subsection SRFI-23 - Error Reporting +@cindex SRFI-23 + +The SRFI-23 @code{error} procedure is always available. + +@node SRFI-26 +@subsection SRFI-26 - specializing parameters +@cindex SRFI-26 +@cindex parameter specialize +@cindex argument specialize +@cindex specialize parameter + +This SRFI provides a syntax for conveniently specializing selected +parameters of a function. It can be used with, + +@example +(use-modules (srfi srfi-26)) +@end example + +@deffn {library syntax} cut slot1 slot2 @dots{} +@deffnx {library syntax} cute slot1 slot2 @dots{} +Return a new procedure which will make a call (@var{slot1} @var{slot2} +@dots{}) but with selected parameters specialized to given expressions. + +An example will illustrate the idea. The following is a +specialization of @code{write}, sending output to +@code{my-output-port}, + +@example +(cut write <> my-output-port) +@result{} +(lambda (obj) (write obj my-output-port)) +@end example + +The special symbol @code{<>} indicates a slot to be filled by an +argument to the new procedure. @code{my-output-port} on the other +hand is an expression to be evaluated and passed, ie.@: it specializes +the behaviour of @code{write}. + +@table @nicode +@item <> +A slot to be filled by an argument from the created procedure. +Arguments are assigned to @code{<>} slots in the order they appear in +the @code{cut} form, there's no way to re-arrange arguments. + +The first argument to @code{cut} is usually a procedure (or expression +giving a procedure), but @code{<>} is allowed there too. For example, + +@example +(cut <> 1 2 3) +@result{} +(lambda (proc) (proc 1 2 3)) +@end example + +@item <...> +A slot to be filled by all remaining arguments from the new procedure. +This can only occur at the end of a @code{cut} form. + +For example, a procedure taking a variable number of arguments like +@code{max} but in addition enforcing a lower bound, + +@example +(define my-lower-bound 123) + +(cut max my-lower-bound <...>) +@result{} +(lambda arglist (apply max my-lower-bound arglist)) +@end example +@end table + +For @code{cut} the specializing expressions are evaluated each time +the new procedure is called. For @code{cute} they're evaluated just +once, when the new procedure is created. The name @code{cute} stands +for ``@code{cut} with evaluated arguments''. In all cases the +evaluations take place in an unspecified order. + +The following illustrates the difference between @code{cut} and +@code{cute}, + +@example +(cut format <> "the time is ~s" (current-time)) +@result{} +(lambda (port) (format port "the time is ~s" (current-time))) + +(cute format <> "the time is ~s" (current-time)) +@result{} +(let ((val (current-time))) + (lambda (port) (format port "the time is ~s" val)) +@end example + +(There's no provision for a mixture of @code{cut} and @code{cute} +where some expressions would be evaluated every time but others +evaluated only once.) + +@code{cut} is really just a shorthand for the sort of @code{lambda} +forms shown in the above examples. But notice @code{cut} avoids the +need to name unspecialized parameters, and is more compact. Use in +functional programming style or just with @code{map}, @code{for-each} +or similar is typical. + +@example +(map (cut * 2 <>) '(1 2 3 4)) + +(for-each (cut write <> my-port) my-list) +@end example +@end deffn + +@node SRFI-27 +@subsection SRFI-27 - Sources of Random Bits +@cindex SRFI-27 + +This subsection is based on the +@uref{http://srfi.schemers.org/srfi-27/srfi-27.html, specification of +SRFI-27} written by Sebastian Egner. + +@c The copyright notice and license text of the SRFI-27 specification is +@c reproduced below: + +@c Copyright (C) Sebastian Egner (2002). All Rights Reserved. + +@c Permission is hereby granted, free of charge, to any person obtaining a +@c copy of this software and associated documentation files (the +@c "Software"), to deal in the Software without restriction, including +@c without limitation the rights to use, copy, modify, merge, publish, +@c distribute, sublicense, and/or sell copies of the Software, and to +@c permit persons to whom the Software is furnished to do so, subject to +@c the following conditions: + +@c The above copyright notice and this permission notice shall be included +@c in all copies or substantial portions of the Software. + +@c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +@c OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +@c MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@c NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +@c LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +@c OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +@c WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This SRFI provides access to a (pseudo) random number generator; for +Guile's built-in random number facilities, which SRFI-27 is implemented +upon, @xref{Random}. With SRFI-27, random numbers are obtained from a +@emph{random source}, which encapsulates a random number generation +algorithm and its state. + +@menu +* SRFI-27 Default Random Source:: Obtaining random numbers +* SRFI-27 Random Sources:: Creating and manipulating random sources +* SRFI-27 Random Number Generators:: Obtaining random number generators +@end menu + +@node SRFI-27 Default Random Source +@subsubsection The Default Random Source +@cindex SRFI-27 + +@defun random-integer n +Return a random number between zero (inclusive) and @var{n} (exclusive), +using the default random source. The numbers returned have a uniform +distribution. +@end defun + +@defun random-real +Return a random number in (0,1), using the default random source. The +numbers returned have a uniform distribution. +@end defun + +@defun default-random-source +A random source from which @code{random-integer} and @code{random-real} +have been derived using @code{random-source-make-integers} and +@code{random-source-make-reals} (@pxref{SRFI-27 Random Number Generators} +for those procedures). Note that an assignment to +@code{default-random-source} does not change @code{random-integer} or +@code{random-real}; it is also strongly recommended not to assign a new +value. +@end defun + +@node SRFI-27 Random Sources +@subsubsection Random Sources +@cindex SRFI-27 + +@defun make-random-source +Create a new random source. The stream of random numbers obtained from +each random source created by this procedure will be identical, unless +its state is changed by one of the procedures below. +@end defun + +@defun random-source? object +Tests whether @var{object} is a random source. Random sources are a +disjoint type. +@end defun + +@defun random-source-randomize! source +Attempt to set the state of the random source to a truly random value. +The current implementation uses a seed based on the current system time. +@end defun + +@defun random-source-pseudo-randomize! source i j +Changes the state of the random source s into the initial state of the +(@var{i}, @var{j})-th independent random source, where @var{i} and +@var{j} are non-negative integers. This procedure provides a mechanism +to obtain a large number of independent random sources (usually all +derived from the same backbone generator), indexed by two integers. In +contrast to @code{random-source-randomize!}, this procedure is entirely +deterministic. +@end defun + +The state associated with a random state can be obtained an reinstated +with the following procedures: + +@defun random-source-state-ref source +@defunx random-source-state-set! source state +Get and set the state of a random source. No assumptions should be made +about the nature of the state object, besides it having an external +representation (i.e.@: it can be passed to @code{write} and subsequently +@code{read} back). +@end defun + +@node SRFI-27 Random Number Generators +@subsubsection Obtaining random number generator procedures +@cindex SRFI-27 + +@defun random-source-make-integers source +Obtains a procedure to generate random integers using the random source +@var{source}. The returned procedure takes a single argument @var{n}, +which must be a positive integer, and returns the next uniformly +distributed random integer from the interval @{0, ..., @var{n}-1@} by +advancing the state of @var{source}. + +If an application obtains and uses several generators for the same +random source @var{source}, a call to any of these generators advances +the state of @var{source}. Hence, the generators do not produce the +same sequence of random integers each but rather share a state. This +also holds for all other types of generators derived from a fixed random +sources. + +While the SRFI text specifies that ``Implementations that support +concurrency make sure that the state of a generator is properly +advanced'', this is currently not the case in Guile's implementation of +SRFI-27, as it would cause a severe performance penalty. So in +multi-threaded programs, you either must perform locking on random +sources shared between threads yourself, or use different random sources +for multiple threads. +@end defun + +@defun random-source-make-reals source +@defunx random-source-make-reals source unit +Obtains a procedure to generate random real numbers @math{0 < x < 1} +using the random source @var{source}. The procedure rand is called +without arguments. + +The optional parameter @var{unit} determines the type of numbers being +produced by the returned procedure and the quantization of the output. +@var{unit} must be a number such that @math{0 < @var{unit} < 1}. The +numbers created by the returned procedure are of the same numerical type +as @var{unit} and the potential output values are spaced by at most +@var{unit}. One can imagine rand to create numbers as @var{x} * +@var{unit} where @var{x} is a random integer in @{1, ..., +floor(1/unit)-1@}. Note, however, that this need not be the way the +values are actually created and that the actual resolution of rand can +be much higher than unit. In case @var{unit} is absent it defaults to a +reasonably small value (related to the width of the mantissa of an +efficient number format). +@end defun + +@node SRFI-28 +@subsection SRFI-28 - Basic Format Strings +@cindex SRFI-28 + +SRFI-28 provides a basic @code{format} procedure that provides only +the @code{~a}, @code{~s}, @code{~%}, and @code{~~} format specifiers. +You can import this procedure by using: + +@lisp +(use-modules (srfi srfi-28)) +@end lisp + +@deffn {Scheme Procedure} format message arg @dots{} +Returns a formatted message, using @var{message} as the format string, +which can contain the following format specifiers: + +@table @code +@item ~a +Insert the textual representation of the next @var{arg}, as if printed +by @code{display}. + +@item ~s +Insert the textual representation of the next @var{arg}, as if printed +by @code{write}. + +@item ~% +Insert a newline. + +@item ~~ +Insert a tilde. +@end table + +This procedure is the same as calling @code{simple-format} +(@pxref{Simple Output}) with @code{#f} as the destination. +@end deffn + +@node SRFI-30 +@subsection SRFI-30 - Nested Multi-line Comments +@cindex SRFI-30 + +Starting from version 2.0, Guile's @code{read} supports SRFI-30/R6RS +nested multi-line comments by default, @ref{Block Comments}. + +@node SRFI-31 +@subsection SRFI-31 - A special form `rec' for recursive evaluation +@cindex SRFI-31 +@cindex recursive expression +@findex rec + +SRFI-31 defines a special form that can be used to create +self-referential expressions more conveniently. The syntax is as +follows: + +@example +@group +<rec expression> --> (rec <variable> <expression>) +<rec expression> --> (rec (<variable>+) <body>) +@end group +@end example + +The first syntax can be used to create self-referential expressions, +for example: + +@lisp + guile> (define tmp (rec ones (cons 1 (delay ones)))) +@end lisp + +The second syntax can be used to create anonymous recursive functions: + +@lisp + guile> (define tmp (rec (display-n item n) + (if (positive? n) + (begin (display n) (display-n (- n 1)))))) + guile> (tmp 42 3) + 424242 + guile> +@end lisp + + +@node SRFI-34 +@subsection SRFI-34 - Exception handling for programs + +@cindex SRFI-34 +Guile provides an implementation of +@uref{http://srfi.schemers.org/srfi-34/srfi-34.html, SRFI-34's exception +handling mechanisms} as an alternative to its own built-in mechanisms +(@pxref{Exceptions}). It can be made available as follows: + +@lisp +(use-modules (srfi srfi-34)) +@end lisp + +@c FIXME: Document it. + + +@node SRFI-35 +@subsection SRFI-35 - Conditions + +@cindex SRFI-35 +@cindex conditions +@cindex exceptions + +@uref{http://srfi.schemers.org/srfi-35/srfi-35.html, SRFI-35} implements +@dfn{conditions}, a data structure akin to records designed to convey +information about exceptional conditions between parts of a program. It +is normally used in conjunction with SRFI-34's @code{raise}: + +@lisp +(raise (condition (&message + (message "An error occurred")))) +@end lisp + +Users can define @dfn{condition types} containing arbitrary information. +Condition types may inherit from one another. This allows the part of +the program that handles (or ``catches'') conditions to get accurate +information about the exceptional condition that arose. + +SRFI-35 conditions are made available using: + +@lisp +(use-modules (srfi srfi-35)) +@end lisp + +The procedures available to manipulate condition types are the +following: + +@deffn {Scheme Procedure} make-condition-type id parent field-names +Return a new condition type named @var{id}, inheriting from +@var{parent}, and with the fields whose names are listed in +@var{field-names}. @var{field-names} must be a list of symbols and must +not contain names already used by @var{parent} or one of its supertypes. +@end deffn + +@deffn {Scheme Procedure} condition-type? obj +Return true if @var{obj} is a condition type. +@end deffn + +Conditions can be created and accessed with the following procedures: + +@deffn {Scheme Procedure} make-condition type . field+value +Return a new condition of type @var{type} with fields initialized as +specified by @var{field+value}, a sequence of field names (symbols) and +values as in the following example: + +@lisp +(let ((&ct (make-condition-type 'foo &condition '(a b c)))) + (make-condition &ct 'a 1 'b 2 'c 3)) +@end lisp + +Note that all fields of @var{type} and its supertypes must be specified. +@end deffn + +@deffn {Scheme Procedure} make-compound-condition condition1 condition2 @dots{} +Return a new compound condition composed of @var{condition1} +@var{condition2} @enddots{}. The returned condition has the type of +each condition of condition1 condition2 @dots{} (per +@code{condition-has-type?}). +@end deffn + +@deffn {Scheme Procedure} condition-has-type? c type +Return true if condition @var{c} has type @var{type}. +@end deffn + +@deffn {Scheme Procedure} condition-ref c field-name +Return the value of the field named @var{field-name} from condition @var{c}. + +If @var{c} is a compound condition and several underlying condition +types contain a field named @var{field-name}, then the value of the +first such field is returned, using the order in which conditions were +passed to @code{make-compound-condition}. +@end deffn + +@deffn {Scheme Procedure} extract-condition c type +Return a condition of condition type @var{type} with the field values +specified by @var{c}. + +If @var{c} is a compound condition, extract the field values from the +subcondition belonging to @var{type} that appeared first in the call to +@code{make-compound-condition} that created the condition. +@end deffn + +Convenience macros are also available to create condition types and +conditions. + +@deffn {library syntax} define-condition-type type supertype predicate field-spec... +Define a new condition type named @var{type} that inherits from +@var{supertype}. In addition, bind @var{predicate} to a type predicate +that returns true when passed a condition of type @var{type} or any of +its subtypes. @var{field-spec} must have the form @code{(field +accessor)} where @var{field} is the name of field of @var{type} and +@var{accessor} is the name of a procedure to access field @var{field} in +conditions of type @var{type}. + +The example below defines condition type @code{&foo}, inheriting from +@code{&condition} with fields @code{a}, @code{b} and @code{c}: + +@lisp +(define-condition-type &foo &condition + foo-condition? + (a foo-a) + (b foo-b) + (c foo-c)) +@end lisp +@end deffn + +@deffn {library syntax} condition type-field-binding1 type-field-binding2 @dots{} +Return a new condition or compound condition, initialized according to +@var{type-field-binding1} @var{type-field-binding2} @enddots{}. Each +@var{type-field-binding} must have the form @code{(type +field-specs...)}, where @var{type} is the name of a variable bound to a +condition type; each @var{field-spec} must have the form +@code{(field-name value)} where @var{field-name} is a symbol denoting +the field being initialized to @var{value}. As for +@code{make-condition}, all fields must be specified. + +The following example returns a simple condition: + +@lisp +(condition (&message (message "An error occurred"))) +@end lisp + +The one below returns a compound condition: + +@lisp +(condition (&message (message "An error occurred")) + (&serious)) +@end lisp +@end deffn + +Finally, SRFI-35 defines a several standard condition types. + +@defvar &condition +This condition type is the root of all condition types. It has no +fields. +@end defvar + +@defvar &message +A condition type that carries a message describing the nature of the +condition to humans. +@end defvar + +@deffn {Scheme Procedure} message-condition? c +Return true if @var{c} is of type @code{&message} or one of its +subtypes. +@end deffn + +@deffn {Scheme Procedure} condition-message c +Return the message associated with message condition @var{c}. +@end deffn + +@defvar &serious +This type describes conditions serious enough that they cannot safely be +ignored. It has no fields. +@end defvar + +@deffn {Scheme Procedure} serious-condition? c +Return true if @var{c} is of type @code{&serious} or one of its +subtypes. +@end deffn + +@defvar &error +This condition describes errors, typically caused by something that has +gone wrong in the interaction of the program with the external world or +the user. +@end defvar + +@deffn {Scheme Procedure} error? c +Return true if @var{c} is of type @code{&error} or one of its subtypes. +@end deffn + +@node SRFI-37 +@subsection SRFI-37 - args-fold +@cindex SRFI-37 + +This is a processor for GNU @code{getopt_long}-style program +arguments. It provides an alternative, less declarative interface +than @code{getopt-long} in @code{(ice-9 getopt-long)} +(@pxref{getopt-long,,The (ice-9 getopt-long) Module}). Unlike +@code{getopt-long}, it supports repeated options and any number of +short and long names per option. Access it with: + +@lisp +(use-modules (srfi srfi-37)) +@end lisp + +@acronym{SRFI}-37 principally provides an @code{option} type and the +@code{args-fold} function. To use the library, create a set of +options with @code{option} and use it as a specification for invoking +@code{args-fold}. + +Here is an example of a simple argument processor for the typical +@samp{--version} and @samp{--help} options, which returns a backwards +list of files given on the command line: + +@lisp +(args-fold (cdr (program-arguments)) + (let ((display-and-exit-proc + (lambda (msg) + (lambda (opt name arg loads) + (display msg) (quit))))) + (list (option '(#\v "version") #f #f + (display-and-exit-proc "Foo version 42.0\n")) + (option '(#\h "help") #f #f + (display-and-exit-proc + "Usage: foo scheme-file ...")))) + (lambda (opt name arg loads) + (error "Unrecognized option `~A'" name)) + (lambda (op loads) (cons op loads)) + '()) +@end lisp + +@deffn {Scheme Procedure} option names required-arg? optional-arg? processor +Return an object that specifies a single kind of program option. + +@var{names} is a list of command-line option names, and should consist of +characters for traditional @code{getopt} short options and strings for +@code{getopt_long}-style long options. + +@var{required-arg?} and @var{optional-arg?} are mutually exclusive; +one or both must be @code{#f}. If @var{required-arg?}, the option +must be followed by an argument on the command line, such as +@samp{--opt=value} for long options, or an error will be signalled. +If @var{optional-arg?}, an argument will be taken if available. + +@var{processor} is a procedure that takes at least 3 arguments, called +when @code{args-fold} encounters the option: the containing option +object, the name used on the command line, and the argument given for +the option (or @code{#f} if none). The rest of the arguments are +@code{args-fold} ``seeds'', and the @var{processor} should return +seeds as well. +@end deffn + +@deffn {Scheme Procedure} option-names opt +@deffnx {Scheme Procedure} option-required-arg? opt +@deffnx {Scheme Procedure} option-optional-arg? opt +@deffnx {Scheme Procedure} option-processor opt +Return the specified field of @var{opt}, an option object, as +described above for @code{option}. +@end deffn + +@deffn {Scheme Procedure} args-fold args options unrecognized-option-proc operand-proc seed @dots{} +Process @var{args}, a list of program arguments such as that returned by +@code{(cdr (program-arguments))}, in order against @var{options}, a list +of option objects as described above. All functions called take the +``seeds'', or the last multiple-values as multiple arguments, starting +with @var{seed} @dots{}, and must return the new seeds. Return the +final seeds. + +Call @code{unrecognized-option-proc}, which is like an option object's +processor, for any options not found in @var{options}. + +Call @code{operand-proc} with any items on the command line that are +not named options. This includes arguments after @samp{--}. It is +called with the argument in question, as well as the seeds. +@end deffn + +@node SRFI-38 +@subsection SRFI-38 - External Representation for Data With Shared Structure +@cindex SRFI-38 + +This subsection is based on +@uref{http://srfi.schemers.org/srfi-38/srfi-38.html, the specification +of SRFI-38} written by Ray Dillinger. + +@c Copyright (C) Ray Dillinger 2003. All Rights Reserved. + +@c Permission is hereby granted, free of charge, to any person obtaining a +@c copy of this software and associated documentation files (the +@c "Software"), to deal in the Software without restriction, including +@c without limitation the rights to use, copy, modify, merge, publish, +@c distribute, sublicense, and/or sell copies of the Software, and to +@c permit persons to whom the Software is furnished to do so, subject to +@c the following conditions: + +@c The above copyright notice and this permission notice shall be included +@c in all copies or substantial portions of the Software. + +@c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +@c OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +@c MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@c NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +@c LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +@c OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +@c WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This SRFI creates an alternative external representation for data +written and read using @code{write-with-shared-structure} and +@code{read-with-shared-structure}. It is identical to the grammar for +external representation for data written and read with @code{write} and +@code{read} given in section 7 of R5RS, except that the single +production + +@example +<datum> --> <simple datum> | <compound datum> +@end example + +is replaced by the following five productions: + +@example +<datum> --> <defining datum> | <nondefining datum> | <defined datum> +<defining datum> --> #<indexnum>=<nondefining datum> +<defined datum> --> #<indexnum># +<nondefining datum> --> <simple datum> | <compound datum> +<indexnum> --> <digit 10>+ +@end example + +@deffn {Scheme procedure} write-with-shared-structure obj +@deffnx {Scheme procedure} write-with-shared-structure obj port +@deffnx {Scheme procedure} write-with-shared-structure obj port optarg + +Writes an external representation of @var{obj} to the given port. +Strings that appear in the written representation are enclosed in +doublequotes, and within those strings backslash and doublequote +characters are escaped by backslashes. Character objects are written +using the @code{#\} notation. + +Objects which denote locations rather than values (cons cells, vectors, +and non-zero-length strings in R5RS scheme; also Guile's structs, +bytevectors and ports and hash-tables), if they appear at more than one +point in the data being written, are preceded by @samp{#@var{N}=} the +first time they are written and replaced by @samp{#@var{N}#} all +subsequent times they are written, where @var{N} is a natural number +used to identify that particular object. If objects which denote +locations occur only once in the structure, then +@code{write-with-shared-structure} must produce the same external +representation for those objects as @code{write}. + +@code{write-with-shared-structure} terminates in finite time and +produces a finite representation when writing finite data. + +@code{write-with-shared-structure} returns an unspecified value. The +@var{port} argument may be omitted, in which case it defaults to the +value returned by @code{(current-output-port)}. The @var{optarg} +argument may also be omitted. If present, its effects on the output and +return value are unspecified but @code{write-with-shared-structure} must +still write a representation that can be read by +@code{read-with-shared-structure}. Some implementations may wish to use +@var{optarg} to specify formatting conventions, numeric radixes, or +return values. Guile's implementation ignores @var{optarg}. + +For example, the code + +@lisp +(begin (define a (cons 'val1 'val2)) + (set-cdr! a a) + (write-with-shared-structure a)) +@end lisp + +should produce the output @code{#1=(val1 . #1#)}. This shows a cons +cell whose @code{cdr} contains itself. + +@end deffn + +@deffn {Scheme procedure} read-with-shared-structure +@deffnx {Scheme procedure} read-with-shared-structure port + +@code{read-with-shared-structure} converts the external representations +of Scheme objects produced by @code{write-with-shared-structure} into +Scheme objects. That is, it is a parser for the nonterminal +@samp{<datum>} in the augmented external representation grammar defined +above. @code{read-with-shared-structure} returns the next object +parsable from the given input port, updating @var{port} to point to the +first character past the end of the external representation of the +object. + +If an end-of-file is encountered in the input before any characters are +found that can begin an object, then an end-of-file object is returned. +The port remains open, and further attempts to read it (by +@code{read-with-shared-structure} or @code{read} will also return an +end-of-file object. If an end of file is encountered after the +beginning of an object's external representation, but the external +representation is incomplete and therefore not parsable, an error is +signalled. + +The @var{port} argument may be omitted, in which case it defaults to the +value returned by @code{(current-input-port)}. It is an error to read +from a closed port. + +@end deffn + +@node SRFI-39 +@subsection SRFI-39 - Parameters +@cindex SRFI-39 + +This SRFI adds support for dynamically-scoped parameters. SRFI 39 is +implemented in the Guile core; there's no module needed to get SRFI-39 +itself. Parameters are documented in @ref{Parameters}. + +This module does export one extra function: @code{with-parameters*}. +This is a Guile-specific addition to the SRFI, similar to the core +@code{with-fluids*} (@pxref{Fluids and Dynamic States}). + +@defun with-parameters* param-list value-list thunk +Establish a new dynamic scope, as per @code{parameterize} above, +taking parameters from @var{param-list} and corresponding values from +@var{value-list}. A call @code{(@var{thunk})} is made in the new +scope and the result from that @var{thunk} is the return from +@code{with-parameters*}. +@end defun + +@node SRFI-41 +@subsection SRFI-41 - Streams +@cindex SRFI-41 + +This subsection is based on the +@uref{http://srfi.schemers.org/srfi-41/srfi-41.html, specification of +SRFI-41} by Philip L.@: Bewig. + +@c The copyright notice and license text of the SRFI-41 specification is +@c reproduced below: + +@c Copyright (C) Philip L. Bewig (2007). All Rights Reserved. + +@c Permission is hereby granted, free of charge, to any person obtaining a +@c copy of this software and associated documentation files (the +@c "Software"), to deal in the Software without restriction, including +@c without limitation the rights to use, copy, modify, merge, publish, +@c distribute, sublicense, and/or sell copies of the Software, and to +@c permit persons to whom the Software is furnished to do so, subject to +@c the following conditions: + +@c The above copyright notice and this permission notice shall be included +@c in all copies or substantial portions of the Software. + +@c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +@c OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +@c MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@c NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +@c LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +@c OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +@c WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@noindent +This SRFI implements streams, sometimes called lazy lists, a sequential +data structure containing elements computed only on demand. A stream is +either null or is a pair with a stream in its cdr. Since elements of a +stream are computed only when accessed, streams can be infinite. Once +computed, the value of a stream element is cached in case it is needed +again. SRFI-41 can be made available with: + +@example +(use-modules (srfi srfi-41)) +@end example + +@menu +* SRFI-41 Stream Fundamentals:: +* SRFI-41 Stream Primitives:: +* SRFI-41 Stream Library:: +@end menu + +@node SRFI-41 Stream Fundamentals +@subsubsection SRFI-41 Stream Fundamentals + +SRFI-41 Streams are based on two mutually-recursive abstract data types: +An object of the @code{stream} abstract data type is a promise that, +when forced, is either @code{stream-null} or is an object of type +@code{stream-pair}. An object of the @code{stream-pair} abstract data +type contains a @code{stream-car} and a @code{stream-cdr}, which must be +a @code{stream}. The essential feature of streams is the systematic +suspensions of the recursive promises between the two data types. + +The object stored in the @code{stream-car} of a @code{stream-pair} is a +promise that is forced the first time the @code{stream-car} is accessed; +its value is cached in case it is needed again. The object may have any +type, and different stream elements may have different types. If the +@code{stream-car} is never accessed, the object stored there is never +evaluated. Likewise, the @code{stream-cdr} is a promise to return a +stream, and is only forced on demand. + +@node SRFI-41 Stream Primitives +@subsubsection SRFI-41 Stream Primitives + +This library provides eight operators: constructors for +@code{stream-null} and @code{stream-pair}s, type predicates for streams +and the two kinds of streams, accessors for both fields of a +@code{stream-pair}, and a lambda that creates procedures that return +streams. + +@defvr {Scheme Variable} stream-null +A promise that, when forced, is a single object, distinguishable from +all other objects, that represents the null stream. @code{stream-null} +is immutable and unique. +@end defvr + +@deffn {Scheme Syntax} stream-cons object-expr stream-expr +Creates a newly-allocated stream containing a promise that, when forced, +is a @code{stream-pair} with @var{object-expr} in its @code{stream-car} +and @var{stream-expr} in its @code{stream-cdr}. Neither +@var{object-expr} nor @var{stream-expr} is evaluated when +@code{stream-cons} is called. + +Once created, a @code{stream-pair} is immutable; there is no +@code{stream-set-car!} or @code{stream-set-cdr!} that modifies an +existing stream-pair. There is no dotted-pair or improper stream as +with lists. +@end deffn + +@deffn {Scheme Procedure} stream? object +Returns true if @var{object} is a stream, otherwise returns false. If +@var{object} is a stream, its promise will not be forced. If +@code{(stream? obj)} returns true, then one of @code{(stream-null? obj)} +or @code{(stream-pair? obj)} will return true and the other will return +false. +@end deffn + +@deffn {Scheme Procedure} stream-null? object +Returns true if @var{object} is the distinguished null stream, otherwise +returns false. If @var{object} is a stream, its promise will be forced. +@end deffn + +@deffn {Scheme Procedure} stream-pair? object +Returns true if @var{object} is a @code{stream-pair} constructed by +@code{stream-cons}, otherwise returns false. If @var{object} is a +stream, its promise will be forced. +@end deffn + +@deffn {Scheme Procedure} stream-car stream +Returns the object stored in the @code{stream-car} of @var{stream}. An +error is signalled if the argument is not a @code{stream-pair}. This +causes the @var{object-expr} passed to @code{stream-cons} to be +evaluated if it had not yet been; the value is cached in case it is +needed again. +@end deffn + +@deffn {Scheme Procedure} stream-cdr stream +Returns the stream stored in the @code{stream-cdr} of @var{stream}. An +error is signalled if the argument is not a @code{stream-pair}. +@end deffn + +@deffn {Scheme Syntax} stream-lambda formals body @dots{} +Creates a procedure that returns a promise to evaluate the @var{body} of +the procedure. The last @var{body} expression to be evaluated must +yield a stream. As with normal @code{lambda}, @var{formals} may be a +single variable name, in which case all the formal arguments are +collected into a single list, or a list of variable names, which may be +null if there are no arguments, proper if there are an exact number of +arguments, or dotted if a fixed number of arguments is to be followed by +zero or more arguments collected into a list. @var{Body} must contain +at least one expression, and may contain internal definitions preceding +any expressions to be evaluated. +@end deffn + +@example +(define strm123 + (stream-cons 1 + (stream-cons 2 + (stream-cons 3 + stream-null)))) + +(stream-car strm123) @result{} 1 +(stream-car (stream-cdr strm123) @result{} 2 + +(stream-pair? + (stream-cdr + (stream-cons (/ 1 0) stream-null))) @result{} #f + +(stream? (list 1 2 3)) @result{} #f + +(define iter + (stream-lambda (f x) + (stream-cons x (iter f (f x))))) + +(define nats (iter (lambda (x) (+ x 1)) 0)) + +(stream-car (stream-cdr nats)) @result{} 1 + +(define stream-add + (stream-lambda (s1 s2) + (stream-cons + (+ (stream-car s1) (stream-car s2)) + (stream-add (stream-cdr s1) + (stream-cdr s2))))) + +(define evens (stream-add nats nats)) + +(stream-car evens) @result{} 0 +(stream-car (stream-cdr evens)) @result{} 2 +(stream-car (stream-cdr (stream-cdr evens))) @result{} 4 +@end example + +@node SRFI-41 Stream Library +@subsubsection SRFI-41 Stream Library + +@deffn {Scheme Syntax} define-stream (name args @dots{}) body @dots{} +Creates a procedure that returns a stream, and may appear anywhere a +normal @code{define} may appear, including as an internal definition. +It may contain internal definitions of its own. The defined procedure +takes arguments in the same way as @code{stream-lambda}. +@code{define-stream} is syntactic sugar on @code{stream-lambda}; see +also @code{stream-let}, which is also a sugaring of +@code{stream-lambda}. + +A simple version of @code{stream-map} that takes only a single input +stream calls itself recursively: + +@example +(define-stream (stream-map proc strm) + (if (stream-null? strm) + stream-null + (stream-cons + (proc (stream-car strm)) + (stream-map proc (stream-cdr strm)))))) +@end example +@end deffn + +@deffn {Scheme Procedure} list->stream list +Returns a newly-allocated stream containing the elements from +@var{list}. +@end deffn + +@deffn {Scheme Procedure} port->stream [port] +Returns a newly-allocated stream containing in its elements the +characters on the port. If @var{port} is not given it defaults to the +current input port. The returned stream has finite length and is +terminated by @code{stream-null}. + +It looks like one use of @code{port->stream} would be this: + +@example +(define s ;wrong! + (with-input-from-file filename + (lambda () (port->stream)))) +@end example + +But that fails, because @code{with-input-from-file} is eager, and closes +the input port prematurely, before the first character is read. To read +a file into a stream, say: + +@example +(define-stream (file->stream filename) + (let ((p (open-input-file filename))) + (stream-let loop ((c (read-char p))) + (if (eof-object? c) + (begin (close-input-port p) + stream-null) + (stream-cons c + (loop (read-char p))))))) +@end example +@end deffn + +@deffn {Scheme Syntax} stream object-expr @dots{} +Creates a newly-allocated stream containing in its elements the objects, +in order. The @var{object-expr}s are evaluated when they are accessed, +not when the stream is created. If no objects are given, as in +(stream), the null stream is returned. See also @code{list->stream}. + +@example +(define strm123 (stream 1 2 3)) + +; (/ 1 0) not evaluated when stream is created +(define s (stream 1 (/ 1 0) -1)) +@end example +@end deffn + +@deffn {Scheme Procedure} stream->list [n] stream +Returns a newly-allocated list containing in its elements the first +@var{n} items in @var{stream}. If @var{stream} has less than @var{n} +items, all the items in the stream will be included in the returned +list. If @var{n} is not given it defaults to infinity, which means that +unless @var{stream} is finite @code{stream->list} will never return. + +@example +(stream->list 10 + (stream-map (lambda (x) (* x x)) + (stream-from 0))) + @result{} (0 1 4 9 16 25 36 49 64 81) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-append stream @dots{} +Returns a newly-allocated stream containing in its elements those +elements contained in its input @var{stream}s, in order of input. If +any of the input streams is infinite, no elements of any of the +succeeding input streams will appear in the output stream. See also +@code{stream-concat}. +@end deffn + +@deffn {Scheme Procedure} stream-concat stream +Takes a @var{stream} consisting of one or more streams and returns a +newly-allocated stream containing all the elements of the input streams. +If any of the streams in the input @var{stream} is infinite, any +remaining streams in the input stream will never appear in the output +stream. See also @code{stream-append}. +@end deffn + +@deffn {Scheme Procedure} stream-constant object @dots{} +Returns a newly-allocated stream containing in its elements the +@var{object}s, repeating in succession forever. + +@example +(stream-constant 1) @result{} 1 1 1 @dots{} +(stream-constant #t #f) @result{} #t #f #t #f #t #f @dots{} +@end example +@end deffn + +@deffn {Scheme Procedure} stream-drop n stream +Returns the suffix of the input @var{stream} that starts at the next +element after the first @var{n} elements. The output stream shares +structure with the input @var{stream}; thus, promises forced in one +instance of the stream are also forced in the other instance of the +stream. If the input @var{stream} has less than @var{n} elements, +@code{stream-drop} returns the null stream. See also +@code{stream-take}. +@end deffn + +@deffn {Scheme Procedure} stream-drop-while pred stream +Returns the suffix of the input @var{stream} that starts at the first +element @var{x} for which @code{(pred x)} returns false. The output +stream shares structure with the input @var{stream}. See also +@code{stream-take-while}. +@end deffn + +@deffn {Scheme Procedure} stream-filter pred stream +Returns a newly-allocated stream that contains only those elements +@var{x} of the input @var{stream} which satisfy the predicate +@code{pred}. + +@example +(stream-filter odd? (stream-from 0)) + @result{} 1 3 5 7 9 @dots{} +@end example +@end deffn + +@deffn {Scheme Procedure} stream-fold proc base stream +Applies a binary procedure @var{proc} to @var{base} and the first +element of @var{stream} to compute a new @var{base}, then applies the +procedure to the new @var{base} and the next element of @var{stream} to +compute a succeeding @var{base}, and so on, accumulating a value that is +finally returned as the value of @code{stream-fold} when the end of the +stream is reached. @var{stream} must be finite, or @code{stream-fold} +will enter an infinite loop. See also @code{stream-scan}, which is +similar to @code{stream-fold}, but useful for infinite streams. For +readers familiar with other functional languages, this is a left-fold; +there is no corresponding right-fold, since right-fold relies on finite +streams that are fully-evaluated, in which case they may as well be +converted to a list. +@end deffn + +@deffn {Scheme Procedure} stream-for-each proc stream @dots{} +Applies @var{proc} element-wise to corresponding elements of the input +@var{stream}s for side-effects; it returns nothing. +@code{stream-for-each} stops as soon as any of its input streams is +exhausted. +@end deffn + +@deffn {Scheme Procedure} stream-from first [step] +Creates a newly-allocated stream that contains @var{first} as its first +element and increments each succeeding element by @var{step}. If +@var{step} is not given it defaults to 1. @var{first} and @var{step} +may be of any numeric type. @code{stream-from} is frequently useful as +a generator in @code{stream-of} expressions. See also +@code{stream-range} for a similar procedure that creates finite streams. +@end deffn + +@deffn {Scheme Procedure} stream-iterate proc base +Creates a newly-allocated stream containing @var{base} in its first +element and applies @var{proc} to each element in turn to determine the +succeeding element. See also @code{stream-unfold} and +@code{stream-unfolds}. +@end deffn + +@deffn {Scheme Procedure} stream-length stream +Returns the number of elements in the @var{stream}; it does not evaluate +its elements. @code{stream-length} may only be used on finite streams; +it enters an infinite loop with infinite streams. +@end deffn + +@deffn {Scheme Syntax} stream-let tag ((var expr) @dots{}) body @dots{} +Creates a local scope that binds each variable to the value of its +corresponding expression. It additionally binds @var{tag} to a +procedure which takes the bound variables as arguments and @var{body} as +its defining expressions, binding the @var{tag} with +@code{stream-lambda}. @var{tag} is in scope within body, and may be +called recursively. When the expanded expression defined by the +@code{stream-let} is evaluated, @code{stream-let} evaluates the +expressions in its @var{body} in an environment containing the +newly-bound variables, returning the value of the last expression +evaluated, which must yield a stream. + +@code{stream-let} provides syntactic sugar on @code{stream-lambda}, in +the same manner as normal @code{let} provides syntactic sugar on normal +@code{lambda}. However, unlike normal @code{let}, the @var{tag} is +required, not optional, because unnamed @code{stream-let} is +meaningless. + +For example, @code{stream-member} returns the first @code{stream-pair} +of the input @var{strm} with a @code{stream-car} @var{x} that satisfies +@code{(eql? obj x)}, or the null stream if @var{x} is not present in +@var{strm}. + +@example +(define-stream (stream-member eql? obj strm) + (stream-let loop ((strm strm)) + (cond ((stream-null? strm) strm) + ((eql? obj (stream-car strm)) strm) + (else (loop (stream-cdr strm)))))) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-map proc stream @dots{} +Applies @var{proc} element-wise to corresponding elements of the input +@var{stream}s, returning a newly-allocated stream containing elements +that are the results of those procedure applications. The output stream +has as many elements as the minimum-length input stream, and may be +infinite. +@end deffn + +@deffn {Scheme Syntax} stream-match stream clause @dots{} +Provides pattern-matching for streams. The input @var{stream} is an +expression that evaluates to a stream. Clauses are of the form +@code{(pattern [fender] expression)}, consisting of a @var{pattern} that +matches a stream of a particular shape, an optional @var{fender} that +must succeed if the pattern is to match, and an @var{expression} that is +evaluated if the pattern matches. There are four types of patterns: + +@itemize @bullet +@item +() matches the null stream. + +@item +(@var{pat0} @var{pat1} @dots{}) matches a finite stream with length +exactly equal to the number of pattern elements. + +@item +(@var{pat0} @var{pat1} @dots{} @code{.} @var{pat-rest}) matches an +infinite stream, or a finite stream with length at least as great as the +number of pattern elements before the literal dot. + +@item +@var{pat} matches an entire stream. Should always appear last in the +list of clauses; it's not an error to appear elsewhere, but subsequent +clauses could never match. +@end itemize + +Each pattern element may be either: + +@itemize @bullet +@item +An identifier, which matches any stream element. Additionally, the +value of the stream element is bound to the variable named by the +identifier, which is in scope in the @var{fender} and @var{expression} +of the corresponding @var{clause}. Each identifier in a single pattern +must be unique. + +@item +A literal underscore (@code{_}), which matches any stream element but +creates no bindings. +@end itemize + +The @var{pattern}s are tested in order, left-to-right, until a matching +pattern is found; if @var{fender} is present, it must evaluate to a true +value for the match to be successful. Pattern variables are bound in +the corresponding @var{fender} and @var{expression}. Once the matching +@var{pattern} is found, the corresponding @var{expression} is evaluated +and returned as the result of the match. An error is signaled if no +pattern matches the input @var{stream}. + +@code{stream-match} is often used to distinguish null streams from +non-null streams, binding @var{head} and @var{tail}: + +@example +(define (len strm) + (stream-match strm + (() 0) + ((head . tail) (+ 1 (len tail))))) +@end example + +Fenders can test the common case where two stream elements must be +identical; the @code{else} pattern is an identifier bound to the entire +stream, not a keyword as in @code{cond}. + +@example +(stream-match strm + ((x y . _) (equal? x y) 'ok) + (else 'error)) +@end example + +A more complex example uses two nested matchers to match two different +stream arguments; @code{(stream-merge lt? . strms)} stably merges two or +more streams ordered by the @code{lt?} predicate: + +@example +(define-stream (stream-merge lt? . strms) + (define-stream (merge xx yy) + (stream-match xx (() yy) ((x . xs) + (stream-match yy (() xx) ((y . ys) + (if (lt? y x) + (stream-cons y (merge xx ys)) + (stream-cons x (merge xs yy)))))))) + (stream-let loop ((strms strms)) + (cond ((null? strms) stream-null) + ((null? (cdr strms)) (car strms)) + (else (merge (car strms) + (apply stream-merge lt? + (cdr strms))))))) +@end example +@end deffn + +@deffn {Scheme Syntax} stream-of expr clause @dots{} +Provides the syntax of stream comprehensions, which generate streams by +means of looping expressions. The result is a stream of objects of the +type returned by @var{expr}. There are four types of clauses: + +@itemize @bullet +@item +(@var{var} @code{in} @var{stream-expr}) loops over the elements of +@var{stream-expr}, in order from the start of the stream, binding each +element of the stream in turn to @var{var}. @code{stream-from} and +@code{stream-range} are frequently useful as generators for +@var{stream-expr}. + +@item +(@var{var} @code{is} @var{expr}) binds @var{var} to the value obtained +by evaluating @var{expr}. + +@item +(@var{pred} @var{expr}) includes in the output stream only those +elements @var{x} which satisfy the predicate @var{pred}. +@end itemize + +The scope of variables bound in the stream comprehension is the clauses +to the right of the binding clause (but not the binding clause itself) +plus the result expression. + +When two or more generators are present, the loops are processed as if +they are nested from left to right; that is, the rightmost generator +varies fastest. A consequence of this is that only the first generator +may be infinite and all subsequent generators must be finite. If no +generators are present, the result of a stream comprehension is a stream +containing the result expression; thus, @samp{(stream-of 1)} produces a +finite stream containing only the element 1. + +@example +(stream-of (* x x) + (x in (stream-range 0 10)) + (even? x)) + @result{} 0 4 16 36 64 + +(stream-of (list a b) + (a in (stream-range 1 4)) + (b in (stream-range 1 3))) + @result{} (1 1) (1 2) (2 1) (2 2) (3 1) (3 2) + +(stream-of (list i j) + (i in (stream-range 1 5)) + (j in (stream-range (+ i 1) 5))) + @result{} (1 2) (1 3) (1 4) (2 3) (2 4) (3 4) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-range first past [step] +Creates a newly-allocated stream that contains @var{first} as its first +element and increments each succeeding element by @var{step}. The +stream is finite and ends before @var{past}, which is not an element of +the stream. If @var{step} is not given it defaults to 1 if @var{first} +is less than past and -1 otherwise. @var{first}, @var{past} and +@var{step} may be of any real numeric type. @code{stream-range} is +frequently useful as a generator in @code{stream-of} expressions. See +also @code{stream-from} for a similar procedure that creates infinite +streams. + +@example +(stream-range 0 10) @result{} 0 1 2 3 4 5 6 7 8 9 +(stream-range 0 10 2) @result{} 0 2 4 6 8 +@end example + +Successive elements of the stream are calculated by adding @var{step} to +@var{first}, so if any of @var{first}, @var{past} or @var{step} are +inexact, the length of the output stream may differ from +@code{(ceiling (- (/ (- past first) step) 1)}. +@end deffn + +@deffn {Scheme Procedure} stream-ref stream n +Returns the @var{n}th element of stream, counting from zero. An error +is signaled if @var{n} is greater than or equal to the length of stream. + +@example +(define (fact n) + (stream-ref + (stream-scan * 1 (stream-from 1)) + n)) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-reverse stream +Returns a newly-allocated stream containing the elements of the input +@var{stream} but in reverse order. @code{stream-reverse} may only be +used with finite streams; it enters an infinite loop with infinite +streams. @code{stream-reverse} does not force evaluation of the +elements of the stream. +@end deffn + +@deffn {Scheme Procedure} stream-scan proc base stream +Accumulates the partial folds of an input @var{stream} into a +newly-allocated output stream. The output stream is the @var{base} +followed by @code{(stream-fold proc base (stream-take i stream))} for +each of the first @var{i} elements of @var{stream}. + +@example +(stream-scan + 0 (stream-from 1)) + @result{} (stream 0 1 3 6 10 15 @dots{}) + +(stream-scan * 1 (stream-from 1)) + @result{} (stream 1 1 2 6 24 120 @dots{}) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-take n stream +Returns a newly-allocated stream containing the first @var{n} elements +of the input @var{stream}. If the input @var{stream} has less than +@var{n} elements, so does the output stream. See also +@code{stream-drop}. +@end deffn + +@deffn {Scheme Procedure} stream-take-while pred stream +Takes a predicate and a @code{stream} and returns a newly-allocated +stream containing those elements @code{x} that form the maximal prefix +of the input stream which satisfy @var{pred}. See also +@code{stream-drop-while}. +@end deffn + +@deffn {Scheme Procedure} stream-unfold map pred gen base +The fundamental recursive stream constructor. It constructs a stream by +repeatedly applying @var{gen} to successive values of @var{base}, in the +manner of @code{stream-iterate}, then applying @var{map} to each of the +values so generated, appending each of the mapped values to the output +stream as long as @code{(pred? base)} returns a true value. See also +@code{stream-iterate} and @code{stream-unfolds}. + +The expression below creates the finite stream @samp{0 1 4 9 16 25 36 49 +64 81}. Initially the @var{base} is 0, which is less than 10, so +@var{map} squares the @var{base} and the mapped value becomes the first +element of the output stream. Then @var{gen} increments the @var{base} +by 1, so it becomes 1; this is less than 10, so @var{map} squares the +new @var{base} and 1 becomes the second element of the output stream. +And so on, until the base becomes 10, when @var{pred} stops the +recursion and stream-null ends the output stream. + +@example +(stream-unfold + (lambda (x) (expt x 2)) ; map + (lambda (x) (< x 10)) ; pred? + (lambda (x) (+ x 1)) ; gen + 0) ; base +@end example +@end deffn + +@deffn {Scheme Procedure} stream-unfolds proc seed +Returns @var{n} newly-allocated streams containing those elements +produced by successive calls to the generator @var{proc}, which takes +the current @var{seed} as its argument and returns @var{n}+1 values + +(@var{proc} @var{seed}) @result{} @var{seed} @var{result_0} @dots{} @var{result_n-1} + +where the returned @var{seed} is the input @var{seed} to the next call +to the generator and @var{result_i} indicates how to produce the next +element of the @var{i}th result stream: + +@itemize @bullet +@item +(@var{value}): @var{value} is the next car of the result stream. + +@item +@code{#f}: no value produced by this iteration of the generator +@var{proc} for the result stream. + +@item +(): the end of the result stream. +@end itemize + +It may require multiple calls of @var{proc} to produce the next element +of any particular result stream. See also @code{stream-iterate} and +@code{stream-unfold}. + +@example +(define (stream-partition pred? strm) + (stream-unfolds + (lambda (s) + (if (stream-null? s) + (values s '() '()) + (let ((a (stream-car s)) + (d (stream-cdr s))) + (if (pred? a) + (values d (list a) #f) + (values d #f (list a)))))) + strm)) + +(call-with-values + (lambda () + (stream-partition odd? + (stream-range 1 6))) + (lambda (odds evens) + (list (stream->list odds) + (stream->list evens)))) + @result{} ((1 3 5) (2 4)) +@end example +@end deffn + +@deffn {Scheme Procedure} stream-zip stream @dots{} +Returns a newly-allocated stream in which each element is a list (not a +stream) of the corresponding elements of the input @var{stream}s. The +output stream is as long as the shortest input @var{stream}, if any of +the input @var{stream}s is finite, or is infinite if all the input +@var{stream}s are infinite. +@end deffn + +@node SRFI-42 +@subsection SRFI-42 - Eager Comprehensions +@cindex SRFI-42 + +See @uref{http://srfi.schemers.org/srfi-42/srfi-42.html, the +specification of SRFI-42}. + +@node SRFI-43 +@subsection SRFI-43 - Vector Library +@cindex SRFI-43 + +This subsection is based on the +@uref{http://srfi.schemers.org/srfi-43/srfi-43.html, specification of +SRFI-43} by Taylor Campbell. + +@c The copyright notice and license text of the SRFI-43 specification is +@c reproduced below: + +@c Copyright (C) Taylor Campbell (2003). All Rights Reserved. + +@c Permission is hereby granted, free of charge, to any person obtaining a +@c copy of this software and associated documentation files (the +@c "Software"), to deal in the Software without restriction, including +@c without limitation the rights to use, copy, modify, merge, publish, +@c distribute, sublicense, and/or sell copies of the Software, and to +@c permit persons to whom the Software is furnished to do so, subject to +@c the following conditions: + +@c The above copyright notice and this permission notice shall be included +@c in all copies or substantial portions of the Software. + +@c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +@c OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +@c MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@c NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +@c LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +@c OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +@c WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@noindent +SRFI-43 implements a comprehensive library of vector operations. It can +be made available with: + +@example +(use-modules (srfi srfi-43)) +@end example + +@menu +* SRFI-43 Constructors:: +* SRFI-43 Predicates:: +* SRFI-43 Selectors:: +* SRFI-43 Iteration:: +* SRFI-43 Searching:: +* SRFI-43 Mutators:: +* SRFI-43 Conversion:: +@end menu + +@node SRFI-43 Constructors +@subsubsection SRFI-43 Constructors + +@deffn {Scheme Procedure} make-vector size [fill] +Create and return a vector of size @var{size}, optionally filling it +with @var{fill}. The default value of @var{fill} is unspecified. + +@example +(make-vector 5 3) @result{} #(3 3 3 3 3) +@end example +@end deffn + +@deffn {Scheme Procedure} vector x @dots{} +Create and return a vector whose elements are @var{x} @enddots{}. + +@example +(vector 0 1 2 3 4) @result{} #(0 1 2 3 4) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-unfold f length initial-seed @dots{} +The fundamental vector constructor. Create a vector whose length +is @var{length} and iterates across each index k from 0 up to +@var{length} - 1, applying @var{f} at each iteration to the current +index and current seeds, in that order, to receive n + 1 values: the +element to put in the kth slot of the new vector, and n new seeds for +the next iteration. It is an error for the number of seeds to vary +between iterations. + +@example +(vector-unfold (lambda (i x) (values x (- x 1))) + 10 0) +@result{} #(0 -1 -2 -3 -4 -5 -6 -7 -8 -9) + +(vector-unfold values 10) +@result{} #(0 1 2 3 4 5 6 7 8 9) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-unfold-right f length initial-seed @dots{} +Like @code{vector-unfold}, but it uses @var{f} to generate elements from +right-to-left, rather than left-to-right. + +@example +(vector-unfold-right (lambda (i x) (values x (+ x 1))) + 10 0) +@result{} #(9 8 7 6 5 4 3 2 1 0) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-copy vec [start [end [fill]]] +Allocate a new vector whose length is @var{end} - @var{start} and fills +it with elements from @var{vec}, taking elements from @var{vec} starting +at index @var{start} and stopping at index @var{end}. @var{start} +defaults to 0 and @var{end} defaults to the value of +@code{(vector-length vec)}. If @var{end} extends beyond the length of +@var{vec}, the slots in the new vector that obviously cannot be filled +by elements from @var{vec} are filled with @var{fill}, whose default +value is unspecified. + +@example +(vector-copy '#(a b c d e f g h i)) +@result{} #(a b c d e f g h i) + +(vector-copy '#(a b c d e f g h i) 6) +@result{} #(g h i) + +(vector-copy '#(a b c d e f g h i) 3 6) +@result{} #(d e f) + +(vector-copy '#(a b c d e f g h i) 6 12 'x) +@result{} #(g h i x x x) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-reverse-copy vec [start [end]] +Like @code{vector-copy}, but it copies the elements in the reverse order +from @var{vec}. + +@example +(vector-reverse-copy '#(5 4 3 2 1 0) 1 5) +@result{} #(1 2 3 4) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-append vec @dots{} +Return a newly allocated vector that contains all elements in order from +the subsequent locations in @var{vec} @enddots{}. + +@example +(vector-append '#(a) '#(b c d)) +@result{} #(a b c d) +@end example +@end deffn + +@deffn {Scheme Procedure} vector-concatenate list-of-vectors +Append each vector in @var{list-of-vectors}. Equivalent to +@code{(apply vector-append list-of-vectors)}. + +@example +(vector-concatenate '(#(a b) #(c d))) +@result{} #(a b c d) +@end example +@end deffn + +@node SRFI-43 Predicates +@subsubsection SRFI-43 Predicates + +@deffn {Scheme Procedure} vector? obj +Return true if @var{obj} is a vector, else return false. +@end deffn + +@deffn {Scheme Procedure} vector-empty? vec +Return true if @var{vec} is empty, i.e. its length is 0, else return +false. +@end deffn + +@deffn {Scheme Procedure} vector= elt=? vec @dots{} +Return true if the vectors @var{vec} @dots{} have equal lengths and +equal elements according to @var{elt=?}. @var{elt=?} is always applied +to two arguments. Element comparison must be consistent with @code{eq?} +in the following sense: if @code{(eq? a b)} returns true, then +@code{(elt=? a b)} must also return true. The order in which +comparisons are performed is unspecified. +@end deffn + +@node SRFI-43 Selectors +@subsubsection SRFI-43 Selectors + +@deffn {Scheme Procedure} vector-ref vec i +Return the element at index @var{i} in @var{vec}. Indexing is based on +zero. +@end deffn + +@deffn {Scheme Procedure} vector-length vec +Return the length of @var{vec}. +@end deffn + +@node SRFI-43 Iteration +@subsubsection SRFI-43 Iteration + +@deffn {Scheme Procedure} vector-fold kons knil vec1 vec2 @dots{} +The fundamental vector iterator. @var{kons} is iterated over each index +in all of the vectors, stopping at the end of the shortest; @var{kons} +is applied as +@smalllisp +(kons i state (vector-ref vec1 i) (vector-ref vec2 i) ...) +@end smalllisp +where @var{state} is the current state value, and @var{i} is the current +index. The current state value begins with @var{knil}, and becomes +whatever @var{kons} returned at the respective iteration. The iteration +is strictly left-to-right. +@end deffn + +@deffn {Scheme Procedure} vector-fold-right kons knil vec1 vec2 @dots{} +Similar to @code{vector-fold}, but it iterates right-to-left instead of +left-to-right. +@end deffn + +@deffn {Scheme Procedure} vector-map f vec1 vec2 @dots{} +Return a new vector of the shortest size of the vector arguments. Each +element at index i of the new vector is mapped from the old vectors by +@smalllisp +(f i (vector-ref vec1 i) (vector-ref vec2 i) ...) +@end smalllisp +The dynamic order of application of @var{f} is unspecified. +@end deffn + +@deffn {Scheme Procedure} vector-map! f vec1 vec2 @dots{} +Similar to @code{vector-map}, but rather than mapping the new elements +into a new vector, the new mapped elements are destructively inserted +into @var{vec1}. The dynamic order of application of @var{f} is +unspecified. +@end deffn + +@deffn {Scheme Procedure} vector-for-each f vec1 vec2 @dots{} +Call @code{(f i (vector-ref vec1 i) (vector-ref vec2 i) ...)} for each +index i less than the length of the shortest vector passed. The +iteration is strictly left-to-right. +@end deffn + +@deffn {Scheme Procedure} vector-count pred? vec1 vec2 @dots{} +Count the number of parallel elements in the vectors that satisfy +@var{pred?}, which is applied, for each index i less than the length of +the smallest vector, to i and each parallel element in the vectors at +that index, in order. + +@example +(vector-count (lambda (i elt) (even? elt)) + '#(3 1 4 1 5 9 2 5 6)) +@result{} 3 +(vector-count (lambda (i x y) (< x y)) + '#(1 3 6 9) '#(2 4 6 8 10 12)) +@result{} 2 +@end example +@end deffn + +@node SRFI-43 Searching +@subsubsection SRFI-43 Searching + +@deffn {Scheme Procedure} vector-index pred? vec1 vec2 @dots{} +Find and return the index of the first elements in @var{vec1} @var{vec2} +@dots{} that satisfy @var{pred?}. If no matching element is found by +the end of the shortest vector, return @code{#f}. + +@example +(vector-index even? '#(3 1 4 1 5 9)) +@result{} 2 +(vector-index < '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2)) +@result{} 1 +(vector-index = '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2)) +@result{} #f +@end example +@end deffn + +@deffn {Scheme Procedure} vector-index-right pred? vec1 vec2 @dots{} +Like @code{vector-index}, but it searches right-to-left, rather than +left-to-right. Note that the SRFI 43 specification requires that all +the vectors must have the same length, but both the SRFI 43 reference +implementation and Guile's implementation allow vectors with unequal +lengths, and start searching from the last index of the shortest vector. +@end deffn + +@deffn {Scheme Procedure} vector-skip pred? vec1 vec2 @dots{} +Find and return the index of the first elements in @var{vec1} @var{vec2} +@dots{} that do not satisfy @var{pred?}. If no matching element is +found by the end of the shortest vector, return @code{#f}. Equivalent +to @code{vector-index} but with the predicate inverted. + +@example +(vector-skip number? '#(1 2 a b 3 4 c d)) @result{} 2 +@end example +@end deffn + +@deffn {Scheme Procedure} vector-skip-right pred? vec1 vec2 @dots{} +Like @code{vector-skip}, but it searches for a non-matching element +right-to-left, rather than left-to-right. Note that the SRFI 43 +specification requires that all the vectors must have the same length, +but both the SRFI 43 reference implementation and Guile's implementation +allow vectors with unequal lengths, and start searching from the last +index of the shortest vector. +@end deffn + +@deffn {Scheme Procedure} vector-binary-search vec value cmp [start [end]] +Find and return an index of @var{vec} between @var{start} and @var{end} +whose value is @var{value} using a binary search. If no matching +element is found, return @code{#f}. The default @var{start} is 0 and +the default @var{end} is the length of @var{vec}. + +@var{cmp} must be a procedure of two arguments such that @code{(cmp a +b)} returns a negative integer if @math{a < b}, a positive integer if +@math{a > b}, or zero if @math{a = b}. The elements of @var{vec} must +be sorted in non-decreasing order according to @var{cmp}. + +Note that SRFI 43 does not document the @var{start} and @var{end} +arguments, but both its reference implementation and Guile's +implementation support them. + +@example +(define (char-cmp c1 c2) + (cond ((char<? c1 c2) -1) + ((char>? c1 c2) 1) + (else 0))) + +(vector-binary-search '#(#\a #\b #\c #\d #\e #\f #\g #\h) + #\g + char-cmp) +@result{} 6 +@end example +@end deffn + +@deffn {Scheme Procedure} vector-any pred? vec1 vec2 @dots{} +Find the first parallel set of elements from @var{vec1} @var{vec2} +@dots{} for which @var{pred?} returns a true value. If such a parallel +set of elements exists, @code{vector-any} returns the value that +@var{pred?} returned for that set of elements. The iteration is +strictly left-to-right. +@end deffn + +@deffn {Scheme Procedure} vector-every pred? vec1 vec2 @dots{} +If, for every index i between 0 and the length of the shortest vector +argument, the set of elements @code{(vector-ref vec1 i)} +@code{(vector-ref vec2 i)} @dots{} satisfies @var{pred?}, +@code{vector-every} returns the value that @var{pred?} returned for the +last set of elements, at the last index of the shortest vector. +Otherwise it returns @code{#f}. The iteration is strictly +left-to-right. +@end deffn + +@node SRFI-43 Mutators +@subsubsection SRFI-43 Mutators + +@deffn {Scheme Procedure} vector-set! vec i value +Assign the contents of the location at @var{i} in @var{vec} to +@var{value}. +@end deffn + +@deffn {Scheme Procedure} vector-swap! vec i j +Swap the values of the locations in @var{vec} at @var{i} and @var{j}. +@end deffn + +@deffn {Scheme Procedure} vector-fill! vec fill [start [end]] +Assign the value of every location in @var{vec} between @var{start} and +@var{end} to @var{fill}. @var{start} defaults to 0 and @var{end} +defaults to the length of @var{vec}. +@end deffn + +@deffn {Scheme Procedure} vector-reverse! vec [start [end]] +Destructively reverse the contents of @var{vec} between @var{start} and +@var{end}. @var{start} defaults to 0 and @var{end} defaults to the +length of @var{vec}. +@end deffn + +@deffn {Scheme Procedure} vector-copy! target tstart source [sstart [send]] +Copy a block of elements from @var{source} to @var{target}, both of +which must be vectors, starting in @var{target} at @var{tstart} and +starting in @var{source} at @var{sstart}, ending when (@var{send} - +@var{sstart}) elements have been copied. It is an error for +@var{target} to have a length less than (@var{tstart} + @var{send} - +@var{sstart}). @var{sstart} defaults to 0 and @var{send} defaults to +the length of @var{source}. +@end deffn + +@deffn {Scheme Procedure} vector-reverse-copy! target tstart source [sstart [send]] +Like @code{vector-copy!}, but this copies the elements in the reverse +order. It is an error if @var{target} and @var{source} are identical +vectors and the @var{target} and @var{source} ranges overlap; however, +if @var{tstart} = @var{sstart}, @code{vector-reverse-copy!} behaves as +@code{(vector-reverse! target tstart send)} would. +@end deffn + +@node SRFI-43 Conversion +@subsubsection SRFI-43 Conversion + +@deffn {Scheme Procedure} vector->list vec [start [end]] +Return a newly allocated list containing the elements in @var{vec} +between @var{start} and @var{end}. @var{start} defaults to 0 and +@var{end} defaults to the length of @var{vec}. +@end deffn + +@deffn {Scheme Procedure} reverse-vector->list vec [start [end]] +Like @code{vector->list}, but the resulting list contains the specified +range of elements of @var{vec} in reverse order. +@end deffn + +@deffn {Scheme Procedure} list->vector proper-list [start [end]] +Return a newly allocated vector of the elements from @var{proper-list} +with indices between @var{start} and @var{end}. @var{start} defaults to +0 and @var{end} defaults to the length of @var{proper-list}. Note that +SRFI 43 does not document the @var{start} and @var{end} arguments, but +both its reference implementation and Guile's implementation support +them. +@end deffn + +@deffn {Scheme Procedure} reverse-list->vector proper-list [start [end]] +Like @code{list->vector}, but the resulting vector contains the specified +range of elements of @var{proper-list} in reverse order. Note that SRFI +43 does not document the @var{start} and @var{end} arguments, but both +its reference implementation and Guile's implementation support them. +@end deffn + +@node SRFI-45 +@subsection SRFI-45 - Primitives for Expressing Iterative Lazy Algorithms +@cindex SRFI-45 + +This subsection is based on @uref{http://srfi.schemers.org/srfi-45/srfi-45.html, the +specification of SRFI-45} written by Andr@'e van Tonder. + +@c Copyright (C) André van Tonder (2003). All Rights Reserved. + +@c Permission is hereby granted, free of charge, to any person obtaining a +@c copy of this software and associated documentation files (the +@c "Software"), to deal in the Software without restriction, including +@c without limitation the rights to use, copy, modify, merge, publish, +@c distribute, sublicense, and/or sell copies of the Software, and to +@c permit persons to whom the Software is furnished to do so, subject to +@c the following conditions: + +@c The above copyright notice and this permission notice shall be included +@c in all copies or substantial portions of the Software. + +@c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +@c OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +@c MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +@c NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +@c LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +@c OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +@c WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Lazy evaluation is traditionally simulated in Scheme using @code{delay} +and @code{force}. However, these primitives are not powerful enough to +express a large class of lazy algorithms that are iterative. Indeed, it +is folklore in the Scheme community that typical iterative lazy +algorithms written using delay and force will often require unbounded +memory. + +This SRFI provides set of three operations: @{@code{lazy}, @code{delay}, +@code{force}@}, which allow the programmer to succinctly express lazy +algorithms while retaining bounded space behavior in cases that are +properly tail-recursive. A general recipe for using these primitives is +provided. An additional procedure @code{eager} is provided for the +construction of eager promises in cases where efficiency is a concern. + +Although this SRFI redefines @code{delay} and @code{force}, the +extension is conservative in the sense that the semantics of the subset +@{@code{delay}, @code{force}@} in isolation (i.e., as long as the +program does not use @code{lazy}) agrees with that in R5RS. In other +words, no program that uses the R5RS definitions of delay and force will +break if those definition are replaced by the SRFI-45 definitions of +delay and force. + +Guile also adds @code{promise?} to the list of exports, which is not +part of the official SRFI-45. + +@deffn {Scheme Procedure} promise? obj +Return true if @var{obj} is an SRFI-45 promise, otherwise return false. +@end deffn + +@deffn {Scheme Syntax} delay expression +Takes an expression of arbitrary type @var{a} and returns a promise of +type @code{(Promise @var{a})} which at some point in the future may be +asked (by the @code{force} procedure) to evaluate the expression and +deliver the resulting value. +@end deffn + +@deffn {Scheme Syntax} lazy expression +Takes an expression of type @code{(Promise @var{a})} and returns a +promise of type @code{(Promise @var{a})} which at some point in the +future may be asked (by the @code{force} procedure) to evaluate the +expression and deliver the resulting promise. +@end deffn + +@deffn {Scheme Procedure} force expression +Takes an argument of type @code{(Promise @var{a})} and returns a value +of type @var{a} as follows: If a value of type @var{a} has been computed +for the promise, this value is returned. Otherwise, the promise is +first evaluated, then overwritten by the obtained promise or value, and +then force is again applied (iteratively) to the promise. +@end deffn + +@deffn {Scheme Procedure} eager expression +Takes an argument of type @var{a} and returns a value of type +@code{(Promise @var{a})}. As opposed to @code{delay}, the argument is +evaluated eagerly. Semantically, writing @code{(eager expression)} is +equivalent to writing + +@lisp +(let ((value expression)) (delay value)). +@end lisp + +However, the former is more efficient since it does not require +unnecessary creation and evaluation of thunks. We also have the +equivalence + +@lisp +(delay expression) = (lazy (eager expression)) +@end lisp +@end deffn + +The following reduction rules may be helpful for reasoning about these +primitives. However, they do not express the memoization and memory +usage semantics specified above: + +@lisp +(force (delay expression)) -> expression +(force (lazy expression)) -> (force expression) +(force (eager value)) -> value +@end lisp + +@subsubheading Correct usage + +We now provide a general recipe for using the primitives @{@code{lazy}, +@code{delay}, @code{force}@} to express lazy algorithms in Scheme. The +transformation is best described by way of an example: Consider the +stream-filter algorithm, expressed in a hypothetical lazy language as + +@lisp +(define (stream-filter p? s) + (if (null? s) '() + (let ((h (car s)) + (t (cdr s))) + (if (p? h) + (cons h (stream-filter p? t)) + (stream-filter p? t))))) +@end lisp + +This algorithm can be expressed as follows in Scheme: + +@lisp +(define (stream-filter p? s) + (lazy + (if (null? (force s)) (delay '()) + (let ((h (car (force s))) + (t (cdr (force s)))) + (if (p? h) + (delay (cons h (stream-filter p? t))) + (stream-filter p? t)))))) +@end lisp + +In other words, we + +@itemize @bullet +@item +wrap all constructors (e.g., @code{'()}, @code{cons}) with @code{delay}, +@item +apply @code{force} to arguments of deconstructors (e.g., @code{car}, +@code{cdr} and @code{null?}), +@item +wrap procedure bodies with @code{(lazy ...)}. +@end itemize + +@node SRFI-46 +@subsection SRFI-46 Basic syntax-rules Extensions +@cindex SRFI-46 + +Guile's core @code{syntax-rules} supports the extensions specified by +SRFI-46/R7RS. Tail patterns have been supported since at least Guile +2.0, and custom ellipsis identifiers have been supported since Guile +2.0.10. @xref{Syntax Rules}. + +@node SRFI-55 +@subsection SRFI-55 - Requiring Features +@cindex SRFI-55 + +SRFI-55 provides @code{require-extension} which is a portable +mechanism to load selected SRFI modules. This is implemented in the +Guile core, there's no module needed to get SRFI-55 itself. + +@deffn {library syntax} require-extension clause1 clause2 @dots{} +Require the features of @var{clause1} @var{clause2} @dots{} , throwing +an error if any are unavailable. + +A @var{clause} is of the form @code{(@var{identifier} arg...)}. The +only @var{identifier} currently supported is @code{srfi} and the +arguments are SRFI numbers. For example to get SRFI-1 and SRFI-6, + +@example +(require-extension (srfi 1 6)) +@end example + +@code{require-extension} can only be used at the top-level. + +A Guile-specific program can simply @code{use-modules} to load SRFIs +not already in the core, @code{require-extension} is for programs +designed to be portable to other Scheme implementations. +@end deffn + + +@node SRFI-60 +@subsection SRFI-60 - Integers as Bits +@cindex SRFI-60 +@cindex integers as bits +@cindex bitwise logical + +This SRFI provides various functions for treating integers as bits and +for bitwise manipulations. These functions can be obtained with, + +@example +(use-modules (srfi srfi-60)) +@end example + +Integers are treated as infinite precision twos-complement, the same +as in the core logical functions (@pxref{Bitwise Operations}). And +likewise bit indexes start from 0 for the least significant bit. The +following functions in this SRFI are already in the Guile core, + +@quotation +@code{logand}, +@code{logior}, +@code{logxor}, +@code{lognot}, +@code{logtest}, +@code{logcount}, +@code{integer-length}, +@code{logbit?}, +@code{ash} +@end quotation + +@sp 1 +@defun bitwise-and n1 ... +@defunx bitwise-ior n1 ... +@defunx bitwise-xor n1 ... +@defunx bitwise-not n +@defunx any-bits-set? j k +@defunx bit-set? index n +@defunx arithmetic-shift n count +@defunx bit-field n start end +@defunx bit-count n +Aliases for @code{logand}, @code{logior}, @code{logxor}, +@code{lognot}, @code{logtest}, @code{logbit?}, @code{ash}, +@code{bit-extract} and @code{logcount} respectively. + +Note that the name @code{bit-count} conflicts with @code{bit-count} in +the core (@pxref{Bit Vectors}). +@end defun + +@defun bitwise-if mask n1 n0 +@defunx bitwise-merge mask n1 n0 +Return an integer with bits selected from @var{n1} and @var{n0} +according to @var{mask}. Those bits where @var{mask} has 1s are taken +from @var{n1}, and those where @var{mask} has 0s are taken from +@var{n0}. + +@example +(bitwise-if 3 #b0101 #b1010) @result{} 9 +@end example +@end defun + +@defun log2-binary-factors n +@defunx first-set-bit n +Return a count of how many factors of 2 are present in @var{n}. This +is also the bit index of the lowest 1 bit in @var{n}. If @var{n} is +0, the return is @math{-1}. + +@example +(log2-binary-factors 6) @result{} 1 +(log2-binary-factors -8) @result{} 3 +@end example +@end defun + +@defun copy-bit index n newbit +Return @var{n} with the bit at @var{index} set according to +@var{newbit}. @var{newbit} should be @code{#t} to set the bit to 1, +or @code{#f} to set it to 0. Bits other than at @var{index} are +unchanged in the return. + +@example +(copy-bit 1 #b0101 #t) @result{} 7 +@end example +@end defun + +@defun copy-bit-field n newbits start end +Return @var{n} with the bits from @var{start} (inclusive) to @var{end} +(exclusive) changed to the value @var{newbits}. + +The least significant bit in @var{newbits} goes to @var{start}, the +next to @math{@var{start}+1}, etc. Anything in @var{newbits} past the +@var{end} given is ignored. + +@example +(copy-bit-field #b10000 #b11 1 3) @result{} #b10110 +@end example +@end defun + +@defun rotate-bit-field n count start end +Return @var{n} with the bit field from @var{start} (inclusive) to +@var{end} (exclusive) rotated upwards by @var{count} bits. + +@var{count} can be positive or negative, and it can be more than the +field width (it'll be reduced modulo the width). + +@example +(rotate-bit-field #b0110 2 1 4) @result{} #b1010 +@end example +@end defun + +@defun reverse-bit-field n start end +Return @var{n} with the bits from @var{start} (inclusive) to @var{end} +(exclusive) reversed. + +@example +(reverse-bit-field #b101001 2 4) @result{} #b100101 +@end example +@end defun + +@defun integer->list n [len] +Return bits from @var{n} in the form of a list of @code{#t} for 1 and +@code{#f} for 0. The least significant @var{len} bits are returned, +and the first list element is the most significant of those bits. If +@var{len} is not given, the default is @code{(integer-length @var{n})} +(@pxref{Bitwise Operations}). + +@example +(integer->list 6) @result{} (#t #t #f) +(integer->list 1 4) @result{} (#f #f #f #t) +@end example +@end defun + +@defun list->integer lst +@defunx booleans->integer bool@dots{} +Return an integer formed bitwise from the given @var{lst} list of +booleans, or for @code{booleans->integer} from the @var{bool} +arguments. + +Each boolean is @code{#t} for a 1 and @code{#f} for a 0. The first +element becomes the most significant bit in the return. + +@example +(list->integer '(#t #f #t #f)) @result{} 10 +@end example +@end defun + + +@node SRFI-61 +@subsection SRFI-61 - A more general @code{cond} clause + +This SRFI extends RnRS @code{cond} to support test expressions that +return multiple values, as well as arbitrary definitions of test +success. SRFI 61 is implemented in the Guile core; there's no module +needed to get SRFI-61 itself. Extended @code{cond} is documented in +@ref{Conditionals,, Simple Conditional Evaluation}. + +@node SRFI-62 +@subsection SRFI-62 - S-expression comments. +@cindex SRFI-62 + +Starting from version 2.0, Guile's @code{read} supports SRFI-62/R7RS +S-expression comments by default. + +@node SRFI-64 +@subsection SRFI-64 - A Scheme API for test suites. +@cindex SRFI-64 + +See @uref{http://srfi.schemers.org/srfi-64/srfi-64.html, the +specification of SRFI-64}. + +@node SRFI-67 +@subsection SRFI-67 - Compare procedures +@cindex SRFI-67 + +See @uref{http://srfi.schemers.org/srfi-67/srfi-67.html, the +specification of SRFI-67}. + +@node SRFI-69 +@subsection SRFI-69 - Basic hash tables +@cindex SRFI-69 + +This is a portable wrapper around Guile's built-in hash table and weak +table support. @xref{Hash Tables}, for information on that built-in +support. Above that, this hash-table interface provides association +of equality and hash functions with tables at creation time, so +variants of each function are not required, as well as a procedure +that takes care of most uses for Guile hash table handles, which this +SRFI does not provide as such. + +Access it with: + +@lisp +(use-modules (srfi srfi-69)) +@end lisp + +@menu +* SRFI-69 Creating hash tables:: +* SRFI-69 Accessing table items:: +* SRFI-69 Table properties:: +* SRFI-69 Hash table algorithms:: +@end menu + +@node SRFI-69 Creating hash tables +@subsubsection Creating hash tables + +@deffn {Scheme Procedure} make-hash-table [equal-proc hash-proc #:weak weakness start-size] +Create and answer a new hash table with @var{equal-proc} as the +equality function and @var{hash-proc} as the hashing function. + +By default, @var{equal-proc} is @code{equal?}. It can be any +two-argument procedure, and should answer whether two keys are the +same for this table's purposes. + +My default @var{hash-proc} assumes that @code{equal-proc} is no +coarser than @code{equal?} unless it is literally @code{string-ci=?}. +If provided, @var{hash-proc} should be a two-argument procedure that +takes a key and the current table size, and answers a reasonably good +hash integer between 0 (inclusive) and the size (exclusive). + +@var{weakness} should be @code{#f} or a symbol indicating how ``weak'' +the hash table is: + +@table @code +@item #f +An ordinary non-weak hash table. This is the default. + +@item key +When the key has no more non-weak references at GC, remove that entry. + +@item value +When the value has no more non-weak references at GC, remove that +entry. + +@item key-or-value +When either has no more non-weak references at GC, remove the +association. +@end table + +As a legacy of the time when Guile couldn't grow hash tables, +@var{start-size} is an optional integer argument that specifies the +approximate starting size for the hash table, which will be rounded to +an algorithmically-sounder number. +@end deffn + +By @dfn{coarser} than @code{equal?}, we mean that for all @var{x} and +@var{y} values where @code{(@var{equal-proc} @var{x} @var{y})}, +@code{(equal? @var{x} @var{y})} as well. If that does not hold for +your @var{equal-proc}, you must provide a @var{hash-proc}. + +In the case of weak tables, remember that @dfn{references} above +always refers to @code{eq?}-wise references. Just because you have a +reference to some string @code{"foo"} doesn't mean that an association +with key @code{"foo"} in a weak-key table @emph{won't} be collected; +it only counts as a reference if the two @code{"foo"}s are @code{eq?}, +regardless of @var{equal-proc}. As such, it is usually only sensible +to use @code{eq?} and @code{hashq} as the equivalence and hash +functions for a weak table. @xref{Weak References}, for more +information on Guile's built-in weak table support. + +@deffn {Scheme Procedure} alist->hash-table alist [equal-proc hash-proc #:weak weakness start-size] +As with @code{make-hash-table}, but initialize it with the +associations in @var{alist}. Where keys are repeated in @var{alist}, +the leftmost association takes precedence. +@end deffn + +@node SRFI-69 Accessing table items +@subsubsection Accessing table items + +@deffn {Scheme Procedure} hash-table-ref table key [default-thunk] +@deffnx {Scheme Procedure} hash-table-ref/default table key default +Answer the value associated with @var{key} in @var{table}. If +@var{key} is not present, answer the result of invoking the thunk +@var{default-thunk}, which signals an error instead by default. + +@code{hash-table-ref/default} is a variant that requires a third +argument, @var{default}, and answers @var{default} itself instead of +invoking it. +@end deffn + +@deffn {Scheme Procedure} hash-table-set! table key new-value +Set @var{key} to @var{new-value} in @var{table}. +@end deffn + +@deffn {Scheme Procedure} hash-table-delete! table key +Remove the association of @var{key} in @var{table}, if present. If +absent, do nothing. +@end deffn + +@deffn {Scheme Procedure} hash-table-exists? table key +Answer whether @var{key} has an association in @var{table}. +@end deffn + +@deffn {Scheme Procedure} hash-table-update! table key modifier [default-thunk] +@deffnx {Scheme Procedure} hash-table-update!/default table key modifier default +Replace @var{key}'s associated value in @var{table} by invoking +@var{modifier} with one argument, the old value. + +If @var{key} is not present, and @var{default-thunk} is provided, +invoke it with no arguments to get the ``old value'' to be passed to +@var{modifier} as above. If @var{default-thunk} is not provided in +such a case, signal an error. + +@code{hash-table-update!/default} is a variant that requires the +fourth argument, which is used directly as the ``old value'' rather +than as a thunk to be invoked to retrieve the ``old value''. +@end deffn + +@node SRFI-69 Table properties +@subsubsection Table properties + +@deffn {Scheme Procedure} hash-table-size table +Answer the number of associations in @var{table}. This is guaranteed +to run in constant time for non-weak tables. +@end deffn + +@deffn {Scheme Procedure} hash-table-keys table +Answer an unordered list of the keys in @var{table}. +@end deffn + +@deffn {Scheme Procedure} hash-table-values table +Answer an unordered list of the values in @var{table}. +@end deffn + +@deffn {Scheme Procedure} hash-table-walk table proc +Invoke @var{proc} once for each association in @var{table}, passing +the key and value as arguments. +@end deffn + +@deffn {Scheme Procedure} hash-table-fold table proc init +Invoke @code{(@var{proc} @var{key} @var{value} @var{previous})} for +each @var{key} and @var{value} in @var{table}, where @var{previous} is +the result of the previous invocation, using @var{init} as the first +@var{previous} value. Answer the final @var{proc} result. +@end deffn + +@deffn {Scheme Procedure} hash-table->alist table +Answer an alist where each association in @var{table} is an +association in the result. +@end deffn + +@node SRFI-69 Hash table algorithms +@subsubsection Hash table algorithms + +Each hash table carries an @dfn{equivalence function} and a @dfn{hash +function}, used to implement key lookups. Beginning users should +follow the rules for consistency of the default @var{hash-proc} +specified above. Advanced users can use these to implement their own +equivalence and hash functions for specialized lookup semantics. + +@deffn {Scheme Procedure} hash-table-equivalence-function hash-table +@deffnx {Scheme Procedure} hash-table-hash-function hash-table +Answer the equivalence and hash function of @var{hash-table}, respectively. +@end deffn + +@deffn {Scheme Procedure} hash obj [size] +@deffnx {Scheme Procedure} string-hash obj [size] +@deffnx {Scheme Procedure} string-ci-hash obj [size] +@deffnx {Scheme Procedure} hash-by-identity obj [size] +Answer a hash value appropriate for equality predicate @code{equal?}, +@code{string=?}, @code{string-ci=?}, and @code{eq?}, respectively. +@end deffn + +@code{hash} is a backwards-compatible replacement for Guile's built-in +@code{hash}. + +@node SRFI-71 +@subsection SRFI-71 - Extended let-syntax for multiple values +@cindex SRFI-71 + +This SRFI shadows the forms for @code{let}, @code{let*}, and @code{letrec} +so that they may accept multiple values. For example: + +@example +(use-modules (srfi srfi-71)) + +(let* ((x y (values 1 2)) + (z (+ x y))) + (* z 2)) +@result{} 6 +@end example + +See @uref{http://srfi.schemers.org/srfi-71/srfi-71.html, the +specification of SRFI-71}. + +@node SRFI-87 +@subsection SRFI-87 => in case clauses +@cindex SRFI-87 + +Starting from version 2.0.6, Guile's core @code{case} syntax supports +@code{=>} in clauses, as specified by SRFI-87/R7RS. +@xref{Conditionals}. + +@node SRFI-88 +@subsection SRFI-88 Keyword Objects +@cindex SRFI-88 +@cindex keyword objects + +@uref{http://srfi.schemers.org/srfi-88/srfi-88.html, SRFI-88} provides +@dfn{keyword objects}, which are equivalent to Guile's keywords +(@pxref{Keywords}). SRFI-88 keywords can be entered using the +@dfn{postfix keyword syntax}, which consists of an identifier followed +by @code{:} (@pxref{Scheme Read, @code{postfix} keyword syntax}). +SRFI-88 can be made available with: + +@example +(use-modules (srfi srfi-88)) +@end example + +Doing so installs the right reader option for keyword syntax, using +@code{(read-set! keywords 'postfix)}. It also provides the procedures +described below. + +@deffn {Scheme Procedure} keyword? obj +Return @code{#t} if @var{obj} is a keyword. This is the same procedure +as the same-named built-in procedure (@pxref{Keyword Procedures, +@code{keyword?}}). + +@example +(keyword? foo:) @result{} #t +(keyword? 'foo:) @result{} #t +(keyword? "foo") @result{} #f +@end example +@end deffn + +@deffn {Scheme Procedure} keyword->string kw +Return the name of @var{kw} as a string, i.e., without the trailing +colon. The returned string may not be modified, e.g., with +@code{string-set!}. + +@example +(keyword->string foo:) @result{} "foo" +@end example +@end deffn + +@deffn {Scheme Procedure} string->keyword str +Return the keyword object whose name is @var{str}. + +@example +(keyword->string (string->keyword "a b c")) @result{} "a b c" +@end example +@end deffn + +@node SRFI-98 +@subsection SRFI-98 Accessing environment variables. +@cindex SRFI-98 +@cindex environment variables + +This is a portable wrapper around Guile's built-in support for +interacting with the current environment, @xref{Runtime Environment}. + +@deffn {Scheme Procedure} get-environment-variable name +Returns a string containing the value of the environment variable +given by the string @code{name}, or @code{#f} if the named +environment variable is not found. This is equivalent to +@code{(getenv name)}. +@end deffn + +@deffn {Scheme Procedure} get-environment-variables +Returns the names and values of all the environment variables as an +association list in which both the keys and the values are strings. +@end deffn + +@node SRFI-105 +@subsection SRFI-105 Curly-infix expressions. +@cindex SRFI-105 +@cindex curly-infix +@cindex curly-infix-and-bracket-lists + +Guile's built-in reader includes support for SRFI-105 curly-infix +expressions. See @uref{http://srfi.schemers.org/srfi-105/srfi-105.html, +the specification of SRFI-105}. Some examples: + +@example +@{n <= 5@} @result{} (<= n 5) +@{a + b + c@} @result{} (+ a b c) +@{a * @{b + c@}@} @result{} (* a (+ b c)) +@{(- a) / b@} @result{} (/ (- a) b) +@{-(a) / b@} @result{} (/ (- a) b) as well +@{(f a b) + (g h)@} @result{} (+ (f a b) (g h)) +@{f(a b) + g(h)@} @result{} (+ (f a b) (g h)) as well +@{f[a b] + g(h)@} @result{} (+ ($bracket-apply$ f a b) (g h)) +'@{a + f(b) + x@} @result{} '(+ a (f b) x) +@{length(x) >= 6@} @result{} (>= (length x) 6) +@{n-1 + n-2@} @result{} (+ n-1 n-2) +@{n * factorial@{n - 1@}@} @result{} (* n (factorial (- n 1))) +@{@{a > 0@} and @{b >= 1@}@} @result{} (and (> a 0) (>= b 1)) +@{f@{n - 1@}(x)@} @result{} ((f (- n 1)) x) +@{a . z@} @result{} ($nfx$ a . z) +@{a + b - c@} @result{} ($nfx$ a + b - c) +@end example + +To enable curly-infix expressions within a file, place the reader +directive @code{#!curly-infix} before the first use of curly-infix +notation. To globally enable curly-infix expressions in Guile's reader, +set the @code{curly-infix} read option. + +Guile also implements the following non-standard extension to SRFI-105: +if @code{curly-infix} is enabled and there is no other meaning assigned +to square brackets (i.e. the @code{square-brackets} read option is +turned off), then lists within square brackets are read as normal lists +but with the special symbol @code{$bracket-list$} added to the front. +To enable this combination of read options within a file, use the reader +directive @code{#!curly-infix-and-bracket-lists}. For example: + +@example +[a b] @result{} ($bracket-list$ a b) +[a . b] @result{} ($bracket-list$ a . b) +@end example + + +For more information on reader options, @xref{Scheme Read}. + +@node SRFI-111 +@subsection SRFI-111 Boxes. +@cindex SRFI-111 + +@uref{http://srfi.schemers.org/srfi-111/srfi-111.html, SRFI-111} +provides boxes: objects with a single mutable cell. + +@deffn {Scheme Procedure} box value +Return a newly allocated box whose contents is initialized to +@var{value}. +@end deffn + +@deffn {Scheme Procedure} box? obj +Return true if @var{obj} is a box, otherwise return false. +@end deffn + +@deffn {Scheme Procedure} unbox box +Return the current contents of @var{box}. +@end deffn + +@deffn {Scheme Procedure} set-box! box value +Set the contents of @var{box} to @var{value}. +@end deffn + +@c srfi-modules.texi ends here + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/statprof.texi b/doc/ref/statprof.texi new file mode 100644 index 000000000..850c5bd2e --- /dev/null +++ b/doc/ref/statprof.texi @@ -0,0 +1,254 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2013, 2015, 2017 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Statprof +@section Statprof + +Statprof is a statistical profiler for Guile. + +A simple use of statprof would look like this: + +@example +(use-modules (statprof)) +(statprof (lambda () + (map 1+ (iota 1000000)) + #f)) +@end example + +This would run the thunk with statistical profiling, finally displaying +a flat table of statistics which could look something like this: + +@example +% 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) +@end example + +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 @code{% time} column indicates the percentage of the run-time time +spent inside the procedure itself (not counting children). It is +calculated as @code{self seconds}, measuring the amount of time spent in +the procedure, divided by the total run-time. + +@code{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 +@code{#:count-calls? #t} keyword argument to @code{statprof} to record +all calls: + +@example +(use-modules (statprof)) +(statprof (lambda () + (map 1+ (iota 1000000)) + #f) + #:count-calls? #t) +@end example + +The result has an additional @code{calls} column: + +@example +% 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) +@end example + +As you can see, the profile is perturbed: @code{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. + +@heading Implementation notes + +The profiler works by setting the unix profiling signal +@code{ITIMER_PROF} to go off after the interval you define in the call +to @code{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 @code{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. + +@heading Usage + +@deffn {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 @var{thunk}, and return its return values. + +The stack will be sampled @var{hz} times per second, and the thunk +itself will be called @var{loop} times. + +If @var{count-calls?} is true, all procedure calls will be recorded. +This operation is somewhat expensive. + +After the @var{thunk} has been profiled, print out a profile to +@var{port}. If @var{display-style} is @code{flat}, the results will be +printed as a flat profile. Otherwise if @var{display-style} is +@code{tree}, print the results as a tree profile. + +Note that @code{statprof} requires a working profiling timer. Some +platforms do not support profiling timers. @code{(provided? +'ITIMER_PROF)} can be used to check for support of profiling timers. +@end deffn + +Profiling can also be enabled and disabled manually. + +@deffn {Scheme Procedure} statprof-active? +Returns @code{#t} if @code{statprof-start} has been called more times +than @code{statprof-stop}, @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} statprof-start +@deffnx {Scheme Procedure} statprof-stop +Start or stop the profiler. +@end deffn + +@deffn {Scheme Procedure} statprof-reset sample-seconds sample-microseconds count-calls? +Reset the profiling sample interval to @var{sample-seconds} and +@var{sample-microseconds}. If @var{count-calls?} is true, arrange to +instrument procedure calls as well as collecting statistical profiling +data. +@end deffn + +If you use the manual @code{statprof-start}/@code{statprof-stop} +interface, an implicit statprof state will persist starting from the +last call to @code{statprof-reset}, or the first call to +@code{statprof-start}. There are a number of accessors to fetch +statistics from this implicit state. + +@deffn {Scheme Procedure} statprof-accumulated-time +Returns the time accumulated during the last statprof run. +@end deffn + +@deffn {Scheme Procedure} statprof-sample-count +Returns the number of samples taken during the last statprof run. +@end deffn + +@deffn {Scheme Procedure} statprof-fold-call-data proc init +Fold @var{proc} over the call-data accumulated by statprof. This +procedure cannot be called while statprof is active. + +@var{proc} will be called with arguments, @var{call-data} and +@var{prior-result}. +@end deffn + +@deffn {Scheme Procedure} statprof-proc-call-data proc +Returns the call-data associated with @var{proc}, or @code{#f} if none +is available. +@end deffn + +@deffn {Scheme Procedure} statprof-call-data-name cd +@deffnx {Scheme Procedure} statprof-call-data-calls cd +@deffnx {Scheme Procedure} statprof-call-data-cum-samples cd +@deffnx {Scheme Procedure} statprof-call-data-self-samples cd +Accessors for the fields in a statprof call-data object. +@end deffn + +@deffn {Scheme Procedure} statprof-call-data->stats call-data +Returns an object of type @code{statprof-stats}. +@end deffn + +@deffn {Scheme Procedure} statprof-stats-proc-name stats +@deffnx {Scheme Procedure} statprof-stats-%-time-in-proc stats +@deffnx {Scheme Procedure} statprof-stats-cum-secs-in-proc stats +@deffnx {Scheme Procedure} statprof-stats-self-secs-in-proc stats +@deffnx {Scheme Procedure} statprof-stats-calls stats +@deffnx {Scheme Procedure} statprof-stats-self-secs-per-call stats +@deffnx {Scheme Procedure} statprof-stats-cum-secs-per-call stats +Accessors for the fields in a @code{statprof-stats} object. +@end deffn + +@deffn {Scheme Procedure} statprof-display @ + [port=(current-output-port)] [#:style style=flat] +Displays a summary of the statistics collected. Possible values for +@var{style} include: + +@table @code +@item flat +Display a traditional gprof-style flat profile. +@item anomalies +Find statistical anomalies in the data. +@item tree +Display a tree profile. +@end table +@end deffn + +@deffn {Scheme Procedure} statprof-fetch-stacks +Returns a list of stacks, as they were captured since the last call to +@code{statprof-reset}. +@end deffn + +@deffn {Scheme Procedure} statprof-fetch-call-tree [#:precise precise?=#f] +@verbatim +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. +@end verbatim + +@end deffn + +@deffn {Scheme Procedure} gcprof thunk [#:loop] +Like the @code{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 @var{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 +@var{loop} parameter, to cause @var{thunk} to be called @var{loop} +times. +@end deffn diff --git a/doc/ref/sxml-match.texi b/doc/ref/sxml-match.texi new file mode 100644 index 000000000..3adf34751 --- /dev/null +++ b/doc/ref/sxml-match.texi @@ -0,0 +1,377 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2010, 2013 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. +@c +@c Based on the documentation at +@c <http://planet.plt-scheme.org/package-source/jim/sxml-match.plt/1/1/doc.txt>, +@c copyright 2005 Jim Bender, and released under the MIT/X11 license (like the +@c rest of `sxml-match'.) +@c +@c Converted to Texinfo and modified by Ludovic Courtès, 2010. + +@node sxml-match +@section @code{sxml-match}: Pattern Matching of SXML + +@cindex pattern matching (SXML) +@cindex SXML pattern matching + +The @code{(sxml match)} module provides syntactic forms for pattern +matching of SXML trees, in a ``by example'' style reminiscent of the +pattern matching of the @code{syntax-rules} and @code{syntax-case} macro +systems. @xref{SXML}, for more information on SXML. + +The following example@footnote{This example is taken from a paper by +Krishnamurthi et al. Their paper was the first to show the usefulness of the +@code{syntax-rules} style of pattern matching for transformation of XML, though +the language described, XT3D, is an XML language.} provides a brief +illustration, transforming a music album catalog language into HTML. + +@lisp +(define (album->html x) + (sxml-match x + [(album (@@ (title ,t)) (catalog (num ,n) (fmt ,f)) ...) + `(ul (li ,t) + (li (b ,n) (i ,f)) ...)])) +@end lisp + +Three macros are provided: @code{sxml-match}, @code{sxml-match-let}, and +@code{sxml-match-let*}. + +Compared to a standard s-expression pattern matcher (@pxref{Pattern +Matching}), @code{sxml-match} provides the following benefits: + +@itemize +@item +matching of SXML elements does not depend on any degree of normalization of the +SXML; +@item +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; +@item +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. +@end itemize + +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. + +@unnumberedsubsec Syntax + +@code{sxml-match} provides @code{case}-like form for pattern matching of XML +nodes. + +@deffn {Scheme Syntax} sxml-match input-expression clause1 clause2 @dots{} +Match @var{input-expression}, an SXML tree, according to the given @var{clause}s +(one or more), each consisting of a pattern and one or more expressions to be +evaluated if the pattern match succeeds. Optionally, each @var{clause} within +@code{sxml-match} may include a @dfn{guard expression}. +@end deffn + +The pattern notation is based on that of Scheme's @code{syntax-rules} and +@code{syntax-case} macro systems. The grammar for the @code{sxml-match} syntax +is given below: + +@verbatim +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*]) +@end verbatim + +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 @code{sxml-match} pattern +matcher. + +@unnumberedsubsec Matching XML Elements + +The example below illustrates the pattern matching of an XML element: + +@lisp +(sxml-match '(e (@@ (i 1)) 3 4 5) + [(e (@@ (i ,d)) ,a ,b ,c) (list d a b c)] + [,otherwise #f]) +@end lisp + +Each clause in @code{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 @code{e} with an attribute @code{i} and three +children. + +Pattern variables must be ``unquoted'' in the pattern. The above expression +binds @var{d} to @code{1}, @var{a} to @code{3}, @var{b} to @code{4}, and @var{c} +to @code{5}. + +@unnumberedsubsec Ellipses in Patterns + +As in @code{syntax-rules}, ellipses may be used to specify a repeated pattern. +Note that the pattern @code{item ...} specifies zero-or-more matches of the +pattern @code{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 +@code{a} element, within an element @code{d}. + +@lisp +(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 ...) ...)]) +@end lisp + +The above expression returns a value of @code{((1 2 3) (4 5) (6 7 8) (9 10))}. + +@unnumberedsubsec Ellipses in Quasiquote'd Output + +Within the body of an @code{sxml-match} form, a slightly extended version of +quasiquote is provided, which allows the use of ellipses. This is illustrated +in the example below. + +@lisp +(sxml-match '(e 3 4 5 6 7) + [(e ,i ... 6 7) `("start" ,(list 'wrap i) ... "end")] + [,otherwise #f]) +@end lisp + +The general pattern is that @code{`(something ,i ...)} is rewritten as +@code{`(something ,@@i)}. + +@unnumberedsubsec Matching Nodesets + +A nodeset pattern is designated by a list in the pattern, beginning the +identifier list. The example below illustrates matching a nodeset. + +@lisp +(sxml-match '("i" "j" "k" "l" "m") + [(list ,a ,b ,c ,d ,e) + `((p ,a) (p ,b) (p ,c) (p ,d) (p ,e))]) +@end lisp + +This example wraps each nodeset item in an HTML paragraph element. This example +can be rewritten and simplified through using ellipsis: + +@lisp +(sxml-match '("i" "j" "k" "l" "m") + [(list ,i ...) + `((p ,i) ...)]) +@end lisp + +This version will match nodesets of any length, and wrap each item in the +nodeset in an HTML paragraph element. + +@unnumberedsubsec Matching the ``Rest'' of a Nodeset + +Matching the ``rest'' of a nodeset is achieved by using a @code{. rest)} pattern +at the end of an element or nodeset pattern. + +This is illustrated in the example below: + +@lisp +(sxml-match '(e 3 (f 4 5 6) 7) + [(e ,a (f . ,y) ,d) + (list a y d)]) +@end lisp + +The above expression returns @code{(3 (4 5 6) 7)}. + +@unnumberedsubsec 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 +@code{. rest)} pattern at the end of the attribute list pattern. This is +illustrated in the example below: + +@lisp +(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)]) +@end lisp + +The above expression matches the attribute @code{y} and binds a list of the +remaining attributes to the variable @var{qqq}. The result of the above +expression is @code{(2 ((z 1) (x 3)) 4 5 6)}. + +This type of pattern also allows the binding of all attributes: + +@lisp +(sxml-match '(a (@@ (z 1) (y 2) (x 3))) + [(a (@@ . ,qqq)) + qqq]) +@end lisp + +@unnumberedsubsec 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: + +@lisp +(sxml-match '(e 3 4 5) + [(e (@@ (z (,d 1))) ,a ,b ,c) (list d a b c)]) +@end lisp + +The value @code{1} is used when the attribute @code{z} is absent from the +element @code{e}. + +@unnumberedsubsec Guards in Patterns + +Guards may be added to a pattern clause via the @code{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 @code{#t}. + +The use of guard expressions is illustrated below: + +@lisp +(sxml-match '(a 2 3) + ((a ,n) (guard (number? n)) n) + ((a ,m ,n) (guard (number? m) (number? n)) (+ m n))) +@end lisp + +@unnumberedsubsec Catamorphisms + +The example below illustrates the use of explicit recursion within an +@code{sxml-match} form. This example implements a simple calculator for the +basic arithmetic operations, which are represented by the XML elements +@code{plus}, @code{minus}, @code{times}, and @code{div}. + +@lisp +(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)]))) +@end lisp + +Using the catamorphism feature of @code{sxml-match}, a more concise version of +@code{simple-eval} can be written. The pattern @code{,[x]} recursively invokes +the pattern matcher on the value bound in this position. + +@lisp +(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)]))) +@end lisp + +@unnumberedsubsec Named-Catamorphisms + +It is also possible to explicitly name the operator in the ``cata'' position. +Where @code{,[id*]} recurs to the top of the current @code{sxml-match}, +@code{,[cata -> id*]} recurs to @code{cata}. @code{cata} must evaluate to a +procedure which takes one argument, and returns as many values as there are +identifiers following @code{->}. + +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. + +@lisp +(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 ...) ...))])) +@end lisp + +@unnumberedsubsec @code{sxml-match-let} and @code{sxml-match-let*} + +@deffn {Scheme Syntax} sxml-match-let ((pat expr) ...) expression0 expression ... +@deffnx {Scheme Syntax} sxml-match-let* ((pat expr) ...) expression0 expression ... +These forms generalize the @code{let} and @code{let*} forms of Scheme to allow +an XML pattern in the binding position, rather than a simple variable. +@end deffn + +For example, the expression below: + +@lisp +(sxml-match-let ([(a ,i ,j) '(a 1 2)]) + (+ i j)) +@end lisp + +binds the variables @var{i} and @var{j} to @code{1} and @code{2} in the XML +value given. + +@c Local Variables: +@c coding: utf-8 +@c End: diff --git a/doc/ref/sxml.texi b/doc/ref/sxml.texi new file mode 100644 index 000000000..19125091c --- /dev/null +++ b/doc/ref/sxml.texi @@ -0,0 +1,1144 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2013, 2017 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@c SXPath documentation based on SXPath.scm by Oleg Kiselyov, +@c which is in the public domain according to <http://okmij.org/ftp/> +@c and <http://ssax.sourceforge.net/>. + +@node SXML +@section 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: + +@example +<parrot type="African Grey"><name>Alfie</name></parrot> +@end example + +may be represented with the following SXML: + +@example +(parrot (@@ (type "African Grey")) (name "Alfie")) +@end example + +SXML is very general, and is capable of representing all of XML. +Formally, this means that SXML is a conforming implementation of the +@uref{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 @code{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 +@end menu + +@node SXML Overview +@subsection SXML Overview + +(This section needs to be written; volunteers welcome.) + + +@node Reading and Writing XML +@subsection Reading and Writing XML + +The @code{(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. + +@example +(use-modules (sxml simple)) +@end example + +@deffn {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, @var{string-or-port}, which defaults to the current input +port. Returns the resulting SXML document. If @var{string-or-port} is +a port, it will be left pointing at the next available character in the +port. +@end deffn + +As is normal in SXML, XML elements parse as tagged lists. Attributes, +if any, are placed after the tag, within an @code{@@} element. The root +of the resulting XML will be contained in a special tag, @code{*TOP*}. +This tag will contain the root element of the XML, but also any prior +processing instructions. + +@example +(xml->sxml "<foo/>") +@result{} (*TOP* (foo)) +(xml->sxml "<foo>text</foo>") +@result{} (*TOP* (foo "text")) +(xml->sxml "<foo kind=\"bar\">text</foo>") +@result{} (*TOP* (foo (@@ (kind "bar")) "text")) +(xml->sxml "<?xml version=\"1.0\"?><foo/>") +@result{} (*TOP* (*PI* xml "version=\"1.0\"") (foo)) +@end example + +All namespaces in the XML document must be declared, via @code{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 @code{#:namespaces} keyword argument to +@code{xml->sxml}. + +@example +(xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>") +@result{} (*TOP* (http://example.org/ns1:foo "text")) +(xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>" + #:namespaces '((ns1 . "http://example.org/ns1"))) +@result{} (*TOP* (ns1:foo "text")) +(xml->sxml "<foo xmlns:bar=\"http://example.org/ns2\"><bar:baz/></foo>" + #:namespaces '((ns2 . "http://example.org/ns2"))) +@result{} (*TOP* (foo (ns2:baz))) +@end example + +By default, namespaces passed to @code{xml->sxml} are treated as if they +were declared on the root element. Passing a false +@code{#:declare-namespaces?} argument will disable this behavior, +requiring in-document declarations of namespaces before use.. + +@example +(xml->sxml "<foo><ns2:baz/></foo>" + #:namespaces '((ns2 . "http://example.org/ns2"))) +@result{} (*TOP* (foo (ns2:baz))) +(xml->sxml "<foo><ns2:baz/></foo>" + #:namespaces '((ns2 . "http://example.org/ns2")) + #:declare-namespaces? #f) +@result{} error: undeclared namespace: `bar' +@end example + +By default, all whitespace in XML is significant. Passing the +@code{#:trim-whitespace?} keyword argument to @code{xml->sxml} will trim +whitespace in front, behind and between elements, treating it as +``unsignificant''. Whitespace in text fragments is left alone. + +@example +(xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>") +@result{} (*TOP* (foo "\n" (bar " Alfie the parrot! ") "\n")) +(xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>" + #:trim-whitespace? #t) +@result{} (*TOP* (foo (bar " Alfie the parrot! "))) +@end example + +Parsed entities may be declared with the @code{#:entities} keyword +argument, or handled with the @code{#:default-entity-handler}. By +default, only the standard @code{<}, @code{>}, @code{&}, +@code{'} and @code{"} entities are defined, as well as the +@code{&#@var{N};} and @code{&#x@var{N};} (decimal and hexadecimal) +numeric character entities. + +@example +(xml->sxml "<foo>&</foo>") +@result{} (*TOP* (foo "&")) +(xml->sxml "<foo> </foo>") +@result{} error: undefined entity: nbsp +(xml->sxml "<foo> </foo>") +@result{} (*TOP* (foo "\xa0")) +(xml->sxml "<foo> </foo>" + #:entities '((nbsp . "\xa0"))) +@result{} (*TOP* (foo "\xa0")) +(xml->sxml "<foo> &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))))) +@print{} <unknown file>:0:17: undefined entitity: foo +@result{} (*TOP* (foo "\xa0 foo")) +@end example + +By default, @code{xml->sxml} skips over the @code{<!DOCTYPE>} +declaration, if any. This behavior can be overridden with the +@code{#:doctype-handler} argument, which should be a procedure of three +arguments: the @dfn{docname} (a symbol), @dfn{systemid} (a string), and +the internal doctype subset (as a string or @code{#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 @code{#:entities} and @code{#:namespaces} keyword arguments, +in the same format that @code{xml->sxml} itself takes. These entities +and namespaces will be prepended to those given to the @code{xml->sxml} +invocation. + +@example +(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) +@result{} (*TOP* (p (i "Hello, world!"))) +@end example + +If the document has no doctype declaration, the @var{doctype-handler} is +invoked with @code{#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. + +@deffn {Scheme Procedure} sxml->xml tree [port] +Serialize the SXML tree @var{tree} as XML. The output will be written to +the current output port, unless the optional argument @var{port} is +present. +@end deffn + +@deffn {Scheme Procedure} sxml->string sxml +Detag an sxml tree @var{sxml} into a string. Does not perform any +formatting. +@end deffn + +@node SSAX +@subsection SSAX: A Functional XML Parsing Toolkit + +Guile's XML parser is based on Oleg Kiselyov's powerful XML parsing +toolkit, SSAX. + +@subsubsection 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 user, 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 @emph{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 @code{xml->sxml} interface from the @code{(sxml simple)} module is a +DOM-style parser built using SSAX, though it returns SXML instead of DOM +objects. + +@subsubsection Implementation + +@code{(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. @emph{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 @var{port}, there is another monad -- @var{seed}. Most of +the middle- and high-level parsers are single-threaded through the +@var{seed}. The functions of this framework do not process or affect +the @var{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: +@code{SSAX:make-elem-parser} or @code{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 @var{seed}, among other parameters, and must return the +new @var{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 + +@smallexample + 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) +@end smallexample + +Compare the last two equations with the left fold + +@smallexample + fold-left kons elem:list seed = fold-left kons list (kons elem seed) +@end smallexample + +The real parser created by @code{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 +@uref{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: +@uref{http://www.w3.org/TR/REC-xml-names/}. + +Other links: + +@table @asis +@item [1] +Jeremy Gibbons, Geraint Jones, "The Under-appreciated Unfold," Proc. +ICFP'98, 1998, pp. 273-279. + +@item [2] +Richard S. Bird, The promotion and accumulation strategies in +transformational programming, ACM Trans. Progr. Lang. Systems, +6(4):487-504, October 1984. + +@item [3] +Ralf Hinze, "Deriving Backtracking Monad Transformers," Functional +Pearl. Proc ICFP'00, pp. 186-197. + +@end table + +@subsubsection Usage +@deffn {Scheme Procedure} current-ssax-error-port +@end deffn + +@deffn {Scheme Procedure} with-ssax-error-to-port port thunk +@end deffn + +@deffn {Scheme Procedure} xml-token? _ +@verbatim + -- Scheme Procedure: pair? x + Return `#t' if X is a pair; otherwise return `#f'. + + +@end verbatim +@end deffn + +@deffn {Scheme Syntax} xml-token-kind token +@end deffn + +@deffn {Scheme Syntax} xml-token-head token +@end deffn + +@deffn {Scheme Procedure} make-empty-attlist +@end deffn + +@deffn {Scheme Procedure} attlist-add attlist name-value +@end deffn + +@deffn {Scheme Procedure} attlist-null? x +Return @code{#t} if @var{x} is the empty list, else @code{#f}. +@end deffn + +@deffn {Scheme Procedure} attlist-remove-top attlist +@end deffn + +@deffn {Scheme Procedure} attlist->alist attlist +@end deffn + +@deffn {Scheme Procedure} attlist-fold kons knil lis1 +@end deffn + +@deffn {Scheme Procedure} define-parsed-entity! entity str +Define a new parsed entity. @var{entity} should be a symbol. + +Instances of &@var{entity}; in XML text will be replaced with the string +@var{str}, which will then be parsed. +@end deffn + +@deffn {Scheme Procedure} reset-parsed-entity-definitions! +Restore the set of parsed entity definitions to its initial state. +@end deffn + +@deffn {Scheme Procedure} ssax:uri-string->symbol uri-str +@end deffn + +@deffn {Scheme Procedure} ssax:skip-internal-dtd port +@end deffn + +@deffn {Scheme Procedure} ssax:read-pi-body-as-string port +@end deffn + +@deffn {Scheme Procedure} ssax:reverse-collect-str-drop-ws fragments +@end deffn + +@deffn {Scheme Procedure} ssax:read-markup-token port +@end deffn + +@deffn {Scheme Procedure} ssax:read-cdata-body port str-handler seed +@end deffn + +@deffn {Scheme Procedure} ssax:read-char-ref port +@end deffn + +@deffn {Scheme Procedure} ssax:read-attributes port entities +@end deffn + +@deffn {Scheme Procedure} ssax:complete-start-tag tag-head port elems entities namespaces +@end deffn + +@deffn {Scheme Procedure} ssax:read-external-id port +@end deffn + +@deffn {Scheme Procedure} ssax:read-char-data port expect-eof? str-handler seed +@end deffn + +@deffn {Scheme Procedure} ssax:xml->sxml port namespace-prefix-assig +@end deffn + +@deffn {Scheme Syntax} ssax:make-parser . kw-val-pairs +@end deffn + +@deffn {Scheme Syntax} ssax:make-pi-parser orig-handlers +@end deffn + +@deffn {Scheme Syntax} ssax:make-elem-parser my-new-level-seed my-finish-element my-char-data-handler my-pi-handlers +@end deffn + +@node Transforming SXML +@subsection Transforming SXML +@subsubsection Overview +@heading SXML expression tree transformers +@subheading Pre-Post-order traversal of a tree and creation of a new tree +@smallexample +pre-post-order:: <tree> x <bindings> -> <new-tree> +@end smallexample + +where + +@smallexample + <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> +@end smallexample + +The pre-post-order function visits the nodes and nodelists +pre-post-order (depth-first). For each @code{<Node>} of the form +@code{(@var{name} <Node> ...)}, it looks up an association with the +given @var{name} among its @var{<bindings>}. If failed, +@code{pre-post-order} tries to locate a @code{*default*} binding. It's +an error if the latter attempt fails as well. Having found a binding, +the @code{pre-post-order} function first checks to see if the binding is +of the form + +@smallexample + (<trigger-symbol> *preorder* . <handler>) +@end smallexample + +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 @var{<new-bindings>} prepended to the +@var{<bindings>} in effect. The result of these calls is passed to the +@var{<handler>} (along with the head of the current @var{<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 @code{<tree>}, replaces the current @var{<Node>}. If the current +@var{<Node>} is a text string or other atom, a special binding with a +symbol @code{*text*} is looked up. + +A binding can also be of a form + +@smallexample + (<trigger-symbol> *macro* . <handler>) +@end smallexample + +This is equivalent to @code{*preorder*} described above. However, the +result is re-processed again, with the current stylesheet. + +@subsubsection Usage +@deffn {Scheme Procedure} SRV:send-reply . fragments +Output the @var{fragments} to the current output port. + +The fragments are a list of strings, characters, numbers, thunks, +@code{#f}, @code{#t} -- and other fragments. The function traverses the +tree depth-first, writes out strings and characters, executes thunks, +and ignores @code{#f} and @code{'()}. The function returns @code{#t} if +anything was written at all; otherwise the result is @code{#f} If +@code{#t} occurs among the fragments, it is not written out but causes +the result of @code{SRV:send-reply} to be @code{#t}. +@end deffn + +@deffn {Scheme Procedure} foldts fdown fup fhere seed tree +@end deffn + +@deffn {Scheme Procedure} post-order tree bindings +@end deffn + +@deffn {Scheme Procedure} pre-post-order tree bindings +@end deffn + +@deffn {Scheme Procedure} replace-range beg-pred end-pred forest +@end deffn + +@node SXML Tree Fold +@subsection SXML Tree Fold +@subsubsection Overview +@code{(sxml fold)} defines a number of variants of the @dfn{fold} +algorithm for use in transforming SXML trees. Additionally it defines +the layout operator, @code{fold-layout}, which might be described as a +context-passing variant of SSAX's @code{pre-post-order}. + +@subsubsection Usage +@deffn {Scheme Procedure} foldt fup fhere tree +The standard multithreaded tree fold. + +@var{fup} is of type [a] -> a. @var{fhere} is of type object -> a. +@end deffn + +@deffn {Scheme Procedure} foldts fdown fup fhere seed tree +The single-threaded tree fold originally defined in SSAX. @xref{SSAX}, +for more information. +@end deffn + +@deffn {Scheme Procedure} foldts* fdown fup fhere seed tree +A variant of @code{foldts} that allows pre-order tree +rewrites. Originally defined in Andy Wingo's 2007 paper, +@emph{Applications of fold to XML transformation}. +@end deffn + +@deffn {Scheme Procedure} fold-values proc list . seeds +A variant of @code{fold} that allows multi-valued seeds. Note that the +order of the arguments differs from that of @code{fold}. @xref{SRFI-1 +Fold and Map}. +@end deffn + +@deffn {Scheme Procedure} foldts*-values fdown fup fhere tree . seeds +A variant of @code{foldts*} that allows multi-valued +seeds. Originally defined in Andy Wingo's 2007 paper, @emph{Applications +of fold to XML transformation}. +@end deffn + +@deffn {Scheme Procedure} fold-layout tree bindings params layout stylesheet +A traversal combinator in the spirit of @code{pre-post-order}. +@xref{Transforming SXML}. + +@code{fold-layout} was originally presented in Andy Wingo's 2007 paper, +@emph{Applications of fold to XML transformation}. + +@example +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>) +@end example + +@table @var +@item pre-layout-handler +A function of three arguments: + +@table @var +@item kids +the kids of the current node, before traversal + +@item params +the params of the current node + +@item layout +the layout coming into this node + +@end table + +@var{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. + +@item post-handler +A function of five arguments: + +@table @var +@item tag +the current tag being processed + +@item params +the params of the current node + +@item layout +the layout coming into the current node, before any kids were processed + +@item klayout +the layout after processing all of the children + +@item kids +the already-processed child nodes + +@end table + +@var{post-handler} should return two values, the layout to pass to the +next node and the final tree. + +@item text-handler +@var{text-handler} is a function of three arguments: + +@table @var +@item text +the string + +@item params +the current params + +@item layout +the current layout + +@end table + +@var{text-handler} should return two values, the layout to pass to the +next node and the value to which the string should transform. + +@end table +@end deffn + +@node SXPath +@subsection SXPath +@subsubsection Overview +@heading 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 @code{(sxml ssax)} for the +definition of SXML and more details. SXPath is also a translation into +Scheme of an XML Path Language, @uref{http://www.w3.org/TR/xpath,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': + +@example + <Node> ::= <Element> | <attributes-coll> | <attrib> + | "text string" | <PI> +@end example + +This production can also be described as + +@example + <Node> ::= (name . <Nodeset>) | "text string" +@end example + +An (ordered) set of nodes is just a list of the constituent nodes: + +@example + <Nodeset> ::= (<Node> ...) +@end example + +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 singe 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 @emph{elegantly} implement XPath +as a sequence of projection and filtering primitives -- converters -- +joined by @dfn{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 @code{sxpath} procedure. +@xref{sxpath-procedure-docs,,SXPath procedure documentation}. + +The regression test suite at the end of the file @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. + +@subsubsection 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: + +@example +type Converter = Node|Nodeset -> Nodeset +@end example + +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 @code{#f} in denoting failure. + +@deffn {Scheme Procedure} nodeset? x +Return @code{#t} if @var{x} is a nodeset. +@end deffn + +@deffn {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 @code{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 @var{crit} is a symbol, one of the following: + +@table @code +@item id +tests if the node has the right name (id) + +@item @@ +tests if the node is an <attributes-coll> + +@item * +tests if the node is an <Element> + +@item *text* +tests if the node is a text node + +@item *PI* +tests if the node is a PI (processing instruction) node + +@item *any* +@code{#t} for any type of node +@end table +@end deffn + +@deffn {Scheme Procedure} node-eq? other +A curried equivalence converter predicate that takes a node @var{other} +and returns a function that takes another node. The two nodes are +compared using @code{eq?}. +@end deffn + +@deffn {Scheme Procedure} node-equal? other +A curried equivalence converter predicate that takes a node @var{other} +and returns a function that takes another node. The two nodes are +compared using @code{equal?}. +@end deffn + +@deffn {Scheme Procedure} node-pos n +Select the @var{n}'th element of a nodeset and return as a singular +nodeset. If the @var{n}'th element does not exist, return an empty +nodeset. If @var{n} is a negative number the node is picked from the +tail of the list. + +@example +((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. +@end example +@end deffn + +@deffn {Scheme Procedure} filter pred? +A filter applicator, which introduces a filtering context. The argument +converter @var{pred?} is considered a predicate, with either @code{#f} +or @code{nil} meaning failure. +@end deffn + +@deffn {Scheme Procedure} take-until pred? +@example +take-until:: Converter -> Converter, or +take-until:: Pred -> Node|Nodeset -> Nodeset +@end example + +Given a converter-predicate @var{pred?} and a nodeset, apply the +predicate to each element of the nodeset, until the predicate yields +anything but @code{#f} or @code{nil}. Return the elements of the input +nodeset that have been processed until that moment (that is, which fail +the predicate). + +@code{take-until} is a variation of the @code{filter} above: +@code{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 @code{((take-until (not pred)) nset)} is a subset -- to be +more precise, a prefix -- of the nodeset returned by @code{((filter +pred) nset)}. +@end deffn + +@deffn {Scheme Procedure} take-after pred? +@example +take-after:: Converter -> Converter, or +take-after:: Pred -> Node|Nodeset -> Nodeset +@end example + +Given a converter-predicate @var{pred?} and a nodeset, apply the +predicate to each element of the nodeset, until the predicate yields +anything but @code{#f} or @code{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. + +@code{take-after} along with @code{take-until} partition an input +nodeset into three parts: the first element that satisfies a predicate, +all preceding elements and all following elements. +@end deffn + +@deffn {Scheme Procedure} map-union proc lst +Apply @var{proc} to each element of @var{lst} and return the list of results. +If @var{proc} returns a nodeset, splice it into the result + +From another point of view, @code{map-union} is a function +@code{Converter->Converter}, which places an argument-converter in a joining +context. +@end deffn + +@deffn {Scheme Procedure} node-reverse node-or-nodeset +@example +node-reverse :: Converter, or +node-reverse:: Node|Nodeset -> Nodeset +@end example + +Reverses the order of nodes in the nodeset. This basic converter is +needed to implement a reverse document order (see the XPath +Recommendation). +@end deffn + +@deffn {Scheme Procedure} node-trace title +@example +node-trace:: String -> Converter +@end example + +@code{(node-trace title)} is an identity converter. In addition it +prints out the node or nodeset it is applied to, prefixed with the +@var{title}. This converter is very useful for debugging. +@end deffn + +@subsubsection 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 +@dfn{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, @code{map-union} and +@code{filter} applicators, and the nodeset union. + +@deffn {Scheme Procedure} select-kids test-pred? +@code{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 +@var{test-pred?}. +@end deffn + +@deffn {Scheme Procedure} node-self pred? +Similar to @code{select-kids} except that the predicate @var{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. +@end deffn + +@deffn {Scheme Procedure} node-join . selectors +@example +node-join:: [LocPath] -> Node|Nodeset -> Nodeset, or +node-join:: [Converter] -> Converter +@end example + +Join the sequence of location steps or paths as described above. +@end deffn + +@deffn {Scheme Procedure} node-reduce . converters +@example +node-reduce:: [LocPath] -> Node|Nodeset -> Nodeset, or +node-reduce:: [Converter] -> Converter +@end example + +A regular functional composition of converters. From a different point +of view, @code{((apply node-reduce converters) nodeset)} is equivalent +to @code{(foldl apply nodeset converters)}, i.e., folding, or reducing, +a list of converters with the nodeset as a seed. +@end deffn + +@deffn {Scheme Procedure} node-or . converters +@example +node-or:: [Converter] -> Converter +@end example + +This combinator applies all converters to a given node and produces the +union of their results. This combinator corresponds to a union +(@code{|} operation) for XPath location paths. +@end deffn + +@deffn {Scheme Procedure} node-closure test-pred? +@example +node-closure:: Converter -> Converter +@end example + +Select all @emph{descendants} of a node that satisfy a +converter-predicate @var{test-pred?}. This combinator is similar to +@code{select-kids} but applies to grand... children as well. This +combinator implements the @code{descendant::} XPath axis. Conceptually, +this combinator can be expressed as + +@example +(define (node-closure f) + (node-or + (select-kids f) + (node-reduce (select-kids (node-typeof? '*)) (node-closure f)))) +@end example + +This definition, as written, looks somewhat like a fixpoint, and it will +run forever. It is obvious however that sooner or later +@code{(select-kids (node-typeof? '*))} will return an empty nodeset. At +this point further iterations will no longer affect the result and can +be stopped. +@end deffn + +@deffn {Scheme Procedure} node-parent rootnode +@example +node-parent:: RootNode -> Converter +@end example + +@code{(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 @var{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, + +@verbatim + parent(x) = { y | y=subnode*(root), x=subnode(y) } +@end verbatim + +Therefore, @code{node-parent} is not the fundamental converter: it can +be expressed through the existing ones. Yet @code{node-parent} is a +rather convenient converter. It corresponds to a @code{parent::} axis +of SXPath. Note that the @code{parent::} axis can be used with an +attribute node as well. +@end deffn + +@anchor{sxpath-procedure-docs} +@deffn {Scheme Procedure} sxpath path +Evaluate an abbreviated SXPath. + +@example +sxpath:: AbbrPath -> Converter, or +sxpath:: AbbrPath -> Node|Nodeset -> Nodeset +@end example + +@var{path} is a list. It is translated to the full SXPath according to +the following rewriting rules: + +@example +(sxpath '()) +@result{} (node-join) + +(sxpath '(path-component ...)) +@result{} (node-join (sxpath1 path-component) (sxpath '(...))) + +(sxpath1 '//) +@result{} (node-or + (node-self (node-typeof? '*any*)) + (node-closure (node-typeof? '*any*))) + +(sxpath1 '(equal? x)) +@result{} (select-kids (node-equal? x)) + +(sxpath1 '(eq? x)) +@result{} (select-kids (node-eq? x)) + +(sxpath1 ?symbol) +@result{} (select-kids (node-typeof? ?symbol) + +(sxpath1 procedure) +@result{} procedure + +(sxpath1 '(?symbol ...)) +@result{} (sxpath1 '((?symbol) ...)) + +(sxpath1 '(path reducer ...)) +@result{} (node-reduce (sxpath path) (sxpathr reducer) ...) + +(sxpathr number) +@result{} (node-pos number) + +(sxpathr path-filter) +@result{} (filter (sxpath path-filter)) +@end example +@end deffn + +@node sxml ssax input-parse +@subsection (sxml ssax input-parse) +@subsubsection 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, @code{*eof*}. + +The input stream to parse is specified as a @dfn{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 +@code{parser-error}. The arguments will be of the form @code{(@var{port} +@var{message} @var{specialising-msg}*)}. + +The first argument is a port, which typically points to the offending +character or its neighborhood. You can then use @code{port-column} and +@code{port-line} to query the current position. @var{message} is the +description of the error. Other arguments supply more details about the +problem. + +@subsubsection Usage +@deffn {Scheme Procedure} peek-next-char [port] +@end deffn + +@deffn {Scheme Procedure} assert-curr-char expected-chars comment [port] +@end deffn + +@deffn {Scheme Procedure} skip-until arg [port] +@end deffn + +@deffn {Scheme Procedure} skip-while skip-chars [port] +@end deffn + +@deffn {Scheme Procedure} next-token prefix-skipped-chars break-chars [comment] [port] +@end deffn + +@deffn {Scheme Procedure} next-token-of incl-list/pred [port] +@end deffn + +@deffn {Scheme Procedure} read-text-line [port] +@end deffn + +@deffn {Scheme Procedure} read-string n [port] +@end deffn + +@deffn {Scheme Procedure} find-string-from-port? _ _ . _ +Looks for @var{str} in @var{<input-port>}, optionally within the first +@var{max-no-char} characters. +@end deffn + +@node sxml apply-templates +@subsection (sxml apply-templates) +@subsubsection Overview +Pre-order traversal of a tree and creation of a new tree: + +@smallexample + apply-templates:: tree x <templates> -> <new-tree> +@end smallexample + +where + +@smallexample + <templates> ::= (<template> ...) + <template> ::= (<node-test> <node-test> ... <node-test> . <handler>) + <node-test> ::= an argument to node-typeof? above + <handler> ::= <tree> -> <new-tree> +@end smallexample + +This procedure does a @emph{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 @code{<tree>}, +takes place of the current node in the resulting tree. The name of the +function is not accidental: it resembles rather closely an +@code{apply-templates} function of XSLT. + +@subsubsection Usage +@deffn {Scheme Procedure} apply-templates tree templates +@end deffn + diff --git a/doc/ref/texinfo.texi b/doc/ref/texinfo.texi new file mode 100644 index 000000000..5006fd427 --- /dev/null +++ b/doc/ref/texinfo.texi @@ -0,0 +1,594 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2013 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@c Note: Don't use "Texinfo" as the node name here because this leads to +@c a clash in the HTML output between texinfo.html (from the "texinfo" +@c node) and Texinfo.html on case-insensitive file systems such as +@c HFS+ (MacOS X). +@node Texinfo Processing +@section Texinfo Processing + +@menu +* texinfo:: Parse texinfo files or fragments into @code{stexi}, a scheme representation +* texinfo docbook:: Transform a subset of docbook into @code{stexi} +* texinfo html:: Transform @code{stexi} into HTML +* texinfo indexing:: Extract an index from a piece of @code{stexi} +* texinfo string-utils:: String utility functions used by the texinfo processor +* texinfo plain-text:: Render @code{stexi} as plain text +* texinfo serialize:: Render @code{stexi} as texinfo +* texinfo reflection:: Enable texinfo across Guile's help system +@end menu + +@node texinfo +@subsection (texinfo) +@subsubsection Overview +@subheading 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 @code{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. + +@subheading Notes on the SXML vocabulary +Consider the following texinfo fragment: + +@example + @@deffn Primitive set-car! pair value + This function... + @@end deffn +@end example + +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 @code{@@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'. + +@subsubsection Usage +@anchor{texinfo call-with-file-and-dir}@defun call-with-file-and-dir filename proc +Call the one-argument procedure @var{proc} with an input port that reads +from @var{filename}. During the dynamic extent of @var{proc}'s +execution, the current directory will be @code{(dirname +@var{filename})}. This is useful for parsing documents that can include +files by relative path name. + +@end defun + +@anchor{texinfo texi-command-specs}@defvar texi-command-specs +@end defvar + +@anchor{texinfo texi-command-depth}@defun texi-command-depth command max-depth +Given the texinfo command @var{command}, return its nesting level, or +@code{#f} if it nests too deep for @var{max-depth}. + +Examples: + +@example + (texi-command-depth 'chapter 4) @result{} 1 + (texi-command-depth 'top 4) @result{} 0 + (texi-command-depth 'subsection 4) @result{} 3 + (texi-command-depth 'appendixsubsec 4) @result{} 3 + (texi-command-depth 'subsection 2) @result{} #f +@end example + +@end defun + +@anchor{texinfo texi-fragment->stexi}@defun texi-fragment->stexi string-or-port +Parse the texinfo commands in @var{string-or-port}, and return the +resultant stexi tree. The head of the tree will be the special command, +@code{*fragment*}. + +@end defun + +@anchor{texinfo texi->stexi}@defun texi->stexi port +Read a full texinfo document from @var{port} and return the parsed stexi +tree. The parsing will start at the @code{@@settitle} and end at +@code{@@bye} or EOF. + +@end defun + +@anchor{texinfo stexi->sxml}@defun stexi->sxml tree +Transform the stexi tree @var{tree} into sxml. This involves replacing +the @code{%} element that keeps the texinfo arguments with an element +for each argument. + +FIXME: right now it just changes % to @code{texinfo-arguments} -- that +doesn't hang with the idea of making a dtd at some point + +@end defun + +@node texinfo docbook +@subsection (texinfo docbook) +@subsubsection Overview +@c +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. + +@subsubsection Usage +@anchor{texinfo docbook *sdocbook->stexi-rules*}@defvar *sdocbook->stexi-rules* +@end defvar + +@anchor{texinfo docbook *sdocbook-block-commands*}@defvar *sdocbook-block-commands* +@end defvar + +@anchor{texinfo docbook sdocbook-flatten}@defun 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 @code{refsect2} normally +appears inside a @code{refsect1}. Logical divisions in the document are +represented via the tree topology; a @code{refsect2} element +@emph{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 @code{@@subsection}, and block +elements do not nest inside each other. + +This function takes a nested sdocbook fragment @var{sdocbook} and +flattens all of the sections, such that e.g. + +@example + (refsect1 (refsect2 (para "Hello"))) +@end example + +becomes + +@example + ((refsect1) (refsect2) (para "Hello")) +@end example + +Oftentimes (always?) sectioning elements have @code{<title>} as their +first element child; users interested in processing the @code{refsect*} +elements into proper sectioning elements like @code{chapter} might be +interested in @code{replace-titles} and @code{filter-empty-elements}. +@xref{texinfo docbook replace-titles,,replace-titles}, and @ref{texinfo +docbook filter-empty-elements,,filter-empty-elements}. + +Returns a nodeset; that is to say, an untagged list of stexi elements. +@xref{SXPath}, for the definition of a nodeset. + +@end defun + +@anchor{texinfo docbook filter-empty-elements}@defun filter-empty-elements sdocbook +Filters out empty elements in an sdocbook nodeset. Mostly useful after +running @code{sdocbook-flatten}. + +@end defun + +@anchor{texinfo docbook replace-titles}@defun replace-titles sdocbook-fragment +Iterate over the sdocbook nodeset @var{sdocbook-fragment}, transforming +contiguous @code{refsect} and @code{title} elements into the appropriate +texinfo sectioning command. Most useful after having run +@code{sdocbook-flatten}. + +For example: + +@example + (replace-titles '((refsect1) (title "Foo") (para "Bar."))) + @result{} '((chapter "Foo") (para "Bar.")) +@end example + +@end defun + +@node texinfo html +@subsection (texinfo html) +@subsubsection Overview +This module implements transformation from @code{stexi} to HTML. Note +that the output of @code{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 @code{sxml->xml}. +@xref{Reading and Writing XML}. + +References (i.e., the @code{@@ref} family of commands) are resolved by a +@dfn{ref-resolver}. @xref{texinfo html +add-ref-resolver!,add-ref-resolver!}. + +@subsubsection Usage +@anchor{texinfo html add-ref-resolver!}@defun add-ref-resolver! proc +Add @var{proc} to the head of the list of ref-resolvers. @var{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 @code{#f} to pass control to the next +ref-resolver in the list. + +The default ref-resolver will return the concatenation of the manual +name, @code{#}, and the node name. + +@end defun + +@anchor{texinfo html stexi->shtml}@defun stexi->shtml tree +Transform the stexi @var{tree} into shtml, resolving references via +ref-resolvers. See the module commentary for more details. + +@end defun + +@anchor{texinfo html urlify}@defun urlify str +@end defun + +@node texinfo indexing +@subsection (texinfo indexing) +@subsubsection Overview +@c texinfo formatting +Given a piece of stexi, return an index of a specified variety. + +Note that currently, @code{stexi-extract-index} doesn't differentiate +between different kinds of index entries. That's a bug ;) + +@subsubsection Usage +@anchor{texinfo indexing stexi-extract-index}@defun stexi-extract-index tree manual-name kind +Given an stexi tree @var{tree}, index all of the entries of type +@var{kind}. @var{kind} can be one of the predefined texinfo indices +(@code{concept}, @code{variable}, @code{function}, @code{key}, +@code{program}, @code{type}) or one of the special symbols @code{auto} +or @code{all}. @code{auto} will scan the stext for a @code{(printindex)} +statement, and @code{all} will generate an index from all entries, +regardless of type. + +The returned index is a list of pairs, the @sc{car} of which is the +entry (a string) and the @sc{cdr} of which is a node name (a string). + +@end defun + +@node texinfo string-utils +@subsection (texinfo string-utils) +@subsubsection Overview +Module @samp{(texinfo string-utils)} provides various string-related +functions useful to Guile's texinfo support. + +@subsubsection Usage +@anchor{texinfo string-utils escape-special-chars}@defun escape-special-chars str special-chars escape-char +Returns a copy of @var{str} with all given special characters preceded +by the given @var{escape-char}. + +@var{special-chars} can either be a single character, or a string +consisting of all the special characters. + +@lisp +;; make a string regexp-safe... + (escape-special-chars "***(Example String)***" + "[]()/*." + #\\) +=> "\\*\\*\\*\\(Example String\\)\\*\\*\\*" + +;; also can escape a singe char... + (escape-special-chars "richardt@@vzavenue.net" + #\@@ + #\@@) +=> "richardt@@@@vzavenue.net" +@end lisp + +@end defun + +@anchor{texinfo string-utils transform-string}@defun transform-string str match? replace [start] [end] +Uses @var{match?} against each character in @var{str}, and performs a +replacement on each character for which matches are found. + +@var{match?} may either be a function, a character, a string, or +@code{#t}. If @var{match?} is a function, then it takes a single +character as input, and should return @samp{#t} for matches. +@var{match?} is a character, it is compared to each string character +using @code{char=?}. If @var{match?} is a string, then any character in +that string will be considered a match. @code{#t} will cause every +character to be a match. + +If @var{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 +@samp{display}. If @var{replace} is anything else, it is sent through +the output string via @samp{display}. + +Note that the replacement for the matched characters does not need to be +a single character. That is what differentiates this function from +@samp{string-map}, and what makes it useful for applications such as +converting @samp{#\&} to @samp{"&"} in web page text. Some other +functions in this module are just wrappers around common uses of +@samp{transform-string}. Transformations not possible with this function +should probably be done with regular expressions. + +If @var{start} and @var{end} are given, they control which portion of +the string undergoes transformation. The entire input string is still +output, though. So, if @var{start} is @samp{5}, then the first five +characters of @var{str} will still appear in the returned string. + +@lisp +; these two are equivalent... + (transform-string str #\space #\-) ; change all spaces to -'s + (transform-string str (lambda (c) (char=? #\space c)) #\-) +@end lisp + +@end defun + +@anchor{texinfo string-utils expand-tabs}@defun expand-tabs str [tab-size] +Returns a copy of @var{str} with all tabs expanded to spaces. +@var{tab-size} defaults to 8. + +Assuming tab size of 8, this is equivalent to: + +@lisp + (transform-string str #\tab " ") +@end lisp + +@end defun + +@anchor{texinfo string-utils center-string}@defun center-string str [width] [chr] [rchr] +Returns a copy of @var{str} centered in a field of @var{width} +characters. Any needed padding is done by character @var{chr}, which +defaults to @samp{#\space}. If @var{rchr} is provided, then the padding +to the right will use it instead. See the examples below. left and +@var{rchr} on the right. The default @var{width} is 80. The default +@var{chr} and @var{rchr} is @samp{#\space}. The string is never +truncated. + +@lisp + (center-string "Richard Todd" 24) +=> " Richard Todd " + + (center-string " Richard Todd " 24 #\=) +=> "===== Richard Todd =====" + + (center-string " Richard Todd " 24 #\< #\>) +=> "<<<<< Richard Todd >>>>>" +@end lisp + +@end defun + +@anchor{texinfo string-utils left-justify-string}@defun left-justify-string str [width] [chr] +@code{left-justify-string str [width chr]}. Returns a copy of @var{str} +padded with @var{chr} such that it is left justified in a field of +@var{width} characters. The default @var{width} is 80. Unlike +@samp{string-pad} from srfi-13, the string is never truncated. + +@end defun + +@anchor{texinfo string-utils right-justify-string}@defun right-justify-string str [width] [chr] +Returns a copy of @var{str} padded with @var{chr} such that it is right +justified in a field of @var{width} characters. The default @var{width} +is 80. The default @var{chr} is @samp{#\space}. Unlike @samp{string-pad} +from srfi-13, the string is never truncated. + +@end defun + +@anchor{texinfo string-utils collapse-repeated-chars}@defun collapse-repeated-chars str [chr] [num] +Returns a copy of @var{str} with all repeated instances of @var{chr} +collapsed down to at most @var{num} instances. The default value for +@var{chr} is @samp{#\space}, and the default value for @var{num} is 1. + +@lisp + (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" +@end lisp + +@end defun + +@anchor{texinfo string-utils make-text-wrapper}@defun 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. + +@table @code +@item #:line-width +This is the target length used when deciding where to wrap lines. +Default is 80. + +@item #:expand-tabs? +Boolean describing whether tabs in the input should be expanded. Default +is #t. + +@item #:tab-width +If tabs are expanded, this will be the number of spaces to which they +expand. Default is 8. + +@item #: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 @samp{#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. + +@item #:initial-indent +Defines a string that will be put in front of the first line of wrapped +text. Default is the empty string, ``''. + +@item #: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, ``''. + +@item #: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 @code{#:line-width}. + +@end table + +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. + +@end defun + +@anchor{texinfo string-utils fill-string}@defun fill-string str . kwargs +Wraps the text given in string @var{str} according to the parameters +provided in @var{kwargs}, or the default setting if they are not given. +Returns a single string with the wrapped text. Valid keyword arguments +are discussed in @code{make-text-wrapper}. + +@end defun + +@anchor{texinfo string-utils string->wrapped-lines}@defun string->wrapped-lines str . kwargs +@code{string->wrapped-lines str keywds ...}. Wraps the text given in +string @var{str} according to the parameters provided in @var{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 @code{make-text-wrapper}. + +@end defun + +@node texinfo plain-text +@subsection (texinfo plain-text) +@subsubsection Overview +Transformation from stexi to plain-text. Strives to re-create the output +from @code{info}; comes pretty damn close. + +@subsubsection Usage +@anchor{texinfo plain-text stexi->plain-text}@defun stexi->plain-text tree +Transform @var{tree} into plain text. Returns a string. + +@end defun + +@node texinfo serialize +@subsection (texinfo serialize) +@subsubsection Overview +Serialization of @code{stexi} to plain texinfo. + +@subsubsection Usage +@anchor{texinfo serialize stexi->texi}@defun stexi->texi tree +Serialize the stexi @var{tree} into plain texinfo. + +@end defun + +@node texinfo reflection +@subsection (texinfo reflection) +@subsubsection Overview +Routines to generare @code{stexi} documentation for objects and modules. + +Note that in this context, an @dfn{object} is just a value associated +with a location. It has nothing to do with GOOPS. + +@subsubsection Usage +@anchor{texinfo reflection module-stexi-documentation}@defun module-stexi-documentation sym-name [%docs-resolver] [#:docs-resolver] +Return documentation for the module named @var{sym-name}. The +documentation will be formatted as @code{stexi} +(@pxref{texinfo,texinfo}). + +@end defun + +@anchor{texinfo reflection script-stexi-documentation}@defun 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 @code{stexi} +format (@pxref{texinfo,texinfo}). + +@end defun + +@anchor{texinfo reflection object-stexi-documentation}@defun object-stexi-documentation _ [_] [#:force] +@end defun + +@anchor{texinfo reflection package-stexi-standard-copying}@defun package-stexi-standard-copying name version updated years copyright-holder permissions +Create a standard texinfo @code{copying} section. + +@var{years} is a list of years (as integers) in which the modules being +documented were released. All other arguments are strings. + +@end defun + +@anchor{texinfo reflection package-stexi-standard-titlepage}@defun package-stexi-standard-titlepage name version updated authors +Create a standard GNU title page. + +@var{authors} is a list of @code{(@var{name} . @var{email})} pairs. All +other arguments are strings. + +Here is an example of the usage of this procedure: + +@smallexample + (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") +@end smallexample + +@end defun + +@anchor{texinfo reflection package-stexi-generic-menu}@defun 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 @code{#f} will produce a separator. + +@end defun + +@anchor{texinfo reflection package-stexi-standard-menu}@defun package-stexi-standard-menu name modules module-descriptions extra-entries +Create a standard top node and menu, suitable for processing by +makeinfo. + +@end defun + +@anchor{texinfo reflection package-stexi-extended-menu}@defun 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. + +@end defun + +@anchor{texinfo reflection package-stexi-standard-prologue}@defun 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 +@code{package-stexi-documentation} as the prologue. @xref{texinfo +reflection package-stexi-documentation}, @ref{texinfo reflection +package-stexi-standard-titlepage,package-stexi-standard-titlepage}, +@ref{texinfo reflection +package-stexi-standard-copying,package-stexi-standard-copying}, and +@ref{texinfo reflection +package-stexi-standard-menu,package-stexi-standard-menu}. + +@end defun + +@anchor{texinfo reflection package-stexi-documentation}@defun package-stexi-documentation modules name filename prologue epilogue [#:module-stexi-documentation-args] [#:scripts] +Create stexi documentation for a @dfn{package}, where a package is a set +of modules that is released together. + +@var{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 +@var{name} and a texinfo filename of @var{filename}. + +@var{prologue} and @var{epilogue} are lists of stexi forms that will be +spliced into the output document before and after the generated modules +documentation, respectively. @xref{texinfo reflection +package-stexi-standard-prologue}, to create a conventional GNU texinfo +prologue. + +@var{module-stexi-documentation-args} is an optional argument that, if +given, will be added to the argument list when +@code{module-texi-documentation} is called. For example, it might be +useful to define a @code{#:docs-resolver} argument. + +@end defun + +@anchor{texinfo reflection package-stexi-documentation-for-include}@defun package-stexi-documentation-for-include modules module-descriptions [#:module-stexi-documentation-args] +Create stexi documentation for a @dfn{package}, where a package is a set +of modules that is released together. + +@var{modules} is expected to be a list of module names, where a module +name is a list of symbols. Returns an stexinfo fragment. + +Unlike @code{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 @code{@@include} to pull in the automatically generated +parts. + +@var{module-stexi-documentation-args} is an optional argument that, if +given, will be added to the argument list when +@code{module-texi-documentation} is called. For example, it might be +useful to define a @code{#:docs-resolver} argument. + +@end defun diff --git a/doc/ref/tools.texi b/doc/ref/tools.texi new file mode 100644 index 000000000..e962a86ab --- /dev/null +++ b/doc/ref/tools.texi @@ -0,0 +1,378 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011, 2014 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node Miscellaneous Tools +@chapter Miscellaneous Tools + +Programming is more fun with a good tools. This chapter describes snarfing +tools, and the @code{guild} program which can be used to invoke the rest +of the tools (which are self-documenting). Some of these are used in Guile +development, too. Imagine that! + +@menu +* Snarfing:: Grepping the source in various ways. +* Executable Modules:: Modules callable via guild. +@end menu + +@c --------------------------------------------------------------------------- +@node Snarfing +@section Snarfing +@cindex snarfing + +Because it's easier to maintain documentation, code, and other metainfo in one +source file than in many files, there have evolved many methods for grepping +source to lift and separate these kinds of info, in the process generating +docs or fragments of source or what have you. This is known generally as +@dfn{snarfing}, which comes from the verb ``to snarf'', here meaning ``to +unceremoniously extract information from a somewhat unwilling source.'' + +This section documents the installed program @code{guile-snarf} which does +@dfn{init snarfing}, and also touches upon guile's doc snarfing process which +is not yet finalized (i.e., doc snarfing programs are not installed at this +time). + +@menu +* Init Snarfing with guile-snarf:: Exposing C subrs and friends to Scheme. +* Doc Snarfing:: Generating GDFv2 or texi from source. +@end menu + +@c --------------------------------------------------------------------------- +@node Init Snarfing with guile-snarf +@subsection Init Snarfing with guile-snarf +@c NOTE: This node and two subnodes are adapted from ../sources/snarf.texi. +@cindex snarfing, init +@cindex primitive functions +@cindex subrs, defining + +When writing C code for use with Guile, you typically define a set of C +functions, and then make some of them visible to the Scheme world by +calling the @code{scm_c_define_gsubr} function; a C function published in +this way is called a @dfn{subr}. If you have many subrs to publish, it +can sometimes be annoying to keep the list of calls to +@code{scm_c_define_gsubr} in sync with the list of function definitions. +Frequently, a programmer will define a new subr in C, recompile the +application, and then discover that the Scheme interpreter cannot see +the subr, because of a missed call to @code{scm_c_define_gsubr}. + +Guile provides the @code{guile-snarf} command to manage this problem. +Using this tool, you can keep all the information needed to define the +subr alongside the function definition itself; @code{guile-snarf} will +extract this information from your source code, and automatically +generate a file of calls to @code{scm_c_define_gsubr} which you can +@code{#include} into an initialization function. + +@menu +* How guile-snarf works:: Using @code{guile-snarf}, with example. +* Macros guile-snarf recognizes:: How to mark up code for @code{guile-snarf}. +* Writing your own snarfing macros:: How to define new things to snarf. +@end menu + +@c --------------------------------------------------------------------------- +@node How guile-snarf works +@subsubsection How guile-snarf works +@cindex guile-snarf invocation +@cindex guile-snarf example + +Usage: guile-snarf [-o @var{outfile}] [@var{cpp-args} ...] + +The @code{guile-snarf} program will extract initialization actions to +@var{outfile} or to standard output when no @var{outfile} has been +specified or when @var{outfile} is @code{-}. The C preprocessor is +called with @var{cpp-args} (which usually include an input file) and +the output is filtered to extract the initialization actions. + +If there are errors during processing, @var{outfile} is deleted and the +program exits with non-zero status. + +During snarfing, the pre-processor macro @code{SCM_MAGIC_SNARFER} is +defined. You could use this to avoid including snarfer output files +that don't yet exist by writing code like this: + +@smallexample +#ifndef SCM_MAGIC_SNARFER +#include "foo.x" +#endif +@end smallexample + +If the environment variable @code{CPP} is set, use its value instead of the +C pre-processor determined at Guile configure-time. + +@xref{Macros guile-snarf recognizes}, for a list of the special (some would +say magic) cpp macros you can use, including the list of deprecated macros. + +For example, here is how you might define a new subr called +@code{clear-image}, implemented by the C function @code{clear_image}: + +@example +@group +#include <libguile.h> + +SCM_DEFINE (clear_image, "clear-image", 1, 0, 0, + (SCM image), + "Clear the image.") +#define FUNC_NAME s_clear_image +@{ + /* C code to clear the image in @code{image}... */ +@} +#undef FUNC_NAME + +void +init_image_type () +@{ +#include "image-type.x" +@} +@end group +@end example + +The @code{SCM_DEFINE} declaration says that the C function +@code{clear_image} implements a Scheme subr called @code{clear-image}, +which takes one required argument (of type @code{SCM} and named +@code{image}), no optional arguments, and no rest argument. @xref{Doc +Snarfing}, for info on the docstring. + +This works in concert with @code{FUNC_NAME} to also define a static +array of characters named @code{s_clear_image}, initialized to the +string "clear-image". The body of @code{clear_image} may use the array +in error messages, instead of writing out the literal string; this may +save string space on some systems. + +Assuming the text above lives in a file named @file{image-type.c}, you will +need to execute the following command to prepare this file for compilation: + +@example +guile-snarf -o image-type.x image-type.c +@end example + +This scans @file{image-type.c} for @code{SCM_DEFINE} +declarations, and writes to @file{image-type.x} the output: + +@example +scm_c_define_gsubr (s_clear_image, 1, 0, 0, (SCM (*)() ) clear_image); +@end example + +When compiled normally, @code{SCM_DEFINE} is a macro which expands to +a declaration of the @code{s_clear_image} string and the function +header for @code{clear_image}. + +Note that the output file name matches the @code{#include} from the +input file. Also, you still need to provide all the same information +you would if you were using @code{scm_c_define_gsubr} yourself, but you +can place the information near the function definition itself, so it is +less likely to become incorrect or out-of-date. + +If you have many files that @code{guile-snarf} must process, you should +consider using a fragment like the following in your Makefile: + +@example +snarfcppopts = $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +.SUFFIXES: .x +.c.x: + guile-snarf -o $@@ $< $(snarfcppopts) +@end example + +This tells make to run @code{guile-snarf} to produce each needed +@file{.x} file from the corresponding @file{.c} file. + +The program @code{guile-snarf} passes its command-line arguments +directly to the C preprocessor, which it uses to extract the +information it needs from the source code. this means you can pass +normal compilation flags to @code{guile-snarf} to define preprocessor +symbols, add header file directories, and so on. + +@c --------------------------------------------------------------------------- +@node Macros guile-snarf recognizes +@subsubsection Macros guile-snarf recognizes +@cindex guile-snarf recognized macros +@cindex guile-snarf deprecated macros + +Here are the macros you can use in your source code from which +@code{guile-snarf} can construct initialization code: + +@example +/* procedures */ +SCM_DEFINE (FNAME, PRIMNAME, REQ, OPT, VAR, ARGLIST, DOCSTRING) + +SCM_PROC (RANAME, STR, REQ, OPT, VAR, CFN) +SCM_REGISTER_PROC (RANAME, STR, REQ, OPT, VAR, CFN) + +SCM_GPROC (RANAME, STR, REQ, OPT, VAR, CFN, GF) + +/* everything else */ +SCM_SYMBOL (c_name, scheme_name) +SCM_GLOBAL_SYMBOL (c_name, scheme_name) + +SCM_KEYWORD (c_name, scheme_name) +SCM_GLOBAL_KEYWORD (c_name, scheme_name) + +SCM_VARIABLE (c_name, scheme_name) +SCM_GLOBAL_VARIABLE (c_name, scheme_name) + +SCM_VARIABLE_INIT (c_name, scheme_name, init_val) +SCM_GLOBAL_VARIABLE_INIT (c_name, scheme_name, init_val) +@end example + +@c i like things dense, but maybe someone else will reformat this +@c into an easier-to-read list. also, all-upcase to me is a form +@c of quoting, so @var{} is not necessary there. --ttn +REQ and OPT are numbers indicating required and optional argument +counts, respectively; VAR is a number that, if non-zero, means the +function will accept any remaining arguments as a list; DOCSTRING is a +string (use @code{\n\} at eol for multi-line); FNAME is a C-language +identifier, CFN and GF and @var{c_name} likewise; PRIMNAME is a string +denoting the name available to Scheme code, STR and @var{scheme_name} +likewise; RANAME is the name of the static string (must match that +declared by the associated definition of cpp macro @var{FUNC_NAME}); +ARGLIST is an argument list (in parentheses); and lastly, @var{init_val} +is a expression suitable for initializing a new variable. + +For procedures, you can use @code{SCM_DEFINE} for most purposes. Use +@code{SCM_PROC} along with @code{SCM_REGISTER_PROC} when you don't +want to be bothered with docstrings. Use @code{SCM_GPROC} for generic +functions (@pxref{Creating Generic Functions}). All procedures are +declared with return type @code{SCM}. + +For everything else, use the appropriate macro (@code{SCM_SYMBOL} for +symbols, and so on). Without "_GLOBAL_", the declarations are +@code{static}. + +All these macros should be used at top-level, outside function bodies. +Also, it's a good idea to define @var{FUNC_NAME} immediately after using +@code{SCM_DEFINE} (and similar), and then the function body, and then +@code{#undef FUNC_NAME}. + +@xref{How guile-snarf works}, and also libguile source, for examples. +@xref{Subrs}, for details on argument passing and how to write C +functions. + +@c --------------------------------------------------------------------------- +@node Writing your own snarfing macros +@subsubsection Writing your own snarfing macros + +When you want to use the general snarfing mechanism, but none of the +provided macros fits your need, you can use the macro +@code{SCM_SNARF_INIT}. + +For example, the @code{SCM_SYMBOL} macro can be defined like this: + +@example +#define SCM_SYMBOL(c_name, scheme_name) \ +static SCM c_name \ +SCM_SNARF_INIT(c_name = scm_permanent_object (scm_str2symbol (scheme_name))) +@end example + +@defmac SCM_SNARF_INIT (code) +When processed normally, @code{SCM_SNARF_INIT} expands to nothing; +when processed by the snarfer, it causes @var{code} to be included in +the initialization action file, followed by a semicolon. +@end defmac + +@c --------------------------------------------------------------------------- +@node Doc Snarfing +@subsection Doc Snarfing + +In addition to init snarfing (@pxref{Init Snarfing with guile-snarf}), +the libguile sources are also subject to doc snarfing, by programs that +are included in the distribution (but not installed at this time). The +output is the file @file{guile-procedures.txt} which is installed, and +subsequently used by module @code{(ice-9 documentation)}. + +Here is a list of what does what according to @file{libguile/Makefile.am}: + +@itemize +@item guile-snarf-docs runs cpp defining SCM_MAGIC_SNARF_DOCS +@item guile_filter_doc_snarfage parses guile-snarf-docs output to produce .doc +@item ../scripts/snarf-check-and-output-texi makes guile.texi +@item ../scripts/snarf-check-and-output-texi makes guile-procedures.txt +@item guile-func-name-check checks source snarf-syntax integrity (optional?) +@end itemize + +Note that for guile-1.4, a completely different approach was used! All this +is rather byzantine, so for now @emph{NO} doc snarfing programs are installed. + +[fixme: Document further once doc snarfing is tamed somewhat. --ttn] + +@c --------------------------------------------------------------------------- +@node Executable Modules +@section Executable Modules +@cindex guild +@cindex guile-tools +@cindex modules, executable +@cindex executable modules +@cindex scripts + +When Guile is installed, in addition to the @code{(ice-9 FOO)} modules, a set +of @dfn{guild modules} @code{(scripts BAR)} is also installed. Each is +a regular Scheme module that has some additional packaging so that it can be +used by guild, from the shell. For this reason, we sometimes use the +term @dfn{script} in this context to mean the same thing. + +As a convenience, the @code{guild} wrapper program is installed along with +@code{guile}; it knows where a particular module is installed and calls it +passing its args to the program. The result is that you need not augment your +@code{PATH}. Usage is straightforward: + +@example +guild --help +guild --version +guild [OPTION] PROGRAM [ARGS ...] + +If PROGRAM is "list" or omitted, display contents of scripts dir, otherwise +PROGRAM is run w/ ARGS. Options (only one of which may be used at a time): + --scriptsdir DIR -- Look in DIR for scripts + --guileversion VERS -- Look in $pkgdatadir/VERS/scripts for scripts + --source -- Display PROGRAM source (ignore ARGS) to stdout +@end example + +The modules are self-documenting. For example, to see the documentation for +@code{lint}, use one (or both) of the shell commands: + +@example +guild display-commentary '(scripts lint)' +guild --source lint +@end example + +The rest of this section describes the packaging that goes into creating an +executable module. Feel free to skip to the next chapter. + +@subsection Writing Executable Modules + +@c adapted from scripts/README + +See template file @code{PROGRAM} for a quick start. + +Programs must follow the @dfn{guild} convention, documented here: + +@itemize + +@item +The module name must be "(scripts PROGRAM)". A procedure named PROGRAM w/ +signature "(PROGRAM . args)" must be exported. Basically, use some variant +of the form: + +@example +(define-module (scripts PROGRAM) + #:export (PROGRAM)) +@end example + +Feel free to export other definitions useful in the module context. + +@item +There must be the alias: + +@example +(define main PROGRAM) +@end example + +However, `main' must NOT be exported. + +@end itemize + +Following these conventions allows the program file to be used as module +@code{(scripts PROGRAM)} in addition to being invoked by guild. Please +also include a helpful Commentary section w/ some usage info. + +@c tools.texi ends here diff --git a/doc/ref/tour.texi b/doc/ref/tour.texi new file mode 100644 index 000000000..0924216aa --- /dev/null +++ b/doc/ref/tour.texi @@ -0,0 +1,404 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010, 2011, +@c 2012 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@raisesections + +@node Hello Guile! +@section Hello Guile! + +This chapter presents a quick tour of all the ways that Guile can be +used. There are additional examples in the @file{examples/} +directory in the Guile source distribution. It also explains how best to report +any problems that you find. + +The following examples assume that Guile has been installed in +@code{/usr/local/}. + +@menu +* Running Guile Interactively:: +* Running Guile Scripts:: +* Linking Guile into Programs:: +* Writing Guile Extensions:: +* Using the Guile Module System:: +* Reporting Bugs:: +@end menu + + +@node Running Guile Interactively +@subsection Running Guile Interactively + +In its simplest form, Guile acts as an interactive interpreter for the +Scheme programming language, reading and evaluating Scheme expressions +the user enters from the terminal. Here is a sample interaction between +Guile and a user; the user's input appears after the @code{$} and +@code{scheme@@(guile-user)>} prompts: + +@example +$ guile +scheme@@(guile-user)> (+ 1 2 3) ; add some numbers +$1 = 6 +scheme@@(guile-user)> (define (factorial n) ; define a function + (if (zero? n) 1 (* n (factorial (- n 1))))) +scheme@@(guile-user)> (factorial 20) +$2 = 2432902008176640000 +scheme@@(guile-user)> (getpwnam "root") ; look in /etc/passwd +$3 = #("root" "x" 0 0 "root" "/root" "/bin/bash") +scheme@@(guile-user)> @kbd{C-d} +$ +@end example + + +@node Running Guile Scripts +@subsection Running Guile Scripts + +Like AWK, Perl, or any shell, Guile can interpret script files. A Guile +script is simply a file of Scheme code with some extra information at +the beginning which tells the operating system how to invoke Guile, and +then tells Guile how to handle the Scheme code. + +Here is a trivial Guile script. @xref{Guile Scripting}, for more details. + +@example +#!/usr/local/bin/guile -s +!# +(display "Hello, world!") +(newline) +@end example + + +@node Linking Guile into Programs +@subsection Linking Guile into Programs + +The Guile interpreter is available as an object library, to be linked +into applications using Scheme as a configuration or extension +language. + +Here is @file{simple-guile.c}, source code for a program that will +produce a complete Guile interpreter. In addition to all usual +functions provided by Guile, it will also offer the function +@code{my-hostname}. + +@example +#include <stdlib.h> +#include <libguile.h> + +static SCM +my_hostname (void) +@{ + char *s = getenv ("HOSTNAME"); + if (s == NULL) + return SCM_BOOL_F; + else + return scm_from_locale_string (s); +@} + +static void +inner_main (void *data, int argc, char **argv) +@{ + scm_c_define_gsubr ("my-hostname", 0, 0, 0, my_hostname); + scm_shell (argc, argv); +@} + +int +main (int argc, char **argv) +@{ + scm_boot_guile (argc, argv, inner_main, 0); + return 0; /* never reached */ +@} +@end example + +When Guile is correctly installed on your system, the above program +can be compiled and linked like this: + +@example +$ gcc -o simple-guile simple-guile.c \ + `pkg-config --cflags --libs guile-@value{EFFECTIVE-VERSION}` +@end example + +When it is run, it behaves just like the @code{guile} program except +that you can also call the new @code{my-hostname} function. + +@example +$ ./simple-guile +scheme@@(guile-user)> (+ 1 2 3) +$1 = 6 +scheme@@(guile-user)> (my-hostname) +"burns" +@end example + +@node Writing Guile Extensions +@subsection Writing Guile Extensions + +You can link Guile into your program and make Scheme available to the +users of your program. You can also link your library into Guile and +make its functionality available to all users of Guile. + +A library that is linked into Guile is called an @dfn{extension}, but it +really just is an ordinary object library. + +The following example shows how to write a simple extension for Guile +that makes the @code{j0} function available to Scheme code. + +@smallexample +#include <math.h> +#include <libguile.h> + +SCM +j0_wrapper (SCM x) +@{ + return scm_from_double (j0 (scm_to_double (x))); +@} + +void +init_bessel () +@{ + scm_c_define_gsubr ("j0", 1, 0, 0, j0_wrapper); +@} +@end smallexample + +This C source file needs to be compiled into a shared library. Here is +how to do it on GNU/Linux: + +@smallexample +gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` \ + -shared -o libguile-bessel.so -fPIC bessel.c +@end smallexample + +For creating shared libraries portably, we recommend the use of GNU +Libtool (@pxref{Top, , Introduction, libtool, GNU Libtool}). + +A shared library can be loaded into a running Guile process with the +function @code{load-extension}. The @code{j0} is then immediately +available: + +@smallexample +$ guile +scheme@@(guile-user)> (load-extension "./libguile-bessel" "init_bessel") +scheme@@(guile-user)> (j0 2) +$1 = 0.223890779141236 +@end smallexample + +For more on how to install your extension, @pxref{Installing Site +Packages}. + + +@node Using the Guile Module System +@subsection Using the Guile Module System + +Guile has support for dividing a program into @dfn{modules}. By using +modules, you can group related code together and manage the +composition of complete programs from largely independent parts. + +For more details on the module system beyond this introductory material, +@xref{Modules}. + +@menu +* Using Modules:: +* Writing new Modules:: +* Putting Extensions into Modules:: +@end menu + + +@node Using Modules +@subsubsection Using Modules + +Guile comes with a lot of useful modules, for example for string +processing or command line parsing. Additionally, there exist many +Guile modules written by other Guile hackers, but which have to be +installed manually. + +Here is a sample interactive session that shows how to use the +@code{(ice-9 popen)} module which provides the means for communicating +with other processes over pipes together with the @code{(ice-9 +rdelim)} module that provides the function @code{read-line}. + +@smallexample +$ guile +scheme@@(guile-user)> (use-modules (ice-9 popen)) +scheme@@(guile-user)> (use-modules (ice-9 rdelim)) +scheme@@(guile-user)> (define p (open-input-pipe "ls -l")) +scheme@@(guile-user)> (read-line p) +$1 = "total 30" +scheme@@(guile-user)> (read-line p) +$2 = "drwxr-sr-x 2 mgrabmue mgrabmue 1024 Mar 29 19:57 CVS" +@end smallexample + +@node Writing new Modules +@subsubsection Writing new Modules + +You can create new modules using the syntactic form +@code{define-module}. All definitions following this form until the +next @code{define-module} are placed into the new module. + +One module is usually placed into one file, and that file is installed +in a location where Guile can automatically find it. The following +session shows a simple example. + +@smallexample +$ cat /usr/local/share/guile/site/foo/bar.scm + +(define-module (foo bar) + #:export (frob)) + +(define (frob x) (* 2 x)) + +$ guile +scheme@@(guile-user)> (use-modules (foo bar)) +scheme@@(guile-user)> (frob 12) +$1 = 24 +@end smallexample + +For more on how to install your module, @pxref{Installing Site +Packages}. + + +@node Putting Extensions into Modules +@subsubsection Putting Extensions into Modules + +In addition to Scheme code you can also put things that are defined in +C into a module. + +You do this by writing a small Scheme file that defines the module and +call @code{load-extension} directly in the body of the module. + +@smallexample +$ cat /usr/local/share/guile/site/math/bessel.scm + +(define-module (math bessel) + #:export (j0)) + +(load-extension "libguile-bessel" "init_bessel") + +$ file /usr/local/lib/guile/@value{EFFECTIVE-VERSION}/extensions/libguile-bessel.so +@dots{} ELF 32-bit LSB shared object @dots{} +$ guile +scheme@@(guile-user)> (use-modules (math bessel)) +scheme@@(guile-user)> (j0 2) +$1 = 0.223890779141236 +@end smallexample + +@xref{Modules and Extensions}, for more information. + +@lowersections + +@node Reporting Bugs +@section Reporting Bugs + +Any problems with the installation should be reported to +@email{bug-guile@@gnu.org}. + +If you find a bug in Guile, please report it to the Guile developers, so +they can fix it. They may also be able to suggest workarounds when it +is not possible for you to apply the bug-fix or install a new version of +Guile yourself. + +Before sending in bug reports, please check with the following list that +you really have found a bug. + +@itemize @bullet +@item +Whenever documentation and actual behavior differ, you have certainly +found a bug, either in the documentation or in the program. + +@item +When Guile crashes, it is a bug. + +@item +When Guile hangs or takes forever to complete a task, it is a bug. + +@item +When calculations produce wrong results, it is a bug. + +@item +When Guile signals an error for valid Scheme programs, it is a bug. + +@item +When Guile does not signal an error for invalid Scheme programs, it may +be a bug, unless this is explicitly documented. + +@item +When some part of the documentation is not clear and does not make sense +to you even after re-reading the section, it is a bug. +@end itemize + +Before reporting the bug, check whether any programs you have loaded +into Guile, including your @file{.guile} file, set any variables that +may affect the functioning of Guile. Also, see whether the problem +happens in a freshly started Guile without loading your @file{.guile} +file (start Guile with the @code{-q} switch to prevent loading the init +file). If the problem does @emph{not} occur then, you must report the +precise contents of any programs that you must load into Guile in order +to cause the problem to occur. + +When you write a bug report, please make sure to include as much of the +information described below in the report. If you can't figure out some +of the items, it is not a problem, but the more information we get, the +more likely we can diagnose and fix the bug. + +@itemize @bullet +@item +The version number of Guile. You can get this information from invoking +@samp{guile --version} at your shell, or calling @code{(version)} from +within Guile. + +@item +Your machine type, as determined by the @code{config.guess} shell +script. If you have a Guile checkout, this file is located in +@code{build-aux}; otherwise you can fetch the latest version from +@uref{http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD}. + +@example +$ build-aux/config.guess +x86_64-unknown-linux-gnu +@end example + +@item +If you installed Guile from a binary package, the version of that +package. On systems that use RPM, use @code{rpm -qa | grep guile}. On systems +that use DPKG, @code{dpkg -l | grep guile}. + +@item +If you built Guile yourself, the build configuration that you used: + +@example +$ ./config.status --config +'--enable-error-on-warning' '--disable-deprecated'... +@end example + +@item +A complete description of how to reproduce the bug. + +If you have a Scheme program that produces the bug, please include it in +the bug report. If your program is too big to include. please try to +reduce your code to a minimal test case. + +If you can reproduce your problem at the REPL, that is best. Give a +transcript of the expressions you typed at the REPL. + +@item +A description of the incorrect behavior. For example, "The Guile +process gets a fatal signal," or, "The resulting output is as follows, +which I think is wrong." + +If the manifestation of the bug is a Guile error message, it is +important to report the precise text of the error message, and a +backtrace showing how the Scheme program arrived at the error. This can +be done using the @code{,backtrace} command in Guile's debugger. +@end itemize + +If your bug causes Guile to crash, additional information from a +low-level debugger such as GDB might be helpful. If you have built Guile +yourself, you can run Guile under GDB via the +@code{meta/gdb-uninstalled-guile} script. Instead of invoking Guile as +usual, invoke the wrapper script, type @code{run} to start the process, +then @code{backtrace} when the crash comes. Include that backtrace in +your report. + + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/ref/vm.texi b/doc/ref/vm.texi new file mode 100644 index 000000000..d11847091 --- /dev/null +++ b/doc/ref/vm.texi @@ -0,0 +1,1961 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2008-2011, 2013, 2015, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node A Virtual Machine for Guile +@section 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@footnote{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''.}. + +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:: +@end menu + +@node Why a VM? +@subsection Why a VM? + +@cindex interpreter +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 @code{(f x y)} always had to figure out whether @var{f} +was a procedure, or a special form like @code{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, @code{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 uses the portable GNU Lightning library +to emit that code, 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 @ref{Extending the Compiler}. + +@node VM Concepts +@subsection 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: + +@itemize +@item ip - Instruction pointer +@item sp - Stack pointer +@item fp - Frame pointer +@end itemize + +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. + +@node Stack Layout +@subsection Stack Layout + +The stack of Guile's virtual machine is composed of @dfn{frames}. Each +frame corresponds to the application of one compiled procedure, and +contains storage space for arguments, local variables, and some +bookkeeping information (such as what to do after the frame is +finished). + +While the compiler is free to do whatever it wants to, as long as the +semantics of a computation are preserved, in practice every time you +call a function, a new frame is created. (The notable exception of +course is the tail call case, @pxref{Tail Calls}.) + +The structure of the top stack frame is as follows: + +@example + | ...previous frame locals... | + +==============================+ <- fp + 3 + | Dynamic link | + +------------------------------+ + | Virtual return address (vRA) | + +------------------------------+ + | Machine return address (mRA) | + +==============================+ <- fp + | Local 0 | + +------------------------------+ + | Local 1 | + +------------------------------+ + | ... | + +------------------------------+ + | Local N-1 | + \------------------------------/ <- sp +@end example + +In the above drawing, the stack grows downward. At the beginning of a +function call, the procedure being applied is in local 0, followed by +the arguments from local 1. After the procedure checks that it is being +passed a compatible set of arguments, the procedure allocates some +additional space in the frame to hold variables local to the function. + +Note that once a value in a local variable slot is no longer needed, +Guile is free to re-use that slot. This applies to the slots that were +initially used for the callee and arguments, too. For this reason, +backtraces in Guile aren't always able to show all of the arguments: it +could be that the slot corresponding to that argument was re-used by +some other variable. + +The @dfn{virtual return address} is the @code{ip} that was in effect +before this program was applied. When we return from this activation +frame, we will jump back to this @code{ip}. Likewise, the @dfn{dynamic +link} is the offset of the @code{fp} that was in effect before this +program was applied, relative to the current @code{fp}. + +There are two return addresses: the virtual return address (vRA), and +the machine return address (mRA). The vRA is always present and +indicates a bytecode address. The mRA is only present when a call is +made from a function with machine code (e.g. a function that has been +JIT-compiled). + +To prepare for a non-tail application, Guile's VM will emit code that +shuffles the function to apply and its arguments into appropriate stack +slots, with three free slots below them. The call then initializes +those free slots to hold the machine return address (or NULL), the +virtual return address, and the offset to the previous frame pointer +(@code{fp}). It then gets the @code{ip} for the function being called +and adjusts @code{fp} to point to the new call frame. + +In this way, the dynamic link links the current frame to the previous +frame. Computing a stack trace involves traversing these frames. + +Each stack local in Guile is 64 bits wide, even on 32-bit architectures. +This allows Guile to preserve its uniform treatment of stack locals +while allowing for unboxed arithmetic on 64-bit integers and +floating-point numbers. @xref{Instruction Set}, for more on unboxed +arithmetic. + +As an implementation detail, we actually store the dynamic link as an +offset and not an absolute value because the stack can move at runtime +as it expands or during partial continuation calls. If it were an +absolute value, we would have to walk the frames, relocating frame +pointers. + +@node Variables and the VM +@subsection Variables and the VM + +Consider the following Scheme code as an example: + +@example + (define (foo a) + (lambda (b) (vector foo a b))) +@end example + +Within the lambda expression, @code{foo} is a top-level variable, +@code{a} is a lexically captured variable, and @code{b} is a local +variable. + +Another way to refer to @code{a} and @code{b} is to say that @code{a} is +a ``free'' variable, since it is not defined within the lambda, and +@code{b} is a ``bound'' variable. These are the terms used in the +@dfn{lambda calculus}, a mathematical notation for describing functions. +The lambda calculus is useful because it is a language in which to +reason precisely about functions and variables. It is especially good +at describing scope relations, and it is for that reason that we mention +it here. + +Guile allocates all variables on the stack. When a lexically enclosed +procedure with free variables---a @dfn{closure}---is created, it copies +those variables into its free variable vector. References to free +variables are then redirected through the free variable vector. + +If a variable is ever @code{set!}, however, it will need to be +heap-allocated instead of stack-allocated, so that different closures +that capture the same variable can see the same value. Also, this +allows continuations to capture a reference to the variable, instead +of to its value at one point in time. For these reasons, @code{set!} +variables are allocated in ``boxes''---actually, in variable cells. +@xref{Variables}, for more information. References to @code{set!} +variables are indirected through the boxes. + +Thus perhaps counterintuitively, what would seem ``closer to the +metal'', viz @code{set!}, actually forces an extra memory allocation and +indirection. Sometimes Guile's optimizer can remove this allocation, +but not always. + +Going back to our example, @code{b} may be allocated on the stack, as +it is never mutated. + +@code{a} may also be allocated on the stack, as it too is never +mutated. Within the enclosed lambda, its value will be copied into +(and referenced from) the free variables vector. + +@code{foo} is a top-level variable, because @code{foo} is not +lexically bound in this example. + +@node VM Programs +@subsection Compiled Procedures are VM Programs + +By default, when you enter in expressions at Guile's REPL, they are +first compiled to bytecode. Then that bytecode is executed to produce a +value. If the expression evaluates to a procedure, the result of this +process is a compiled procedure. + +A compiled procedure is a compound object consisting of its bytecode and +a reference to any captured lexical variables. In addition, when a +procedure is compiled, it has associated metadata written to side +tables, for instance a line number mapping, or its docstring. You can +pick apart these pieces with the accessors in @code{(system vm +program)}. @xref{Compiled Procedures}, for a full API reference. + +A procedure may reference data that was statically allocated when the +procedure was compiled. For example, a pair of immediate objects +(@pxref{Immediate Objects}) can be allocated directly in the memory +segment that contains the compiled bytecode, and accessed directly by +the bytecode. + +Another use for statically allocated data is to serve as a cache for a +bytecode. Top-level variable lookups are handled in this way; the first +time a top-level binding is referenced, the resolved variable will be +stored in a cache. Thereafter all access to the variable goes through +the cache cell. The variable's value may change in the future, but the +variable itself will not. + +We can see how these concepts tie together by disassembling the +@code{foo} function we defined earlier to see what is going on: + +@smallexample +scheme@@(guile-user)> (define (foo a) (lambda (b) (vector foo a b))) +scheme@@(guile-user)> ,x foo +Disassembly of #<procedure foo (a)> at #xf1da30: + + 0 (instrument-entry 164) at (unknown file):5:0 + 2 (assert-nargs-ee/locals 2 1) ;; 3 slots (1 arg) + 3 (allocate-words/immediate 2 3) at (unknown file):5:16 + 4 (load-u64 0 0 65605) + 7 (word-set!/immediate 2 0 0) + 8 (load-label 0 7) ;; anonymous procedure at #xf1da6c + 10 (word-set!/immediate 2 1 0) + 11 (scm-set!/immediate 2 2 1) + 12 (reset-frame 1) ;; 1 slot + 13 (handle-interrupts) + 14 (return-values) + +---------------------------------------- +Disassembly of anonymous procedure at #xf1da6c: + + 0 (instrument-entry 183) at (unknown file):5:16 + 2 (assert-nargs-ee/locals 2 3) ;; 5 slots (1 arg) + 3 (static-ref 2 152) ;; #<variable 112e530 value: #<procedure foo (a)>> + 5 (immediate-tag=? 2 7 0) ;; heap-object? + 7 (je 19) ;; -> L2 + 8 (static-ref 2 119) ;; #<directory (guile-user) ca9750> + 10 (static-ref 1 127) ;; foo + 12 (call-scm<-scm-scm 2 2 1 40) + 14 (immediate-tag=? 2 7 0) ;; heap-object? + 16 (jne 8) ;; -> L1 + 17 (scm-ref/immediate 0 2 1) + 18 (immediate-tag=? 0 4095 2308) ;; undefined? + 20 (je 4) ;; -> L1 + 21 (static-set! 2 134) ;; #<variable 112e530 value: #<procedure foo (a)>> + 23 (j 3) ;; -> L2 +L1: + 24 (throw/value 1 151) ;; #(unbound-variable #f "Unbound variable: ~S") +L2: + 26 (scm-ref/immediate 2 2 1) + 27 (allocate-words/immediate 1 4) at (unknown file):5:28 + 28 (load-u64 0 0 781) + 31 (word-set!/immediate 1 0 0) + 32 (scm-set!/immediate 1 1 2) + 33 (scm-ref/immediate 4 4 2) + 34 (scm-set!/immediate 1 2 4) + 35 (scm-set!/immediate 1 3 3) + 36 (mov 4 1) + 37 (reset-frame 1) ;; 1 slot + 38 (handle-interrupts) + 39 (return-values) +@end smallexample + +The first thing to notice is that the bytecode is at a fairly low level. +When a program is compiled from Scheme to bytecode, it is expressed in +terms of more primitive operations. As such, there can be more +instructions than you might expect. + +The first chunk of instructions is the outer @code{foo} procedure. It +is followed by the code for the contained closure. The code can look +daunting at first glance, but with practice it quickly becomes +comprehensible, and indeed being able to read bytecode is an important +step to understanding the low-level performance of Guile programs. + +The @code{foo} function begins with a prelude. The +@code{instrument-entry} bytecode increments a counter associated with +the function. If the counter reaches a certain threshold, Guile will +emit machine code (``JIT-compile'') for @code{foo}. Emitting machine +code is fairly cheap but it does take time, so it's not something you +want to do for every function. Using a per-function counter and a +global threshold allows Guile to spend time JIT-compiling only the +``hot'' functions. + +Next in the prelude is an argument-checking instruction, which checks +that it was called with only 1 argument (plus the callee function itself +makes 2) and then reserves stack space for an additional 1 local. + +Then from @code{ip} 3 to 11, we allocate a new closure by allocating a +three-word object, initializing its first word to store a type tag, +setting its second word to its code pointer, and finally at @code{ip} +11, storing local value 1 (the @code{a} argument) into the third word +(the first free variable). + +Before returning, @code{foo} ``resets the frame'' to hold only one local +(the return value), runs any pending interrupts (@pxref{Asyncs}) and +then returns. + +Note that local variables in Guile's virtual machine are usually +addressed relative to the stack pointer, which leads to a pleasantly +efficient @code{sp[@var{n}]} access. However it can make the +disassembly hard to read, because the @code{sp} can change during the +function, and because incoming arguments are relative to the @code{fp}, +not the @code{sp}. + +To know what @code{fp}-relative slot corresponds to an +@code{sp}-relative reference, scan up in the disassembly until you get +to a ``@var{n} slots'' annotation; in our case, 3, indicating that the +frame has space for 3 slots. Thus a zero-indexed @code{sp}-relative +slot of 2 corresponds to the @code{fp}-relative slot of 0, which +initially held the value of the closure being called. This means that +Guile doesn't need the value of the closure to compute its result, and +so slot 0 was free for re-use, in this case for the result of making a +new closure. + +A closure is code with data. As you can see, making the closure +involved making an object (@code{ip} 3), putting a code pointer in it +(@code{ip} 8 and 10), and putting in the closure's free variable +(@code{ip} 11). + +The second stanza disassembles the code for the closure. After the +prelude, all of the code between @code{ip} 5 and 24 is related to +loading the toplevel variable @code{foo} into slot 1. This lookup +happens only once, and is associated with a cache; after the first run, +the value in the cache will be a bound variable, and the code will jump +from @code{ip} 7 to 26. On the first run, Guile gets the module +associated with the function, calls out to a run-time routine to look up +the variable, and checks that the variable is bound before initializing +the cache. Either way, @code{ip} 26 dereferences the variable into +local 2. + +What follows is the allocation and initialization of the vector return +value. @code{Ip} 27 does the allocation, and the following two +instructions initialize the type-and-length tag for the object's first +word. @code{Ip} 32 sets word 1 of the object (the first vector slot) to +the value of @code{foo}; @code{ip} 33 fetches the closure variable for +@code{a}, then in @code{ip} 34 stores it in the second vector slot; and +finally, in @code{ip} 35, local @code{b} is stored to the third vector +slot. This is followed by the return sequence. + + +@node Object File Format +@subsection Object File Format + +To compile a file to disk, we need a format in which to write the +compiled code to disk, and later load it into Guile. A good @dfn{object +file format} has a number of characteristics: + +@itemize +@item Above all else, it should be very cheap to load a compiled file. +@item It should be possible to statically allocate constants in the +file. For example, a bytevector literal in source code can be emitted +directly into the object file. +@item The compiled file should enable maximum code and data sharing +between different processes. +@item The compiled file should contain debugging information, such as +line numbers, but that information should be separated from the code +itself. It should be possible to strip debugging information if space +is tight. +@end itemize + +These characteristics are not specific to Scheme. Indeed, mainstream +languages like C and C++ have solved this issue many times in the past. +Guile builds on their work by adopting ELF, the object file format of +GNU and other Unix-like systems, as its object file format. Although +Guile uses ELF on all platforms, we do not use platform support for ELF. +Guile implements its own linker and loader. The advantage of using ELF +is not sharing code, but sharing ideas. ELF is simply a well-designed +object file format. + +An ELF file has two meta-tables describing its contents. The first +meta-table is for the loader, and is called the @dfn{program table} or +sometimes the @dfn{segment table}. The program table divides the file +into big chunks that should be treated differently by the loader. +Mostly the difference between these @dfn{segments} is their +permissions. + +Typically all segments of an ELF file are marked as read-only, except +that part that represents modifiable static data or static data that +needs load-time initialization. Loading an ELF file is as simple as +mmapping the thing into memory with read-only permissions, then using +the segment table to mark a small sub-region of the file as writable. +This writable section is typically added to the root set of the garbage +collector as well. + +One ELF segment is marked as ``dynamic'', meaning that it has data of +interest to the loader. Guile uses this segment to record the Guile +version corresponding to this file. There is also an entry in the +dynamic segment that points to the address of an initialization thunk +that is run to perform any needed link-time initialization. (This is +like dynamic relocations for normal ELF shared objects, except that we +compile the relocations as a procedure instead of having the loader +interpret a table of relocations.) Finally, the dynamic segment marks +the location of the ``entry thunk'' of the object file. This thunk is +returned to the caller of @code{load-thunk-from-memory} or +@code{load-thunk-from-file}. When called, it will execute the ``body'' +of the compiled expression. + +The other meta-table in an ELF file is the @dfn{section table}. Whereas +the program table divides an ELF file into big chunks for the loader, +the section table specifies small sections for use by introspective +tools like debuggers or the like. One segment (program table entry) +typically contains many sections. There may be sections outside of any +segment, as well. + +Typical sections in a Guile @code{.go} file include: + +@table @code +@item .rtl-text +Bytecode. +@item .data +Data that needs initialization, or which may be modified at runtime. +@item .rodata +Statically allocated data that needs no run-time initialization, and +which therefore can be shared between processes. +@item .dynamic +The dynamic section, discussed above. +@item .symtab +@itemx .strtab +A table mapping addresses in the @code{.rtl-text} to procedure names. +@code{.strtab} is used by @code{.symtab}. +@item .guile.procprops +@itemx .guile.arities +@itemx .guile.arities.strtab +@itemx .guile.docstrs +@itemx .guile.docstrs.strtab +Side tables of procedure properties, arities, and docstrings. +@item .guile.docstrs.strtab +Side table of frame maps, describing the set of live slots for ever +return point in the program text, and whether those slots are pointers +are not. Used by the garbage collector. +@item .debug_info +@itemx .debug_abbrev +@itemx .debug_str +@itemx .debug_loc +@itemx .debug_line +Debugging information, in DWARF format. See the DWARF specification, +for more information. +@item .shstrtab +Section name string table. +@end table + +For more information, see @uref{http://linux.die.net/man/5/elf,,the +elf(5) man page}. See @uref{http://dwarfstd.org/,the DWARF +specification} for more on the DWARF debugging format. Or if you are an +adventurous explorer, try running @code{readelf} or @code{objdump} on +compiled @code{.go} files. It's good times! + + +@node Instruction Set +@subsection Instruction Set + +There are currently about 150 instructions in Guile's virtual machine. +These instructions represent atomic units of a program's execution. +Ideally, they perform one task without conditional branches, then +dispatch to the next instruction in the stream. + +Instructions themselves are composed of 1 or more 32-bit units. The low +8 bits of the first word indicate the opcode, and the rest of +instruction describe the operands. There are a number of different ways +operands can be encoded. + +@table @code +@item s@var{n} +An unsigned @var{n}-bit integer, indicating the @code{sp}-relative index +of a local variable. +@item f@var{n} +An unsigned @var{n}-bit integer, indicating the @code{fp}-relative index +of a local variable. Used when a continuation accepts a variable number +of values, to shuffle received values into known locations in the +frame. +@item c@var{n} +An unsigned @var{n}-bit integer, indicating a constant value. +@item l24 +An offset from the current @code{ip}, in 32-bit units, as a signed +24-bit value. Indicates a bytecode address, for a relative jump. +@item i16 +@itemx i32 +An immediate Scheme value (@pxref{Immediate Objects}), encoded directly +in 16 or 32 bits. +@item a32 +@itemx b32 +An immediate Scheme value, encoded as a pair of 32-bit words. +@code{a32} and @code{b32} values always go together on the same opcode, +and indicate the high and low bits, respectively. Normally only used on +64-bit systems. +@item n32 +A statically allocated non-immediate. The address of the non-immediate +is encoded as a signed 32-bit integer, and indicates a relative offset +in 32-bit units. Think of it as @code{SCM x = ip + offset}. +@item r32 +Indirect scheme value, like @code{n32} but indirected. Think of it as +@code{SCM *x = ip + offset}. +@item l32 +@item lo32 +An ip-relative address, as a signed 32-bit integer. Could indicate a +bytecode address, as in @code{make-closure}, or a non-immediate address, +as with @code{static-patch!}. + +@code{l32} and @code{lo32} are the same from the perspective of the +virtual machine. The difference is that an assembler might want to +allow an @code{lo32} address to be specified as a label and then some +number of words offset from that label, for example when patching a +field of a statically allocated object. +@item b1 +A boolean value: 1 for true, otherwise 0. +@item x@var{n} +An ignored sequence of @var{n} bits. +@end table + +An instruction is specified by giving its name, then describing its +operands. The operands are packed by 32-bit words, with earlier +operands occupying the lower bits. + +For example, consider the following instruction specification: + +@deftypefn Instruction {} call f24:@var{proc} x8:@var{_} c24:@var{nlocals} +@end deftypefn + +The first word in the instruction will start with the 8-bit value +corresponding to the @var{call} opcode in the low bits, followed by +@var{proc} as a 24-bit value. The second word starts with 8 dead bits, +followed by the index as a 24-bit immediate value. + +For instructions with operands that encode references to the stack, the +interpretation of those stack values is up to the instruction itself. +Most instructions expect their operands to be tagged SCM values +(@code{scm} representation), but some instructions expect unboxed +integers (@code{u64} and @code{s64} representations) or floating-point +numbers (@code{f64} representation). It is assumed that the bits for a +@code{u64} value are the same as those for an @code{s64} value, and that +@code{s64} values are stored in two's complement. + +Instructions have static types: they must receive their operands in the +format they expect. It's up to the compiler to ensure this is the case. + +Unless otherwise mentioned, all operands and results are in the +@code{scm} representation. + +@menu +* Call and Return Instructions:: +* Function Prologue Instructions:: +* Shuffling Instructions:: +* Trampoline Instructions:: +* Non-Local Control Flow Instructions:: +* Instrumentation Instructions:: +* Intrinsic Call Instructions:: +* Constant Instructions:: +* Memory Access Instructions:: +* Atomic Memory Access Instructions:: +* Tagging and Untagging Instructions:: +* Integer Arithmetic Instructions:: +* Floating-Point Arithmetic Instructions:: +* Comparison Instructions:: +* Branch Instructions:: +* Raw Memory Access Instructions:: +@end menu + + +@node Call and Return Instructions +@subsubsection Call and Return Instructions + +As described earlier (@pxref{Stack Layout}), Guile's calling convention +is that arguments are passed and values returned on the stack. + +For calls, both in tail position and in non-tail position, we require +that the procedure and the arguments already be shuffled into place +before the call instruction. ``Into place'' for a tail call means that +the procedure should be in slot 0, relative to the @code{fp}, and the +arguments should follow. For a non-tail call, if the procedure is in +@code{fp}-relative slot @var{n}, the arguments should follow from slot +@var{n}+1, and there should be three free slots between @var{n}-1 and +@var{n}-3 in which to save the mRA, vRA, and @code{fp}. + +Returning values is similar. Multiple-value returns should have values +already shuffled down to start from @code{fp}-relative slot 0 before +emitting @code{return-values}. + +In both calls and returns, the @code{sp} is used to indicate to the +callee or caller the number of arguments or return values, respectively. +After receiving return values, it is the caller's responsibility to +@dfn{restore the frame} by resetting the @code{sp} to its former value. + +@deftypefn Instruction {} call f24:@var{proc} x8:@var{_} c24:@var{nlocals} +Call a procedure. @var{proc} is the local corresponding to a procedure. +The three values below @var{proc} will be overwritten by the saved call +frame data. The new frame will have space for @var{nlocals} locals: one +for the procedure, and the rest for the arguments which should already +have been pushed on. + +When the call returns, execution proceeds with the next instruction. +There may be any number of values on the return stack; the precise +number can be had by subtracting the address of @var{proc}-1 from the +post-call @code{sp}. +@end deftypefn + +@deftypefn Instruction {} call-label f24:@var{proc} x8:@var{_} c24:@var{nlocals} l32:@var{label} +Call a procedure in the same compilation unit. + +This instruction is just like @code{call}, except that instead of +dereferencing @var{proc} to find the call target, the call target is +known to be at @var{label}, a signed 32-bit offset in 32-bit units from +the current @code{ip}. Since @var{proc} is not dereferenced, it may be +some other representation of the closure. +@end deftypefn + +@deftypefn Instruction {} tail-call x24:@var{_} +Tail-call a procedure. Requires that the procedure and all of the +arguments have already been shuffled into position, and that the frame +has already been reset to the number of arguments to the call. +@end deftypefn + +@deftypefn Instruction {} tail-call-label x24:@var{_} l32:@var{label} +Tail-call a known procedure. As @code{call} is to @code{call-label}, +@code{tail-call} is to @code{tail-call-label}. +@end deftypefn + +@deftypefn Instruction {} return-values x24:@var{_} +Return a number of values from a call frame. The return values should +have already been shuffled down to a contiguous array starting at slot +0, and the frame already reset. +@end deftypefn + +@deftypefn Instruction {} receive f12:@var{dst} f12:@var{proc} x8:@var{_} c24:@var{nlocals} +Receive a single return value from a call whose procedure was in +@var{proc}, asserting that the call actually returned at least one +value. Afterwards, resets the frame to @var{nlocals} locals. +@end deftypefn + +@deftypefn Instruction {} receive-values f24:@var{proc} b1:@var{allow-extra?} x7:@var{_} c24:@var{nvalues} +Receive a return of multiple values from a call whose procedure was in +@var{proc}. If fewer than @var{nvalues} values were returned, signal an +error. Unless @var{allow-extra?} is true, require that the number of +return values equals @var{nvalues} exactly. After @code{receive-values} +has run, the values can be copied down via @code{mov}, or used in place. +@end deftypefn + + +@node Function Prologue Instructions +@subsubsection Function Prologue Instructions + +A function call in Guile is very cheap: the VM simply hands control to +the procedure. The procedure itself is responsible for asserting that it +has been passed an appropriate number of arguments. This strategy allows +arbitrarily complex argument parsing idioms to be developed, without +harming the common case. + +For example, only calls to keyword-argument procedures ``pay'' for the +cost of parsing keyword arguments. (At the time of this writing, calling +procedures with keyword arguments is typically two to four times as +costly as calling procedures with a fixed set of arguments.) + +@deftypefn Instruction {} assert-nargs-ee c24:@var{expected} +@deftypefnx Instruction {} assert-nargs-ge c24:@var{expected} +@deftypefnx Instruction {} assert-nargs-le c24:@var{expected} +If the number of actual arguments is not @code{==}, @code{>=}, or +@code{<=} @var{expected}, respectively, signal an error. + +The number of arguments is determined by subtracting the stack pointer +from the frame pointer (@code{fp - sp}). @xref{Stack Layout}, for more +details on stack frames. Note that @var{expected} includes the +procedure itself. +@end deftypefn + +@deftypefn Instruction {} arguments<=? c24:@var{expected} +Set the @code{LESS_THAN}, @code{EQUAL}, or @code{NONE} comparison result +values if the number of arguments is respectively less than, equal to, +or greater than @var{expected}. +@end deftypefn + +@deftypefn Instruction {} positional-arguments<=? c24:@var{nreq} x8:@var{_} c24:@var{expected} +Set the @code{LESS_THAN}, @code{EQUAL}, or @code{NONE} comparison result +values if the number of positional arguments is respectively less than, +equal to, or greater than @var{expected}. The first @var{nreq} +arguments are positional arguments, as are the subsequent arguments that +are not keywords. +@end deftypefn + +The @code{arguments<=?} and @code{positional-arguments<=?} instructions +are used to implement multiple arities, as in @code{case-lambda}. +@xref{Case-lambda}, for more information. @xref{Branch Instructions}, +for more on comparison results. + +@deftypefn Instruction {} bind-kwargs c24:@var{nreq} c8:@var{flags} c24:@var{nreq-and-opt} x8:@var{_} c24:@var{ntotal} n32:@var{kw-offset} +@var{flags} is a bitfield, whose lowest bit is @var{allow-other-keys}, +second bit is @var{has-rest}, and whose following six bits are unused. + +Find the last positional argument, and shuffle all the rest above +@var{ntotal}. Initialize the intervening locals to +@code{SCM_UNDEFINED}. Then load the constant at @var{kw-offset} words +from the current @var{ip}, and use it and the @var{allow-other-keys} +flag to bind keyword arguments. If @var{has-rest}, collect all shuffled +arguments into a list, and store it in @var{nreq-and-opt}. Finally, +clear the arguments that we shuffled up. + +The parsing is driven by a keyword arguments association list, looked up +using @var{kw-offset}. The alist is a list of pairs of the form +@code{(@var{kw} . @var{index})}, mapping keyword arguments to their +local slot indices. Unless @code{allow-other-keys} is set, the parser +will signal an error if an unknown key is found. + +A macro-mega-instruction. +@end deftypefn + +@deftypefn Instruction {} bind-rest f24:@var{dst} +Collect any arguments at or above @var{dst} into a list, and store that +list at @var{dst}. +@end deftypefn + +@deftypefn Instruction {} alloc-frame c24:@var{nlocals} +Ensure that there is space on the stack for @var{nlocals} local +variables, setting them all to @code{SCM_UNDEFINED}, except those values +that are already on the stack. +@end deftypefn + +@deftypefn Instruction {} reset-frame c24:@var{nlocals} +Like @code{alloc-frame}, but doesn't check that the stack is big enough, +and doesn't initialize values to @code{SCM_UNDEFINED}. Used to reset +the frame size to something less than the size that was previously set +via alloc-frame. +@end deftypefn + +@deftypefn Instruction {} assert-nargs-ee/locals c12:@var{expected} c12:@var{nlocals} +Equivalent to a sequence of @code{assert-nargs-ee} and +@code{allocate-frame}. The number of locals reserved is @var{expected} ++ @var{nlocals}. +@end deftypefn + + +@node Shuffling Instructions +@subsubsection Shuffling Instructions + +These instructions are used to move around values on the stack. + +@deftypefn Instruction {} mov s12:@var{dst} s12:@var{src} +@deftypefnx Instruction {} long-mov s24:@var{dst} x8:@var{_} s24:@var{src} +Copy a value from one local slot to another. + +As discussed previously, procedure arguments and local variables are +allocated to local slots. Guile's compiler tries to avoid shuffling +variables around to different slots, which often makes @code{mov} +instructions redundant. However there are some cases in which shuffling +is necessary, and in those cases, @code{mov} is the thing to use. +@end deftypefn + +@deftypefn Instruction {} long-fmov f24:@var{dst} x8:@var{_} f24:@var{src} +Copy a value from one local slot to another, but addressing slots +relative to the @code{fp} instead of the @code{sp}. This is used when +shuffling values into place after multiple-value returns. +@end deftypefn + +@deftypefn Instruction {} push s24:@var{src} +Bump the stack pointer by one word, and fill it with the value from slot +@var{src}. The offset to @var{src} is calculated before the stack +pointer is adjusted. +@end deftypefn + +The @code{push} instruction is used when another instruction is unable +to address an operand because the operand is encoded with fewer than 24 +bits. In that case, Guile's assembler will transparently emit code that +temporarily pushes any needed operands onto the stack, emits the +original instruction to address those now-near variables, then shuffles +the result (if any) back into place. + +@deftypefn Instruction {} pop s24:@var{dst} +Pop the stack pointer, storing the value that was there in slot +@var{dst}. The offset to @var{dst} is calculated after the stack +pointer is adjusted. +@end deftypefn + +@deftypefn Instruction {} drop c24:@var{count} +Pop the stack pointer by @var{count} words, discarding any values that +were stored there. +@end deftypefn + +@deftypefn Instruction {} shuffle-down f12:@var{from} f12:@var{to} +Shuffle down values from @var{from} to @var{to}, reducing the frame size +by @var{FROM}-@var{TO} slots. Part of the internal implementation of +@code{call-with-values}, @code{values}, and @code{apply}. +@end deftypefn + +@deftypefn Instruction {} expand-apply-argument x24:@var{_} +Take the last local in a frame and expand it out onto the stack, as for +the last argument to @code{apply}. +@end deftypefn + + +@node Trampoline Instructions +@subsubsection Trampoline Instructions + +Though most applicable objects in Guile are procedures implemented in +bytecode, not all are. There are primitives, continuations, and other +procedure-like objects that have their own calling convention. Instead +of adding special cases to the @code{call} instruction, Guile wraps +these other applicable objects in VM trampoline procedures, then +provides special support for these objects in bytecode. + +Trampoline procedures are typically generated by Guile at runtime, for +example in response to a call to @code{scm_c_make_gsubr}. As such, a +compiler probably shouldn't emit code with these instructions. However, +it's still interesting to know how these things work, so we document +these trampoline instructions here. + +@deftypefn Instruction {} subr-call c24:@var{idx} +Call a subr, passing all locals in this frame as arguments, and storing +the results on the stack, ready to be returned. +@end deftypefn + +@deftypefn Instruction {} foreign-call c12:@var{cif-idx} c12:@var{ptr-idx} +Call a foreign function. Fetch the @var{cif} and foreign pointer from +@var{cif-idx} and @var{ptr-idx} closure slots of the callee. Arguments +are taken from the stack, and results placed on the stack, ready to be +returned. +@end deftypefn + +@deftypefn Instruction {} builtin-ref s12:@var{dst} c12:@var{idx} +Load a builtin stub by index into @var{dst}. +@end deftypefn + + +@node Non-Local Control Flow Instructions +@subsubsection Non-Local Control Flow Instructions + +@deftypefn Instruction {} capture-continuation s24:@var{dst} +Capture the current continuation, and write it to @var{dst}. Part of +the implementation of @code{call/cc}. +@end deftypefn + +@deftypefn Instruction {} continuation-call c24:@var{contregs} +Return to a continuation, nonlocally. The arguments to the continuation +are taken from the stack. @var{contregs} is a free variable containing +the reified continuation. +@end deftypefn + +@deftypefn Instruction {} abort x24:@var{_} +Abort to a prompt handler. The tag is expected in slot 1, and the rest +of the values in the frame are returned to the prompt handler. This +corresponds to a tail application of @code{abort-to-prompt}. + +If no prompt can be found in the dynamic environment with the given tag, +an error is signalled. Otherwise all arguments are passed to the +prompt's handler, along with the captured continuation, if necessary. + +If the prompt's handler can be proven to not reference the captured +continuation, no continuation is allocated. This decision happens +dynamically, at run-time; the general case is that the continuation may +be captured, and thus resumed. A reinstated continuation will have its +arguments pushed on the stack from slot 0, as if from a multiple-value +return, and control resumes in the caller. Thus to the calling +function, a call to @code{abort-to-prompt} looks like any other function +call. +@end deftypefn + +@deftypefn Instruction {} compose-continuation c24:@var{cont} +Compose a partial continuation with the current continuation. The +arguments to the continuation are taken from the stack. @var{cont} is a +free variable containing the reified continuation. +@end deftypefn + +@deftypefn Instruction {} prompt s24:@var{tag} b1:@var{escape-only?} x7:@var{_} f24:@var{proc-slot} x8:@var{_} l24:@var{handler-offset} +Push a new prompt on the dynamic stack, with a tag from @var{tag} and a +handler at @var{handler-offset} words from the current @var{ip}. + +If an abort is made to this prompt, control will jump to the handler. +The handler will expect a multiple-value return as if from a call with +the procedure at @var{proc-slot}, with the reified partial continuation +as the first argument, followed by the values returned to the handler. +If control returns to the handler, the prompt is already popped off by +the abort mechanism. (Guile's @code{prompt} implements Felleisen's +@dfn{--F--} operator.) + +If @var{escape-only?} is nonzero, the prompt will be marked as +escape-only, which allows an abort to this prompt to avoid reifying the +continuation. + +@xref{Prompts}, for more information on prompts. +@end deftypefn + +@deftypefn Instruction {} throw s12:@var{key} s12:@var{args} +Raise an error by throwing to @var{key} and @var{args}. @var{args} +should be a list. +@end deftypefn + +@deftypefn Instruction {} throw/value s24:@var{value} n32:@var{key-subr-and-message} +@deftypefnx Instruction {} throw/value+data s24:@var{value} n32:@var{key-subr-and-message} +Raise an error, indicating @var{val} as the bad value. +@var{key-subr-and-message} should be a vector, where the first element +is the symbol to which to throw, the second is the procedure in which to +signal the error (a string) or @code{#f}, and the third is a format +string for the message, with one template. These instructions do not +fall through. + +Both of these instructions throw to a key with four arguments: the +procedure that indicates the error (or @code{#f}, the format string, a +list with @var{value}, and either @code{#f} or the list with @var{value} +as the last argument respectively. +@end deftypefn + + +@node Instrumentation Instructions +@subsubsection Instrumentation Instructions + +@deftypefn Instruction {} instrument-entry x24_@var{_} n32:@var{data} +@deftypefnx Instruction {} instrument-loop x24_@var{_} n32:@var{data} +Increase execution counter for this function and potentially tier up to +the next JIT level. @var{data} is an offset to a structure recording +execution counts and the next-level JIT code corresponding to this +function. The increment values are currently 30 for +@code{instrument-entry} and 2 for @code{instrument-loop}. + +@code{instrument-entry} will also run the apply hook, if VM hooks are +enabled. +@end deftypefn + +@deftypefn Instruction {} handle-interrupts x24:@var{_} +Handle pending asynchronous interrupts (asyncs). @xref{Asyncs}. The +compiler inserts @code{handle-interrupts} instructions before any call, +return, or loop back-edge. +@end deftypefn + +@deftypefn Instruction {} return-from-interrupt x24:@var{_} +A special instruction to return from a call and also pop off the stack +frame from the call. Used when returning from asynchronous interrupts. +@end deftypefn + + +@node Intrinsic Call Instructions +@subsubsection Intrinsic Call Instructions + +Guile's instruction set is low-level. This is good because the separate +components of, say, a @code{vector-ref} operation might be able to be +optimized out, leaving only the operations that need to be performed at +run-time. + +However some macro-operations may need to perform large amounts of +computation at run-time to handle all the edge cases, and whose +micro-operation components aren't amenable to optimization. +Residualizing code for the entire macro-operation would lead to code +bloat with no benefit. + +In this kind of a case, Guile's VM calls out to @dfn{intrinsics}: +run-time routines written in the host language (currently C, possibly +more in the future if Guile gains more run-time targets like +WebAssembly). There is one instruction for each instrinsic prototype; +the intrinsic is specified by index in the instruction. + +@deftypefn Instruction {} call-thread x24:@var{_} c32:@var{idx} +Call the @code{void}-returning instrinsic with index @var{idx}, passing +the current @code{scm_thread*} as the argument. +@end deftypefn + +@deftypefn Instruction {} call-thread-scm s24:@var{a} c32:@var{idx} +Call the @code{void}-returning instrinsic with index @var{idx}, passing +the current @code{scm_thread*} and the @code{scm} local @var{a} as +arguments. +@end deftypefn + +@deftypefn Instruction {} call-thread-scm-scm s12:@var{a} s12:@var{b} c32:@var{idx} +Call the @code{void}-returning instrinsic with index @var{idx}, passing +the current @code{scm_thread*} and the @code{scm} locals @var{a} and +@var{b} as arguments. +@end deftypefn + +@deftypefn Instruction {} call-scm-sz-u32 s12:@var{a} s12:@var{b} c32:@var{idx} +Call the @code{void}-returning instrinsic with index @var{idx}, passing +the locals @var{a}, @var{b}, and @var{c} as arguments. @var{a} is a +@code{scm} value, while @var{b} and @var{c} are raw @code{u64} values +which fit into @code{size_t} and @code{uint32_t} types, respectively. +@end deftypefn + +@deftypefn Instruction {} call-scm<-u64 s24:@var{dst} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +the current @code{scm_thread*} as the argument. Place the result in +@var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-u64 s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{u64} local @var{a} as the argument. Place the result in +@var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-s64 s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{s64} local @var{a} as the argument. Place the result in +@var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-scm s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{scm} local @var{a} as the argument. Place the result in +@var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-u64<-scm s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{uint64_t}-returning instrinsic with index @var{idx}, +passing @code{scm} local @var{a} as the argument. Place the @code{u64} +result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-s64<-scm s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{int64_t}-returning instrinsic with index @var{idx}, +passing @code{scm} local @var{a} as the argument. Place the @code{s64} +result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-f64<-scm s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{double}-returning instrinsic with index @var{idx}, +passing @code{scm} local @var{a} as the argument. Place the @code{f64} +result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-scm-scm s8:@var{dst} s8:@var{a} s8:@var{b} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{scm} locals @var{a} and @var{b} as arguments. Place the +@code{scm} result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-scm-uimm s8:@var{dst} s8:@var{a} c8:@var{b} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{scm} local @var{a} and @code{uint8_t} immediate @var{b} as +arguments. Place the @code{scm} result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-thread-scm s12:@var{dst} s12:@var{a} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +the current @code{scm_thread*} and @code{scm} local @var{a} as +arguments. Place the @code{scm} result in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} call-scm<-scm-u64 s8:@var{dst} s8:@var{a} s8:@var{b} c32:@var{idx} +Call the @code{SCM}-returning instrinsic with index @var{idx}, passing +@code{scm} local @var{a} and @code{u64} local @var{b} as arguments. +Place the @code{scm} result in @var{dst}. +@end deftypefn + +There are corresponding macro-instructions for specific intrinsics. +These are equivalent to @code{call-@var{instrinsic-kind}} instructions +with the appropriate intrinsic @var{idx} arguments. + +@deffn {Macro Instruction} add dst a b +@deffnx {Macro Instruction} add/immediate dst a b/imm +Add @code{SCM} values @var{a} and @var{b} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} sub dst a b +@deffnx {Macro Instruction} sub/immediate dst a b/imm +Subtract @code{SCM} value @var{b} from @var{a} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} mul dst a b +Multiply @code{SCM} values @var{a} and @var{b} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} div dst a b +Divide @code{SCM} value @var{a} by @var{b} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} quo dst a b +Compute the quotient of @code{SCM} values @var{a} and @var{b} and place +the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} rem dst a b +Compute the remainder of @code{SCM} values @var{a} and @var{b} and place +the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} mod dst a b +Compute the modulo of @code{SCM} value @var{a} by @var{b} and place the +result in @var{dst}. +@end deffn +@deffn {Macro Instruction} logand dst a b +Compute the bitwise @code{and} of @code{SCM} values @var{a} and @var{b} +and place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} logior dst a b +Compute the bitwise inclusive @code{or} of @code{SCM} values @var{a} and +@var{b} and place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} logxor dst a b +Compute the bitwise exclusive @code{or} of @code{SCM} values @var{a} and +@var{b} and place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} logsub dst a b +Compute the bitwise @code{and} of @code{SCM} value @var{a} and the +bitwise @code{not} of @var{b} and place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} lsh dst a b +@deffnx {Macro Instruction} lsh/immediate a b/imm +Shift @code{SCM} value @var{a} left by @code{u64} value @var{b} bits and +place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} rsh dst a b +@deffnx {Macro Instruction} rsh/immediate dst a b/imm +Shifts @code{SCM} value @var{a} right by @code{u64} value @var{b} bits +and place the result in @var{dst}. +@end deffn +@deffn {Macro Instruction} scm->f64 dst src +Convert @var{src} to an unboxed @code{f64} and place the result in +@var{dst}, or raises an error if @var{src} is not a real number. +@end deffn +@deffn {Macro Instruction} scm->u64 dst src +Convert @var{src} to an unboxed @code{u64} and place the result in +@var{dst}, or raises an error if @var{src} is not an integer within +range. +@end deffn +@deffn {Macro Instruction} scm->u64/truncate dst src +Convert @var{src} to an unboxed @code{u64} and place the result in +@var{dst}, truncating to the low 64 bits, or raises an error if +@var{src} is not an integer. +@end deffn +@deffn {Macro Instruction} scm->s64 dst src +Convert @var{src} to an unboxed @code{s64} and place the result in +@var{dst}, or raises an error if @var{src} is not an integer within +range. +@end deffn +@deffn {Macro Instruction} u64->scm dst src +Convert @var{u64} value @var{src} to a Scheme integer in @var{dst}. +@end deffn +@deffn {Macro Instruction} s64->scm scm<-s64 +Convert @var{s64} value @var{src} to a Scheme integer in @var{dst}. +@end deffn +@deffn {Macro Instruction} string-set! str idx ch +Sets the character @var{idx} (a @code{u64}) of string @var{str} to +@var{ch} (a @code{u64} that is a valid character value). +@end deffn +@deffn {Macro Instruction} string->number dst src +Call @code{string->number} on @var{src} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} string->symbol dst src +Call @code{string->symbol} on @var{src} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} symbol->keyword dst src +Call @code{symbol->keyword} on @var{src} and place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} class-of dst src +Set @var{dst} to the GOOPS class of @code{src}. +@end deffn +@deffn {Macro Instruction} wind winder unwinder +Push wind and unwind procedures onto the dynamic stack. Note that +neither are actually called; the compiler should emit calls to +@var{winder} and @var{unwinder} for the normal dynamic-wind control +flow. Also note that the compiler should have inserted checks that +@var{winder} and @var{unwinder} are thunks, if it could not prove that +to be the case. @xref{Dynamic Wind}. +@end deffn +@deffn {Macro Instruction} unwind +Exit from the dynamic extent of an expression, popping the top entry off +of the dynamic stack. +@end deffn +@deffn {Macro Instruction} push-fluid fluid value +Dynamically bind @var{value} to @var{fluid} by creating a with-fluids +object, pushing that object on the dynamic stack. @xref{Fluids and +Dynamic States}. +@end deffn +@deffn {Macro Instruction} pop-fluid +Leave the dynamic extent of a @code{with-fluid*} expression, restoring +the fluid to its previous value. @code{push-fluid} should always be +balanced with @code{pop-fluid}. +@end deffn +@deffn {Macro Instruction} fluid-ref dst fluid +Place the value associated with the fluid @var{fluid} in @var{dst}. +@end deffn +@deffn {Macro Instruction} fluid-set! fluid value +Set the value of the fluid @var{fluid} to @var{value}. +@end deffn +@deffn {Macro Instruction} push-dynamic-state state +Save the current set of fluid bindings on the dynamic stack and instate +the bindings from @var{state} instead. @xref{Fluids and Dynamic +States}. +@end deffn +@deffn {Macro Instruction} pop-dynamic-state +Restore a saved set of fluid bindings from the dynamic stack. +@code{push-dynamic-state} should always be balanced with +@code{pop-dynamic-state}. +@end deffn +@deffn {Macro Instruction} resolve-module dst name public? +Look up the module named @var{name}, resolve its public interface if the +immediate operand @var{public?} is true, then place the result in +@var{dst}. +@end deffn +@deffn {Macro Instruction} lookup dst mod sym +Look up @var{sym} in module @var{mod}, placing the resulting variable +(or @code{#f} if not found) in @var{dst}. +@end deffn +@deffn {Macro Instruction} define! dst mod sym +Look up @var{sym} in module @var{mod}, placing the resulting variable in +@var{dst}, creating the variable if needed. +@end deffn +@deffn {Macro Instruction} current-module dst +Set @var{dst} to the current module. +@end deffn + + +@node Constant Instructions +@subsubsection Constant Instructions + +The following instructions load literal data into a program. There are +two kinds. + +The first set of instructions loads immediate values. These +instructions encode the immediate directly into the instruction stream. + +@deftypefn Instruction {} make-short-immediate s8:@var{dst} i16:@var{low-bits} +Make an immediate whose low bits are @var{low-bits}, and whose top bits are +0. +@end deftypefn + +@deftypefn Instruction {} make-long-immediate s24:@var{dst} i32:@var{low-bits} +Make an immediate whose low bits are @var{low-bits}, and whose top bits are +0. +@end deftypefn + +@deftypefn Instruction {} make-long-long-immediate s24:@var{dst} a32:@var{high-bits} b32:@var{low-bits} +Make an immediate with @var{high-bits} and @var{low-bits}. +@end deftypefn + +Non-immediate constant literals are referenced either directly or +indirectly. For example, Guile knows at compile-time what the layout of +a string will be like, and arranges to embed that object directly in the +compiled image. A reference to a string will use +@code{make-non-immediate} to treat a pointer into the compilation unit +as a @code{scm} value directly. + +@deftypefn Instruction {} make-non-immediate s24:@var{dst} n32:@var{offset} +Load a pointer to statically allocated memory into @var{dst}. The +object's memory is will be found @var{offset} 32-bit words away from the +current instruction pointer. Whether the object is mutable or immutable +depends on where it was allocated by the compiler, and loaded by the +loader. +@end deftypefn + +Sometimes you need to load up a code pointer into a register; for this, +use @code{load-label}. + +@deftypefn Instruction {} make-non-immediate s24:@var{dst} l32:@var{offset} +Load a label @var{offset} words away from the current @code{ip} and +write it to @var{dst}. @var{offset} is a signed 32-bit integer. +@end deftypefn + +Finally, Guile supports a number of unboxed data types, with their +associate constant loaders. + +@deftypefn Instruction {} load-f64 s24:@var{dst} au32:@var{high-bits} au32:@var{low-bits} +Load a double-precision floating-point value formed by joining +@var{high-bits} and @var{low-bits}, and write it to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} load-u64 s24:@var{dst} au32:@var{high-bits} au32:@var{low-bits} +Load an unsigned 64-bit integer formed by joining @var{high-bits} and +@var{low-bits}, and write it to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} load-s64 s24:@var{dst} au32:@var{high-bits} au32:@var{low-bits} +Load a signed 64-bit integer formed by joining @var{high-bits} and +@var{low-bits}, and write it to @var{dst}. +@end deftypefn + +Some objects must be unique across the whole system. This is the case +for symbols and keywords. For these objects, Guile arranges to +initialize them when the compilation unit is loaded, storing them into a +slot in the image. References go indirectly through that slot. +@code{static-ref} is used in this case. + +@deftypefn Instruction {} static-ref s24:@var{dst} r32:@var{offset} +Load a @var{scm} value into @var{dst}. The @var{scm} value will be fetched from +memory, @var{offset} 32-bit words away from the current instruction +pointer. @var{offset} is a signed value. +@end deftypefn + +Fields of non-immediates may need to be fixed up at load time, because +we do not know in advance at what address they will be loaded. This is +the case, for example, for a pair containing a non-immediate in one of +its fields. @code{static-ref} and @code{static-patch!} are used in +these situations. + +@deftypefn Instruction {} static-set! s24:@var{src} lo32:@var{offset} +Store a @var{scm} value into memory, @var{offset} 32-bit words away from the +current instruction pointer. @var{offset} is a signed value. +@end deftypefn + +@deftypefn Instruction {} static-patch! x24:@var{_} lo32:@var{dst-offset} l32:@var{src-offset} +Patch a pointer at @var{dst-offset} to point to @var{src-offset}. Both offsets +are signed 32-bit values, indicating a memory address as a number +of 32-bit words away from the current instruction pointer. +@end deftypefn + + +@node Memory Access Instructions +@subsubsection Memory Access Instructions + +In these instructions, the @code{/immediate} variants represent their +indexes or counts as immediates; otherwise these values are unboxed u64 +locals. + +@deftypefn Instruction {} allocate-words s12:@var{dst} s12:@var{count} +@deftypefnx Instruction {} allocate-words/immediate s12:@var{dst} c12:@var{count} +Allocate a fresh GC-traced object consisting of @var{count} words and +store it into @var{dst}. +@end deftypefn + +@deftypefn Instruction {} scm-ref s8:@var{dst} s8:@var{obj} s8:@var{idx} +@deftypefnx Instruction {} scm-ref/immediate s8:@var{dst} s8:@var{obj} c8:@var{idx} +Load the @code{SCM} object at word offset @var{idx} from local +@var{obj}, and store it to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} scm-set! s8:@var{dst} s8:@var{idx} s8:@var{obj} +@deftypefnx Instruction {} scm-set!/immediate s8:@var{dst} c8:@var{idx} s8:@var{obj} +Store the @code{scm} local @var{val} into object @var{obj} at word +offset @var{idx}. +@end deftypefn + +@deftypefn Instruction {} scm-ref/tag s8:@var{dst} s8:@var{obj} c8:@var{tag} +Load the first word of @var{obj}, subtract the immediate @var{tag}, and store the +resulting @code{SCM} to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} scm-set!/tag s8:@var{obj} c8:@var{tag} s8:@var{val} +Set the first word of @var{obj} to the unpacked bits of the @code{scm} +value @var{val} plus the immediate value @var{tag}. +@end deftypefn + +@deftypefn Instruction {} word-ref s8:@var{dst} s8:@var{obj} s8:@var{idx} +@deftypefnx Instruction {} word-ref/immediate s8:@var{dst} s8:@var{obj} c8:@var{idx} +Load the word at offset @var{idx} from local @var{obj}, and store it to +the @code{u64} local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} word-set! s8:@var{dst} s8:@var{idx} s8:@var{obj} +@deftypefnx Instruction {} word-set!/immediate s8:@var{dst} c8:@var{idx} s8:@var{obj} +Store the @code{u64} local @var{val} into object @var{obj} at word +offset @var{idx}. +@end deftypefn + +@deftypefn Instruction {} pointer-ref/immediate s8:@var{dst} s8:@var{obj} c8:@var{idx} +Load the pointer at offset @var{idx} from local @var{obj}, and store it +to the unboxed pointer local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} pointer-set!/immediate s8:@var{dst} c8:@var{idx} s8:@var{obj} +Store the unboxed pointer local @var{val} into object @var{obj} at word +offset @var{idx}. +@end deftypefn + +@deftypefn Instruction {} tail-pointer-ref/immediate s8:@var{dst} s8:@var{obj} c8:@var{idx} +Compute the address of word offset @var{idx} from local @var{obj}, and store it +to @var{dst}. +@end deftypefn + + +@node Atomic Memory Access Instructions +@subsubsection Atomic Memory Access Instructions + +@deftypefn Instruction {} current-thread s24:@var{dst} +Write the current thread into @var{dst}. +@end deftypefn + +@deftypefn Instruction {} atomic-scm-ref/immediate s8:@var{dst} s8:@var{obj} c8:@var{idx} +Atomically load the @code{SCM} object at word offset @var{idx} from +local @var{obj}, using the sequential consistency memory model. Store +the result to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} atomic-scm-set!/immediate s8:@var{obj} c8:@var{idx} s8:@var{val} +Atomically set the @code{SCM} object at word offset @var{idx} from local +@var{obj} to @var{val}, using the sequential consistency memory model. +@end deftypefn + +@deftypefn Instruction {} atomic-scm-swap!/immediate s24:@var{dst} x8:@var{_} s24:@var{obj} c8:@var{idx} s24:@var{val} +Atomically swap the @code{SCM} value stored in object @var{obj} at word +offset @var{idx} with @var{val}, using the sequentially consistent +memory model. Store the previous value to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} atomic-scm-compare-and-swap!/immediate s24:@var{dst} x8:@var{_} s24:@var{obj} c8:@var{idx} s24:@var{expected} x8:@var{_} s24:@var{desired} +Atomically swap the @code{SCM} value stored in object @var{obj} at word +offset @var{idx} with @var{desired}, if and only if the value that was +there was @var{expected}, using the sequentially consistent memory +model. Store the value that was previously at @var{idx} from @var{obj} +in @var{dst}. +@end deftypefn + + +@node Tagging and Untagging Instructions +@subsubsection Tagging and Untagging Instructions + +@deftypefn Instruction {} tag-char s12:@var{dst} s12:@var{src} +Make a @code{SCM} character whose integer value is the @code{u64} in +@var{src}, and store it in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} untag-char s12:@var{dst} s12:@var{src} +Extract the integer value from the @code{SCM} character @var{src}, and +store the resulting @code{u64} in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} tag-fixnum s12:@var{dst} s12:@var{src} +Make a @code{SCM} integer whose value is the @code{s64} in @var{src}, +and store it in @var{dst}. +@end deftypefn + +@deftypefn Instruction {} untag-fixnum s12:@var{dst} s12:@var{src} +Extract the integer value from the @code{SCM} integer @var{src}, and +store the resulting @code{s64} in @var{dst}. +@end deftypefn + + +@node Integer Arithmetic Instructions +@subsubsection Integer Arithmetic Instructions + +@deftypefn Instruction {} uadd s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} uadd/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Add the @code{u64} values @var{a} and @var{b}, and store the @code{u64} +result to @var{dst}. Overflow will wrap. +@end deftypefn + +@deftypefn Instruction {} usub s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} usub/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Subtract the @code{u64} value @var{b} from @var{a}, and store the +@code{u64} result to @var{dst}. Underflow will wrap. +@end deftypefn + +@deftypefn Instruction {} umul s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} umul/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Multiply the @code{u64} values @var{a} and @var{b}, and store the +@code{u64} result to @var{dst}. Overflow will wrap. +@end deftypefn + +@deftypefn Instruction {} ulogand s8:@var{dst} s8:@var{a} s8:@var{b} +Place the bitwise @code{and} of the @code{u64} values @var{a} and +@var{b} into the @code{u64} local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} ulogior s8:@var{dst} s8:@var{a} s8:@var{b} +Place the bitwise inclusive @code{or} of the @code{u64} values @var{a} +and @var{b} into the @code{u64} local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} ulogxor s8:@var{dst} s8:@var{a} s8:@var{b} +Place the bitwise exclusive @code{or} of the @code{u64} values @var{a} +and @var{b} into the @code{u64} local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} ulogsub s8:@var{dst} s8:@var{a} s8:@var{b} +Place the bitwise @code{and} of the @code{u64} values @var{a} and the +bitwise @code{not} of @var{b} into the @code{u64} local @var{dst}. +@end deftypefn + +@deftypefn Instruction {} ulsh s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} ulsh/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Shift the unboxed unsigned 64-bit integer in @var{a} left by @var{b} +bits, also an unboxed unsigned 64-bit integer. Truncate to 64 bits and +write to @var{dst} as an unboxed value. Only the lower 6 bits of +@var{b} are used. +@end deftypefn + +@deftypefn Instruction {} ursh s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} ursh/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Shift the unboxed unsigned 64-bit integer in @var{a} right by @var{b} +bits, also an unboxed unsigned 64-bit integer. Truncate to 64 bits and +write to @var{dst} as an unboxed value. Only the lower 6 bits of +@var{b} are used. +@end deftypefn + +@deftypefn Instruction {} srsh s8:@var{dst} s8:@var{a} s8:@var{b} +@deftypefnx Instruction {} srsh/immediate s8:@var{dst} s8:@var{a} c8:@var{b} +Shift the unboxed signed 64-bit integer in @var{a} right by @var{b} +bits, also an unboxed signed 64-bit integer. Truncate to 64 bits and +write to @var{dst} as an unboxed value. Only the lower 6 bits of +@var{b} are used. +@end deftypefn + + +@node Floating-Point Arithmetic Instructions +@subsubsection Floating-Point Arithmetic Instructions + +@deftypefn Instruction {} fadd s8:@var{dst} s8:@var{a} s8:@var{b} +Add the @code{f64} values @var{a} and @var{b}, and store the @code{f64} +result to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} fsub s8:@var{dst} s8:@var{a} s8:@var{b} +Subtract the @code{f64} value @var{b} from @var{a}, and store the +@code{f64} result to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} fmul s8:@var{dst} s8:@var{a} s8:@var{b} +Multiply the @code{f64} values @var{a} and @var{b}, and store the +@code{f64} result to @var{dst}. +@end deftypefn + +@deftypefn Instruction {} fdiv s8:@var{dst} s8:@var{a} s8:@var{b} +Divide the @code{f64} values @var{a} by @var{b}, and store the +@code{f64} result to @var{dst}. +@end deftypefn + + +@node Comparison Instructions +@subsubsection Comparison Instructions + +@deftypefn Instruction {} u64=? s12:@var{a} s12:@var{b} +Set the comparison result to @var{EQUAL} if the @code{u64} values +@var{a} and @var{b} are the same, or @code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} u64<? s12:@var{a} s12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{u64} value +@var{a} is less than the @code{u64} value @var{b} are the same, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} s64<? s12:@var{a} s12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{s64} value +@var{a} is less than the @code{s64} value @var{b} are the same, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} s64-imm=? s12:@var{a} z12:@var{b} +Set the comparison result to @var{EQUAL} if the @code{s64} value @var{a} +is equal to the immediate @code{s64} value @var{b}, or @code{NONE} +otherwise. +@end deftypefn + +@deftypefn Instruction {} u64-imm<? s12:@var{a} c12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{u64} value +@var{a} is less than the immediate @code{u64} value @var{b}, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} imm-u64<? s12:@var{a} s12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{u64} +immediate @var{b} is less than the @code{u64} value @var{a}, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} s64-imm<? s12:@var{a} z12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{s64} value +@var{a} is less than the immediate @code{s64} value @var{b}, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} imm-s64<? s12:@var{a} z12:@var{b} +Set the comparison result to @code{LESS_THAN} if the @code{s64} +immediate @var{b} is less than the @code{s64} value @var{a}, or +@code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} f64=? s12:@var{a} s12:@var{b} +Set the comparison result to @var{EQUAL} if the f64 value @var{a} is +equal to the f64 value @var{b}, or @code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} f64<? s12:@var{a} s12:@var{b} +Set the comparison result to @code{LESS_THAN} if the f64 value @var{a} +is less than the f64 value @var{b}, @code{NONE} if @var{a} is greater +than or equal to @var{b}, or @code{INVALID} otherwise. +@end deftypefn + +@deftypefn Instruction {} =? s12:@var{a} s12:@var{b} +Set the comparison result to @var{EQUAL} if the SCM values @var{a} and +@var{b} are numerically equal, in the sense of the Scheme @code{=} +operator. Set to @code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} heap-numbers-equal? s12:@var{a} s12:@var{b} +Set the comparison result to @var{EQUAL} if the SCM values @var{a} and +@var{b} are numerically equal, in the sense of Scheme @code{=}. Set to +@code{NONE} otherwise. It is known that both @var{a} and @var{b} are +heap numbers. +@end deftypefn + +@deftypefn Instruction {} <? s12:@var{a} s12:@var{b} +Set the comparison result to @code{LESS_THAN} if the SCM value @var{a} +is less than the SCM value @var{b}, @code{NONE} if @var{a} is greater +than or equal to @var{b}, or @code{INVALID} otherwise. +@end deftypefn + +@deftypefn Instruction {} immediate-tag=? s24:@var{obj} c16:@var{mask} c16:@var{tag} +Set the comparison result to @var{EQUAL} if the result of a bitwise +@code{and} between the bits of @code{scm} value @var{a} and the +immediate @var{mask} is @var{tag}, or @code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} heap-tag=? s24:@var{obj} c16:@var{mask} c16:@var{tag} +Set the comparison result to @var{EQUAL} if the result of a bitwise +@code{and} between the first word of @code{scm} value @var{a} and the +immediate @var{mask} is @var{tag}, or @code{NONE} otherwise. +@end deftypefn + +@deftypefn Instruction {} eq? s12:@var{a} s12:@var{b} +Set the comparison result to @var{EQUAL} if the SCM values @var{a} and +@var{b} are @code{eq?}, or @code{NONE} otherwise. +@end deftypefn + +There are a set of macro-instructions for @code{immediate-tag=?} and +@code{heap-tag=?} as well that abstract away the precise type tag +values. @xref{The SCM Type in Guile}. + +@deffn {Macro Instruction} fixnum? x +@deffnx {Macro Instruction} heap-object? x +@deffnx {Macro Instruction} char? x +@deffnx {Macro Instruction} eq-false? x +@deffnx {Macro Instruction} eq-nil? x +@deffnx {Macro Instruction} eq-null? x +@deffnx {Macro Instruction} eq-true? x +@deffnx {Macro Instruction} unspecified? x +@deffnx {Macro Instruction} undefined? x +@deffnx {Macro Instruction} eof-object? x +@deffnx {Macro Instruction} null? x +@deffnx {Macro Instruction} false? x +@deffnx {Macro Instruction} nil? x +Emit a @code{immediate-tag=?} instruction that will set the comparison +result to @code{EQUAL} if @var{x} would pass the corresponding predicate +(e.g. @code{null?}), or @code{NONE} otherwise. +@end deffn + +@deffn {Macro Instruction} pair? x +@deffnx {Macro Instruction} struct? x +@deffnx {Macro Instruction} symbol? x +@deffnx {Macro Instruction} variable? x +@deffnx {Macro Instruction} vector? x +@deffnx {Macro Instruction} immutable-vector? x +@deffnx {Macro Instruction} mutable-vector? x +@deffnx {Macro Instruction} weak-vector? x +@deffnx {Macro Instruction} string? x +@deffnx {Macro Instruction} heap-number? x +@deffnx {Macro Instruction} hash-table? x +@deffnx {Macro Instruction} pointer? x +@deffnx {Macro Instruction} fluid? x +@deffnx {Macro Instruction} stringbuf? x +@deffnx {Macro Instruction} dynamic-state? x +@deffnx {Macro Instruction} frame? x +@deffnx {Macro Instruction} keyword? x +@deffnx {Macro Instruction} atomic-box? x +@deffnx {Macro Instruction} syntax? x +@deffnx {Macro Instruction} program? x +@deffnx {Macro Instruction} vm-continuation? x +@deffnx {Macro Instruction} bytevector? x +@deffnx {Macro Instruction} weak-set? x +@deffnx {Macro Instruction} weak-table? x +@deffnx {Macro Instruction} array? x +@deffnx {Macro Instruction} bitvector? x +@deffnx {Macro Instruction} smob? x +@deffnx {Macro Instruction} port? x +@deffnx {Macro Instruction} bignum? x +@deffnx {Macro Instruction} flonum? x +@deffnx {Macro Instruction} compnum? x +@deffnx {Macro Instruction} fracnum? x +Emit a @code{heap-tag=?} instruction that will set the comparison result +to @code{EQUAL} if @var{x} would pass the corresponding predicate +(e.g. @code{null?}), or @code{NONE} otherwise. +@end deffn + + +@node Branch Instructions +@subsubsection Branch Instructions + +All offsets to branch instructions are 24-bit signed numbers, which +count 32-bit units. This gives Guile effectively a 26-bit address range +for relative jumps. + +@deftypefn Instruction {} j l24:@var{offset} +Add @var{offset} to the current instruction pointer. +@end deftypefn + +@deftypefn Instruction {} jl l24:@var{offset} +If the last comparison result is @code{LESS_THAN}, add @var{offset}, a +signed 24-bit number, to the current instruction pointer. +@end deftypefn + +@deftypefn Instruction {} je l24:@var{offset} +If the last comparison result is @code{EQUAL}, add @var{offset}, a +signed 24-bit number, to the current instruction pointer. +@end deftypefn + +@deftypefn Instruction {} jnl l24:@var{offset} +If the last comparison result is not @code{LESS_THAN}, add @var{offset}, +a signed 24-bit number, to the current instruction pointer. +@end deftypefn + +@deftypefn Instruction {} jne l24:@var{offset} +If the last comparison result is not @code{EQUAL}, add @var{offset}, a +signed 24-bit number, to the current instruction pointer. +@end deftypefn + +@deftypefn Instruction {} jge l24:@var{offset} +If the last comparison result is @code{NONE}, add @var{offset}, a +signed 24-bit number, to the current instruction pointer. + +This is intended for use after a @code{<?} comparison, and is different +from @code{jnl} in the way it handles not-a-number (NaN) values: +@code{<?} sets @code{INVALID} instead of @code{NONE} if either value is +a NaN. For exact numbers, @code{jge} is the same as @code{jnl}. +@end deftypefn + +@deftypefn Instruction {} jnge l24:@var{offset} +If the last comparison result is not @code{NONE}, add @var{offset}, a +signed 24-bit number, to the current instruction pointer. + +This is intended for use after a @code{<?} comparison, and is different +from @code{jl} in the way it handles not-a-number (NaN) values: +@code{<?} sets @code{INVALID} instead of @code{NONE} if either value is +a NaN. For exact numbers, @code{jnge} is the same as @code{jl}. +@end deftypefn + + +@node Raw Memory Access Instructions +@subsubsection Raw Memory Access Instructions + +Bytevector operations correspond closely to what the current hardware +can do, so it makes sense to inline them to VM instructions, providing +a clear path for eventual native compilation. Without this, Scheme +programs would need other primitives for accessing raw bytes -- but +these primitives are as good as any. + +@deftypefn Instruction {} u8-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} s8-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} u16-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} s16-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} u32-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} s32-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} u64-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} s64-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} f32-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} +@deftypefnx Instruction {} f64-ref s8:@var{dst} s8:@var{ptr} s8:@var{idx} + +Fetch the item at byte offset @var{idx} from the raw pointer local +@var{ptr}, and store it in @var{dst}. All accesses use native +endianness. + +The @var{idx} value should be an unboxed unsigned 64-bit integer. + +The results are all written to the stack as unboxed values, either as +signed 64-bit integers, unsigned 64-bit integers, or IEEE double +floating point numbers. +@end deftypefn + +@deftypefn Instruction {} u8-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} s8-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} u16-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} s16-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} u32-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} s32-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} u64-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} s64-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} f32-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} +@deftypefnx Instruction {} f64-set! s8:@var{ptr} s8:@var{idx} s8:@var{val} + +Store @var{val} into memory pointed to by raw pointer local @var{ptr}, +at byte offset @var{idx}. Multibyte values are written using native +endianness. + +The @var{idx} value should be an unboxed unsigned 64-bit integer. + +The @var{val} values are all unboxed, either as signed 64-bit integers, +unsigned 64-bit integers, or IEEE double floating point numbers. +@end deftypefn + +@node Just-In-Time Native Code +@subsection Just-In-Time Native Code + +@cindex just-in-time compiler +@cindex jit compiler +@cindex template jit +@cindex compiler, just-in-time +The final piece of Guile's virtual machine is a just-in-time (JIT) +compiler from bytecode instructions to native code. It is faster to run +a function when its bytecode instructions are compiled to native code, +compared to having the VM interpret the instructions. + +The JIT compiler runs automatically, triggered by counters associated +with each function. The counter increments when functions are called +and during each loop iteration. Once a function's counter passes a +certain value, the function gets JIT-compiled. @xref{Instrumentation +Instructions}, for full details. + +Guile's JIT compiler is what is known as a @dfn{template JIT}. This +kind of JIT is very simple: for each instruction in a function, the JIT +compiler will emit a generic sequence of machine code corresponding to +the instruction kind, specializing that generic template to reference +the specific operands of the instruction being compiled. + +The strength of a template JIT is principally that it is very fast at +emitting code. It doesn't need to do any time-consuming analysis on the +bytecode that it is compiling to do its job. + +A template JIT is also very predictable: the native code emitted by a +template JIT has the same performance characteristics of the +corresponding bytecode, only that it runs faster. In theory you could +even generate the template-JIT machine code ahead of time, as it doesn't +depend on any value seen at run-time. + +This predictability makes it possible to reason about the performance of +a system in terms of bytecode, knowing that the conclusions apply to +native code emitted by a template JIT. + +Because the machine code corresponding to an instruction always performs +the same tasks that the interpreter would do for that instruction, +bytecode and a template JIT also allows Guile programmers to debug their +programs in terms of the bytecode model. When a Guile programmer sets a +breakpoint, Guile will disable the JIT for the thread being debugged, +falling back to the interpreter (which has the corresponding code to run +the hooks). @xref{VM Hooks}. + +Guile uses the GNU Lightning library to emit native code. This allows +Guile's template JIT supports practically all architectures, from +Itanium to MIPS. You can optimize a program on your x86-64 desktop and +you can know that the corresponding program on an AArch64 phone will +also get faster. + +The weaknesses of a template JIT are two-fold. Firstly, as a simple +back-end that has to run fast, a template JIT doesn't have time to do +analysis that could help it generate better code, notably global +register allocation and instruction selection. + +However this is a minor weakness compared to the inability to perform +significant, speculative program transformations. For example, Guile +could see that in an expression @code{(f x)}, that in practice @var{f} +always refers to the same function. An advanced JIT compiler would +speculatively inline @var{f} into the call-site, along with a dynamic +check to make sure that the assertion still held. But as a template JIT +doesn't pay attention to values only known at run-time, it can't make +this transformation. + +This limitation is mitigated in part by Guile's robust ahead-of-time +compiler which can already perform significant optimizations when it can +prove they will always be valid, and its low-level bytecode which is +able to represent the effect of those optimizations (e.g. elided +type-checks). @xref{Compiling to the Virtual Machine}, for more on +Guile's compiler. + +An ahead-of-time Scheme-to-bytecode strategy, complemented by a template +JIT, also particularly suits the somewhat static nature of Scheme. +Scheme programmers often write code in a way that makes the identity of +free variable references lexically apparent. For example, the @code{(f +x)} expression could appear within a @code{(let ((f (lambda (x) (1+ +x)))) ...)} expression, or we could see that @code{f} was imported from +a particular module where we know its binding. Ahead-of-time +compilation techniques can work well for a language like Scheme where +there is little polymorphism and much first-order programming. They do +not work so well for a language like JavaScript, which is highly mutable +at run-time and difficult to analyze due to method calls (which are +effectively higher-order calls). + +All that said, a template JIT works well for Guile at this point. It's +only a few thousand lines of maintainable code, it speeds up Scheme +programs, and it keeps the bulk of the Guile Scheme implementation +written in Scheme itself. The next step is probably to add +ahead-of-time native code emission to the back-end of the compiler +written in Scheme, to take advantage of the opportunity to do global +register allocation and instruction selection. Once this is working, it +can allow Guile to experiment with speculative optimizations in Scheme +as well. @xref{Extending the Compiler}, for more on future directions. diff --git a/doc/ref/web.texi b/doc/ref/web.texi new file mode 100644 index 000000000..c8fc488b7 --- /dev/null +++ b/doc/ref/web.texi @@ -0,0 +1,1975 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 2010, 2011, 2012, 2013, 2015, 2018 Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Web +@section @acronym{HTTP}, the Web, and All That +@cindex Web +@cindex WWW +@cindex HTTP + +It has always been possible to connect computers together and share +information between them, but the rise of the World Wide Web over the +last couple of decades has made it much easier to do so. The result is +a richly connected network of computation, in which Guile forms a part. + +By ``the web'', we mean the HTTP protocol@footnote{Yes, the P is for +protocol, but this phrase appears repeatedly in RFC 2616.} as handled by +servers, clients, proxies, caches, and the various kinds of messages and +message components that can be sent and received by that protocol, +notably HTML. + +On one level, the web is text in motion: the protocols themselves are +textual (though the payload may be binary), and it's possible to create +a socket and speak text to the web. But such an approach is obviously +primitive. This section details the higher-level data types and +operations provided by Guile: URIs, HTTP request and response records, +and a conventional web server implementation. + +The material in this section is arranged in ascending order, in which +later concepts build on previous ones. If you prefer to start with the +highest-level perspective, @pxref{Web Examples}, and work your way +back. + +@menu +* Types and the Web:: Types prevent bugs and security problems. +* URIs:: Universal Resource Identifiers. +* HTTP:: The Hyper-Text Transfer Protocol. +* HTTP Headers:: How Guile represents specific header values. +* Transfer Codings:: HTTP Transfer Codings. +* Requests:: HTTP requests. +* Responses:: HTTP responses. +* Web Client:: Accessing web resources over HTTP. +* Web Server:: Serving HTTP to the internet. +* Web Examples:: How to use this thing. +@end menu + +@node Types and the Web +@subsection Types and the Web + +It is a truth universally acknowledged, that a program with good use of +data types, will be free from many common bugs. Unfortunately, the +common practice in web programming seems to ignore this maxim. This +subsection makes the case for expressive data types in web programming. + +By ``expressive data types'', we mean that the data types @emph{say} +something about how a program solves a problem. For example, if we +choose to represent dates using SRFI 19 date records (@pxref{SRFI-19}), +this indicates that there is a part of the program that will always have +valid dates. Error handling for a number of basic cases, like invalid +dates, occurs on the boundary in which we produce a SRFI 19 date record +from other types, like strings. + +With regards to the web, data types are helpful in the two broad phases +of HTTP messages: parsing and generation. + +Consider a server, which has to parse a request, and produce a response. +Guile will parse the request into an HTTP request object +(@pxref{Requests}), with each header parsed into an appropriate Scheme +data type. This transition from an incoming stream of characters to +typed data is a state change in a program---the strings might parse, or +they might not, and something has to happen if they do not. (Guile +throws an error in this case.) But after you have the parsed request, +``client'' code (code built on top of the Guile web framework) will not +have to check for syntactic validity. The types already make this +information manifest. + +This state change on the parsing boundary makes programs more robust, +as they themselves are freed from the need to do a number of common +error checks, and they can use normal Scheme procedures to handle a +request instead of ad-hoc string parsers. + +The need for types on the response generation side (in a server) is more +subtle, though not less important. Consider the example of a POST +handler, which prints out the text that a user submits from a form. +Such a handler might include a procedure like this: + +@example +;; First, a helper procedure +(define (para . contents) + (string-append "<p>" (string-concatenate contents) "</p>")) + +;; Now the meat of our simple web application +(define (you-said text) + (para "You said: " text)) + +(display (you-said "Hi!")) +@print{} <p>You said: Hi!</p> +@end example + +This is a perfectly valid implementation, provided that the incoming +text does not contain the special HTML characters @samp{<}, @samp{>}, or +@samp{&}. But this provision of a restricted character set is not +reflected anywhere in the program itself: we must @emph{assume} that the +programmer understands this, and performs the check elsewhere. + +Unfortunately, the short history of the practice of programming does not +bear out this assumption. A @dfn{cross-site scripting} (@acronym{XSS}) +vulnerability is just such a common error in which unfiltered user input +is allowed into the output. A user could submit a crafted comment to +your web site which results in visitors running malicious Javascript, +within the security context of your domain: + +@example +(display (you-said "<script src=\"http://bad.com/nasty.js\" />")) +@print{} <p>You said: <script src="http://bad.com/nasty.js" /></p> +@end example + +The fundamental problem here is that both user data and the program +template are represented using strings. This identity means that types +can't help the programmer to make a distinction between these two, so +they get confused. + +There are a number of possible solutions, but perhaps the best is to +treat HTML not as strings, but as native s-expressions: as SXML. The +basic idea is that HTML is either text, represented by a string, or an +element, represented as a tagged list. So @samp{foo} becomes +@samp{"foo"}, and @samp{<b>foo</b>} becomes @samp{(b "foo")}. +Attributes, if present, go in a tagged list headed by @samp{@@}, like +@samp{(img (@@ (src "http://example.com/foo.png")))}. @xref{SXML}, for +more information. + +The good thing about SXML is that HTML elements cannot be confused with +text. Let's make a new definition of @code{para}: + +@example +(define (para . contents) + `(p ,@@contents)) + +(use-modules (sxml simple)) +(sxml->xml (you-said "Hi!")) +@print{} <p>You said: Hi!</p> + +(sxml->xml (you-said "<i>Rats, foiled again!</i>")) +@print{} <p>You said: <i>Rats, foiled again!</i></p> +@end example + +So we see in the second example that HTML elements cannot be unwittingly +introduced into the output. However it is now perfectly acceptable to +pass SXML to @code{you-said}; in fact, that is the big advantage of SXML +over everything-as-a-string. + +@example +(sxml->xml (you-said (you-said "<Hi!>"))) +@print{} <p>You said: <p>You said: <Hi!></p></p> +@end example + +The SXML types allow procedures to @emph{compose}. The types make +manifest which parts are HTML elements, and which are text. So you +needn't worry about escaping user input; the type transition back to a +string handles that for you. @acronym{XSS} vulnerabilities are a thing +of the past. + +Well. That's all very nice and opinionated and such, but how do I use +the thing? Read on! + +@node URIs +@subsection Universal Resource Identifiers + +Guile provides a standard data type for Universal Resource Identifiers +(URIs), as defined in RFC 3986. + +The generic URI syntax is as follows: + +@example +URI-reference := [scheme ":"] ["//" [userinfo "@@"] host [":" port]] path \ + [ "?" query ] [ "#" fragment ] +@end example + +For example, in the URI, @indicateurl{http://www.gnu.org/help/}, the +scheme is @code{http}, the host is @code{www.gnu.org}, the path is +@code{/help/}, and there is no userinfo, port, query, or fragment. + +Userinfo is something of an abstraction, as some legacy URI schemes +allowed userinfo of the form @code{@var{username}:@var{passwd}}. But +since passwords do not belong in URIs, the RFC does not want to condone +this practice, so it calls anything before the @code{@@} sign +@dfn{userinfo}. + +@example +(use-modules (web uri)) +@end example + +The following procedures can be found in the @code{(web uri)} +module. Load it into your Guile, using a form like the above, to have +access to them. + +The most common way to build a URI from Scheme is with the +@code{build-uri} function. + +@deffn {Scheme Procedure} build-uri scheme @ + [#:userinfo=@code{#f}] [#:host=@code{#f}] [#:port=@code{#f}] @ + [#:path=@code{""}] [#:query=@code{#f}] [#:fragment=@code{#f}] @ + [#:validate?=@code{#t}] +Construct a URI. @var{scheme} should be a symbol, @var{port} either a +positive, exact integer or @code{#f}, and the rest of the fields are +either strings or @code{#f}. If @var{validate?} is true, also run some +consistency checks to make sure that the constructed URI is valid. +@end deffn +@deffn {Scheme Procedure} uri? obj +Return @code{#t} if @var{obj} is a URI. +@end deffn + +Guile, URIs are represented as URI records, with a number of associated +accessors. + +@deffn {Scheme Procedure} uri-scheme uri +@deffnx {Scheme Procedure} uri-userinfo uri +@deffnx {Scheme Procedure} uri-host uri +@deffnx {Scheme Procedure} uri-port uri +@deffnx {Scheme Procedure} uri-path uri +@deffnx {Scheme Procedure} uri-query uri +@deffnx {Scheme Procedure} uri-fragment uri +Field accessors for the URI record type. The URI scheme will be a +symbol, or @code{#f} if the object is a relative-ref (see below). The +port will be either a positive, exact integer or @code{#f}, and the rest +of the fields will be either strings or @code{#f} if not present. +@end deffn + +@deffn {Scheme Procedure} string->uri string +Parse @var{string} into a URI object. Return @code{#f} if the string +could not be parsed. +@end deffn + +@deffn {Scheme Procedure} uri->string uri [#:include-fragment?=@code{#t}] +Serialize @var{uri} to a string. If the URI has a port that is the +default port for its scheme, the port is not included in the +serialization. If @var{include-fragment?} is given as false, the +resulting string will omit the fragment (if any). +@end deffn + +@deffn {Scheme Procedure} declare-default-port! scheme port +Declare a default port for the given URI scheme. +@end deffn + +@deffn {Scheme Procedure} uri-decode str [#:encoding=@code{"utf-8"}] [#:decode-plus-to-space? #t] +Percent-decode the given @var{str}, according to @var{encoding}, which +should be the name of a character encoding. + +Note that this function should not generally be applied to a full URI +string. For paths, use @code{split-and-decode-uri-path} instead. For +query strings, split the query on @code{&} and @code{=} boundaries, and +decode the components separately. + +Note also that percent-encoded strings encode @emph{bytes}, not +characters. There is no guarantee that a given byte sequence is a valid +string encoding. Therefore this routine may signal an error if the +decoded bytes are not valid for the given encoding. Pass @code{#f} for +@var{encoding} if you want decoded bytes as a bytevector directly. +@xref{Ports, @code{set-port-encoding!}}, for more information on +character encodings. + +If @var{decode-plus-to-space?} is true, which is the default, also +replace instances of the plus character @samp{+} with a space character. +This is needed when parsing @code{application/x-www-form-urlencoded} +data. + +Returns a string of the decoded characters, or a bytevector if +@var{encoding} was @code{#f}. +@end deffn + +@deffn {Scheme Procedure} uri-encode str [#:encoding=@code{"utf-8"}] [#:unescaped-chars] +Percent-encode any character not in the character set, +@var{unescaped-chars}. + +The default character set includes alphanumerics from ASCII, as well as +the special characters @samp{-}, @samp{.}, @samp{_}, and @samp{~}. Any +other character will be percent-encoded, by writing out the character to +a bytevector within the given @var{encoding}, then encoding each byte as +@code{%@var{HH}}, where @var{HH} is the hexadecimal representation of +the byte. +@end deffn + +@deffn {Scheme Procedure} split-and-decode-uri-path path +Split @var{path} into its components, and decode each component, +removing empty components. + +For example, @code{"/foo/bar%20baz/"} decodes to the two-element list, +@code{("foo" "bar baz")}. +@end deffn + +@deffn {Scheme Procedure} encode-and-join-uri-path parts +URI-encode each element of @var{parts}, which should be a list of +strings, and join the parts together with @code{/} as a delimiter. + +For example, the list @code{("scrambled eggs" "biscuits&gravy")} encodes +as @code{"scrambled%20eggs/biscuits%26gravy"}. +@end deffn + +@subsubheading Subtypes of URI + +As we noted above, not all URI objects have a scheme. You might have +noted in the ``generic URI syntax'' example that the left-hand side of +that grammar definition was URI-reference, not URI. A +@dfn{URI-reference} is a generalization of a URI where the scheme is +optional. If no scheme is specified, it is taken to be relative to some +other related URI. A common use of URI references is when you want to +be vague regarding the choice of HTTP or HTTPS -- serving a web page +referring to @code{/foo.css} will use HTTPS if loaded over HTTPS, or +HTTP otherwise. + +@deffn {Scheme Procedure} build-uri-reference [#:scheme=@code{#f}]@ + [#:userinfo=@code{#f}] [#:host=@code{#f}] [#:port=@code{#f}] @ + [#:path=@code{""}] [#:query=@code{#f}] [#:fragment=@code{#f}] @ + [#:validate?=@code{#t}] +Like @code{build-uri}, but with an optional scheme. +@end deffn +@deffn {Scheme Procedure} uri-reference? obj +Return @code{#t} if @var{obj} is a URI-reference. This is the most +general URI predicate, as it includes not only full URIs that have +schemes (those that match @code{uri?}) but also URIs without schemes. +@end deffn + +It's also possible to build a @dfn{relative-ref}: a URI-reference that +explicitly lacks a scheme. + +@deffn {Scheme Procedure} build-relative-ref @ + [#:userinfo=@code{#f}] [#:host=@code{#f}] [#:port=@code{#f}] @ + [#:path=@code{""}] [#:query=@code{#f}] [#:fragment=@code{#f}] @ + [#:validate?=@code{#t}] +Like @code{build-uri}, but with no scheme. +@end deffn +@deffn {Scheme Procedure} relative-ref? obj +Return @code{#t} if @var{obj} is a ``relative-ref'': a URI-reference +that has no scheme. Every URI-reference will either match @code{uri?} +or @code{relative-ref?} (but not both). +@end deffn + +In case it's not clear from the above, the most general of these URI +types is the URI-reference, with @code{build-uri-reference} as the most +general constructor. @code{build-uri} and @code{build-relative-ref} +enforce enforce specific restrictions on the URI-reference. The most +generic URI parser is then @code{string->uri-reference}, and there is +also a parser for when you know that you want a relative-ref. + +Note that @code{uri?} will only return @code{#t} for URI objects that +have schemes; that is, it rejects relative-refs. + +@deffn {Scheme Procedure} string->uri-reference string +Parse @var{string} into a URI object, while not requiring a scheme. +Return @code{#f} if the string could not be parsed. +@end deffn + +@deffn {Scheme Procedure} string->relative-ref string +Parse @var{string} into a URI object, while asserting that no scheme is +present. Return @code{#f} if the string could not be parsed. +@end deffn + + +@node HTTP +@subsection The Hyper-Text Transfer Protocol + +The initial motivation for including web functionality in Guile, rather +than rely on an external package, was to establish a standard base on +which people can share code. To that end, we continue the focus on data +types by providing a number of low-level parsers and unparsers for +elements of the HTTP protocol. + +If you are want to skip the low-level details for now and move on to web +pages, @pxref{Web Client}, and @pxref{Web Server}. Otherwise, load the +HTTP module, and read on. + +@example +(use-modules (web http)) +@end example + +The focus of the @code{(web http)} module is to parse and unparse +standard HTTP headers, representing them to Guile as native data +structures. For example, a @code{Date:} header will be represented as a +SRFI-19 date record (@pxref{SRFI-19}), rather than as a string. + +Guile tries to follow RFCs fairly strictly---the road to perdition being +paved with compatibility hacks---though some allowances are made for +not-too-divergent texts. + +Header names are represented as lower-case symbols. + +@deffn {Scheme Procedure} string->header name +Parse @var{name} to a symbolic header name. +@end deffn + +@deffn {Scheme Procedure} header->string sym +Return the string form for the header named @var{sym}. +@end deffn + +For example: + +@example +(string->header "Content-Length") +@result{} content-length +(header->string 'content-length) +@result{} "Content-Length" + +(string->header "FOO") +@result{} foo +(header->string 'foo) +@result{} "Foo" +@end example + +Guile keeps a registry of known headers, their string names, and some +parsing and serialization procedures. If a header is unknown, its +string name is simply its symbol name in title-case. + +@deffn {Scheme Procedure} known-header? sym +Return @code{#t} if @var{sym} is a known header, with associated +parsers and serialization procedures, or @code{#f} otherwise. +@end deffn + +@deffn {Scheme Procedure} header-parser sym +Return the value parser for headers named @var{sym}. The result is a +procedure that takes one argument, a string, and returns the parsed +value. If the header isn't known to Guile, a default parser is returned +that passes through the string unchanged. +@end deffn + +@deffn {Scheme Procedure} header-validator sym +Return a predicate which returns @code{#t} if the given value is valid +for headers named @var{sym}. The default validator for unknown headers +is @code{string?}. +@end deffn + +@deffn {Scheme Procedure} header-writer sym +Return a procedure that writes values for headers named @var{sym} to a +port. The resulting procedure takes two arguments: a value and a port. +The default writer is @code{display}. +@end deffn + +For more on the set of headers that Guile knows about out of the box, +@pxref{HTTP Headers}. To add your own, use the @code{declare-header!} +procedure: + +@deffn {Scheme Procedure} declare-header! name parser validator writer @ + [#:multiple?=@code{#f}] +Declare a parser, validator, and writer for a given header. +@end deffn + +For example, let's say you are running a web server behind some sort of +proxy, and your proxy adds an @code{X-Client-Address} header, indicating +the IPv4 address of the original client. You would like for the HTTP +request record to parse out this header to a Scheme value, instead of +leaving it as a string. You could register this header with Guile's +HTTP stack like this: + +@example +(declare-header! "X-Client-Address" + (lambda (str) + (inet-aton str)) + (lambda (ip) + (and (integer? ip) (exact? ip) (<= 0 ip #xffffffff))) + (lambda (ip port) + (display (inet-ntoa ip) port))) +@end example + +@deffn {Scheme Procedure} declare-opaque-header! name +A specialised version of @code{declare-header!} for the case in which +you want a header's value to be returned/written ``as-is''. +@end deffn + +@deffn {Scheme Procedure} valid-header? sym val +Return a true value if @var{val} is a valid Scheme value for the header +with name @var{sym}, or @code{#f} otherwise. +@end deffn + +Now that we have a generic interface for reading and writing headers, we +do just that. + +@deffn {Scheme Procedure} read-header port +Read one HTTP header from @var{port}. Return two values: the header +name and the parsed Scheme value. May raise an exception if the header +was known but the value was invalid. + +Returns the end-of-file object for both values if the end of the message +body was reached (i.e., a blank line). +@end deffn + +@deffn {Scheme Procedure} parse-header name val +Parse @var{val}, a string, with the parser for the header named +@var{name}. Returns the parsed value. +@end deffn + +@deffn {Scheme Procedure} write-header name val port +Write the given header name and value to @var{port}, using the writer +from @code{header-writer}. +@end deffn + +@deffn {Scheme Procedure} read-headers port +Read the headers of an HTTP message from @var{port}, returning them +as an ordered alist. +@end deffn + +@deffn {Scheme Procedure} write-headers headers port +Write the given header alist to @var{port}. Doesn't write the final +@samp{\r\n}, as the user might want to add another header. +@end deffn + +The @code{(web http)} module also has some utility procedures to read +and write request and response lines. + +@deffn {Scheme Procedure} parse-http-method str [start] [end] +Parse an HTTP method from @var{str}. The result is an upper-case symbol, +like @code{GET}. +@end deffn + +@deffn {Scheme Procedure} parse-http-version str [start] [end] +Parse an HTTP version from @var{str}, returning it as a major--minor +pair. For example, @code{HTTP/1.1} parses as the pair of integers, +@code{(1 . 1)}. +@end deffn + +@deffn {Scheme Procedure} parse-request-uri str [start] [end] +Parse a URI from an HTTP request line. Note that URIs in requests do not +have to have a scheme or host name. The result is a URI object. +@end deffn + +@deffn {Scheme Procedure} read-request-line port +Read the first line of an HTTP request from @var{port}, returning three +values: the method, the URI, and the version. +@end deffn + +@deffn {Scheme Procedure} write-request-line method uri version port +Write the first line of an HTTP request to @var{port}. +@end deffn + +@deffn {Scheme Procedure} read-response-line port +Read the first line of an HTTP response from @var{port}, returning three +values: the HTTP version, the response code, and the ``reason phrase''. +@end deffn + +@deffn {Scheme Procedure} write-response-line version code reason-phrase port +Write the first line of an HTTP response to @var{port}. +@end deffn + + +@node HTTP Headers +@subsection HTTP Headers + +In addition to defining the infrastructure to parse headers, the +@code{(web http)} module defines specific parsers and unparsers for all +headers defined in the HTTP/1.1 standard. + +For example, if you receive a header named @samp{Accept-Language} with a +value @samp{en, es;q=0.8}, Guile parses it as a quality list (defined +below): + +@example +(parse-header 'accept-language "en, es;q=0.8") +@result{} ((1000 . "en") (800 . "es")) +@end example + +The format of the value for @samp{Accept-Language} headers is defined +below, along with all other headers defined in the HTTP standard. (If +the header were unknown, the value would have been returned as a +string.) + +For brevity, the header definitions below are given in the form, +@var{Type} @code{@var{name}}, indicating that values for the header +@code{@var{name}} will be of the given @var{Type}. Since Guile +internally treats header names in lower case, in this document we give +types title-cased names. A short description of the each header's +purpose and an example follow. + +For full details on the meanings of all of these headers, see the HTTP +1.1 standard, RFC 2616. + +@subsubsection HTTP Header Types + +Here we define the types that are used below, when defining headers. + +@deftp {HTTP Header Type} Date +A SRFI-19 date. +@end deftp + +@deftp {HTTP Header Type} KVList +A list whose elements are keys or key-value pairs. Keys are parsed to +symbols. Values are strings by default. Non-string values are the +exception, and are mentioned explicitly below, as appropriate. +@end deftp + +@deftp {HTTP Header Type} SList +A list of strings. +@end deftp + +@deftp {HTTP Header Type} Quality +An exact integer between 0 and 1000. Qualities are used to express +preference, given multiple options. An option with a quality of 870, +for example, is preferred over an option with quality 500. + +(Qualities are written out over the wire as numbers between 0.0 and +1.0, but since the standard only allows three digits after the decimal, +it's equivalent to integers between 0 and 1000, so that's what Guile +uses.) +@end deftp + +@deftp {HTTP Header Type} QList +A quality list: a list of pairs, the car of which is a quality, and the +cdr a string. Used to express a list of options, along with their +qualities. +@end deftp + +@deftp {HTTP Header Type} ETag +An entity tag, represented as a pair. The car of the pair is an opaque +string, and the cdr is @code{#t} if the entity tag is a ``strong'' entity +tag, and @code{#f} otherwise. +@end deftp + +@subsubsection General Headers + +General HTTP headers may be present in any HTTP message. + +@deftypevr {HTTP Header} KVList cache-control +A key-value list of cache-control directives. See RFC 2616, for more +details. + +If present, parameters to @code{max-age}, @code{max-stale}, +@code{min-fresh}, and @code{s-maxage} are all parsed as non-negative +integers. + +If present, parameters to @code{private} and @code{no-cache} are parsed +as lists of header names, as symbols. + +@example +(parse-header 'cache-control "no-cache,no-store" +@result{} (no-cache no-store) +(parse-header 'cache-control "no-cache=\"Authorization,Date\",no-store" +@result{} ((no-cache . (authorization date)) no-store) +(parse-header 'cache-control "no-cache=\"Authorization,Date\",max-age=10" +@result{} ((no-cache . (authorization date)) (max-age . 10)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List connection +A list of header names that apply only to this HTTP connection, as +symbols. Additionally, the symbol @samp{close} may be present, to +indicate that the server should close the connection after responding to +the request. +@example +(parse-header 'connection "close") +@result{} (close) +@end example +@end deftypevr + +@deftypevr {HTTP Header} Date date +The date that a given HTTP message was originated. +@example +(parse-header 'date "Tue, 15 Nov 1994 08:12:31 GMT") +@result{} #<date ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} KVList pragma +A key-value list of implementation-specific directives. +@example +(parse-header 'pragma "no-cache, broccoli=tasty") +@result{} (no-cache (broccoli . "tasty")) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List trailer +A list of header names which will appear after the message body, instead +of with the message headers. +@example +(parse-header 'trailer "ETag") +@result{} (etag) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List transfer-encoding +A list of transfer codings, expressed as key-value lists. The only +transfer coding defined by the specification is @code{chunked}. +@example +(parse-header 'transfer-encoding "chunked") +@result{} ((chunked)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List upgrade +A list of strings, indicating additional protocols that a server could use +in response to a request. +@example +(parse-header 'upgrade "WebSocket") +@result{} ("WebSocket") +@end example +@end deftypevr + +FIXME: parse out more fully? +@deftypevr {HTTP Header} List via +A list of strings, indicating the protocol versions and hosts of +intermediate servers and proxies. There may be multiple @code{via} +headers in one message. +@example +(parse-header 'via "1.0 venus, 1.1 mars") +@result{} ("1.0 venus" "1.1 mars") +@end example +@end deftypevr + +@deftypevr {HTTP Header} List warning +A list of warnings given by a server or intermediate proxy. Each +warning is a itself a list of four elements: a code, as an exact integer +between 0 and 1000, a host as a string, the warning text as a string, +and either @code{#f} or a SRFI-19 date. + +There may be multiple @code{warning} headers in one message. +@example +(parse-header 'warning "123 foo \"core breach imminent\"") +@result{} ((123 "foo" "core-breach imminent" #f)) +@end example +@end deftypevr + + +@subsubsection Entity Headers + +Entity headers may be present in any HTTP message, and refer to the +resource referenced in the HTTP request or response. + +@deftypevr {HTTP Header} List allow +A list of allowed methods on a given resource, as symbols. +@example +(parse-header 'allow "GET, HEAD") +@result{} (GET HEAD) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List content-encoding +A list of content codings, as symbols. +@example +(parse-header 'content-encoding "gzip") +@result{} (gzip) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List content-language +The languages that a resource is in, as strings. +@example +(parse-header 'content-language "en") +@result{} ("en") +@end example +@end deftypevr + +@deftypevr {HTTP Header} UInt content-length +The number of bytes in a resource, as an exact, non-negative integer. +@example +(parse-header 'content-length "300") +@result{} 300 +@end example +@end deftypevr + +@deftypevr {HTTP Header} URI content-location +The canonical URI for a resource, in the case that it is also accessible +from a different URI. +@example +(parse-header 'content-location "http://example.com/foo") +@result{} #<<uri> ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} String content-md5 +The MD5 digest of a resource. +@example +(parse-header 'content-md5 "ffaea1a79810785575e29e2bd45e2fa5") +@result{} "ffaea1a79810785575e29e2bd45e2fa5" +@end example +@end deftypevr + +@deftypevr {HTTP Header} List content-range +A range specification, as a list of three elements: the symbol +@code{bytes}, either the symbol @code{*} or a pair of integers, +indicating the byte rage, and either @code{*} or an integer, for the +instance length. Used to indicate that a response only includes part of +a resource. +@example +(parse-header 'content-range "bytes 10-20/*") +@result{} (bytes (10 . 20) *) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List content-type +The MIME type of a resource, as a symbol, along with any parameters. +@example +(parse-header 'content-type "text/plain") +@result{} (text/plain) +(parse-header 'content-type "text/plain;charset=utf-8") +@result{} (text/plain (charset . "utf-8")) +@end example +Note that the @code{charset} parameter is something is a misnomer, and +the HTTP specification admits this. It specifies the @emph{encoding} of +the characters, not the character set. +@end deftypevr + +@deftypevr {HTTP Header} Date expires +The date/time after which the resource given in a response is considered +stale. +@example +(parse-header 'expires "Tue, 15 Nov 1994 08:12:31 GMT") +@result{} #<date ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} Date last-modified +The date/time on which the resource given in a response was last +modified. +@example +(parse-header 'expires "Tue, 15 Nov 1994 08:12:31 GMT") +@result{} #<date ...> +@end example +@end deftypevr + + +@subsubsection Request Headers + +Request headers may only appear in an HTTP request, not in a response. + +@deftypevr {HTTP Header} List accept +A list of preferred media types for a response. Each element of the +list is itself a list, in the same format as @code{content-type}. +@example +(parse-header 'accept "text/html,text/plain;charset=utf-8") +@result{} ((text/html) (text/plain (charset . "utf-8"))) +@end example +Preference is expressed with quality values: +@example +(parse-header 'accept "text/html;q=0.8,text/plain;q=0.6") +@result{} ((text/html (q . 800)) (text/plain (q . 600))) +@end example +@end deftypevr + +@deftypevr {HTTP Header} QList accept-charset +A quality list of acceptable charsets. Note again that what HTTP calls +a ``charset'' is what Guile calls a ``character encoding''. +@example +(parse-header 'accept-charset "iso-8859-5, unicode-1-1;q=0.8") +@result{} ((1000 . "iso-8859-5") (800 . "unicode-1-1")) +@end example +@end deftypevr + +@deftypevr {HTTP Header} QList accept-encoding +A quality list of acceptable content codings. +@example +(parse-header 'accept-encoding "gzip,identity=0.8") +@result{} ((1000 . "gzip") (800 . "identity")) +@end example +@end deftypevr + +@deftypevr {HTTP Header} QList accept-language +A quality list of acceptable languages. +@example +(parse-header 'accept-language "cn,en=0.75") +@result{} ((1000 . "cn") (750 . "en")) +@end example +@end deftypevr + +@deftypevr {HTTP Header} Pair authorization +Authorization credentials. The car of the pair indicates the +authentication scheme, like @code{basic}. For basic authentication, the +cdr of the pair will be the base64-encoded @samp{@var{user}:@var{pass}} +string. For other authentication schemes, like @code{digest}, the cdr +will be a key-value list of credentials. +@example +(parse-header 'authorization "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" +@result{} (basic . "QWxhZGRpbjpvcGVuIHNlc2FtZQ==") +@end example +@end deftypevr + +@deftypevr {HTTP Header} List expect +A list of expectations that a client has of a server. The expectations +are key-value lists. +@example +(parse-header 'expect "100-continue") +@result{} ((100-continue)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} String from +The email address of a user making an HTTP request. +@example +(parse-header 'from "bob@@example.com") +@result{} "bob@@example.com" +@end example +@end deftypevr + +@deftypevr {HTTP Header} Pair host +The host for the resource being requested, as a hostname-port pair. If +no port is given, the port is @code{#f}. +@example +(parse-header 'host "gnu.org:80") +@result{} ("gnu.org" . 80) +(parse-header 'host "gnu.org") +@result{} ("gnu.org" . #f) +@end example +@end deftypevr + +@deftypevr {HTTP Header} *|List if-match +A set of etags, indicating that the request should proceed if and only +if the etag of the resource is in that set. Either the symbol @code{*}, +indicating any etag, or a list of entity tags. +@example +(parse-header 'if-match "*") +@result{} * +(parse-header 'if-match "asdfadf") +@result{} (("asdfadf" . #t)) +(parse-header 'if-match W/"asdfadf") +@result{} (("asdfadf" . #f)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} Date if-modified-since +Indicates that a response should proceed if and only if the resource has +been modified since the given date. +@example +(parse-header 'if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT") +@result{} #<date ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} *|List if-none-match +A set of etags, indicating that the request should proceed if and only +if the etag of the resource is not in the set. Either the symbol +@code{*}, indicating any etag, or a list of entity tags. +@example +(parse-header 'if-none-match "*") +@result{} * +@end example +@end deftypevr + +@deftypevr {HTTP Header} ETag|Date if-range +Indicates that the range request should proceed if and only if the +resource matches a modification date or an etag. Either an entity tag, +or a SRFI-19 date. +@example +(parse-header 'if-range "\"original-etag\"") +@result{} ("original-etag" . #t) +@end example +@end deftypevr + +@deftypevr {HTTP Header} Date if-unmodified-since +Indicates that a response should proceed if and only if the resource has +not been modified since the given date. +@example +(parse-header 'if-not-modified-since "Tue, 15 Nov 1994 08:12:31 GMT") +@result{} #<date ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} UInt max-forwards +The maximum number of proxy or gateway hops that a request should be +subject to. +@example +(parse-header 'max-forwards "10") +@result{} 10 +@end example +@end deftypevr + +@deftypevr {HTTP Header} Pair proxy-authorization +Authorization credentials for a proxy connection. See the documentation +for @code{authorization} above for more information on the format. +@example +(parse-header 'proxy-authorization "Digest foo=bar,baz=qux" +@result{} (digest (foo . "bar") (baz . "qux")) +@end example +@end deftypevr + +@deftypevr {HTTP Header} Pair range +A range request, indicating that the client wants only part of a +resource. The car of the pair is the symbol @code{bytes}, and the cdr +is a list of pairs. Each element of the cdr indicates a range; the car +is the first byte position and the cdr is the last byte position, as +integers, or @code{#f} if not given. +@example +(parse-header 'range "bytes=10-30,50-") +@result{} (bytes (10 . 30) (50 . #f)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} URI referer +The URI of the resource that referred the user to this resource. The +name of the header is a misspelling, but we are stuck with it. +@example +(parse-header 'referer "http://www.gnu.org/") +@result{} #<uri ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} List te +A list of transfer codings, expressed as key-value lists. A common +transfer coding is @code{trailers}. +@example +(parse-header 'te "trailers") +@result{} ((trailers)) +@end example +@end deftypevr + +@deftypevr {HTTP Header} String user-agent +A string indicating the user agent making the request. The +specification defines a structured format for this header, but it is +widely disregarded, so Guile does not attempt to parse strictly. +@example +(parse-header 'user-agent "Mozilla/5.0") +@result{} "Mozilla/5.0" +@end example +@end deftypevr + + +@subsubsection Response Headers + +@deftypevr {HTTP Header} List accept-ranges +A list of range units that the server supports, as symbols. +@example +(parse-header 'accept-ranges "bytes") +@result{} (bytes) +@end example +@end deftypevr + +@deftypevr {HTTP Header} UInt age +The age of a cached response, in seconds. +@example +(parse-header 'age "3600") +@result{} 3600 +@end example +@end deftypevr + +@deftypevr {HTTP Header} ETag etag +The entity-tag of the resource. +@example +(parse-header 'etag "\"foo\"") +@result{} ("foo" . #t) +@end example +@end deftypevr + +@deftypevr {HTTP Header} URI-reference location +A URI reference on which a request may be completed. Used in +combination with a redirecting status code to perform client-side +redirection. +@example +(parse-header 'location "http://example.com/other") +@result{} #<uri ...> +@end example +@end deftypevr + +@deftypevr {HTTP Header} List proxy-authenticate +A list of challenges to a proxy, indicating the need for authentication. +@example +(parse-header 'proxy-authenticate "Basic realm=\"foo\"") +@result{} ((basic (realm . "foo"))) +@end example +@end deftypevr + +@deftypevr {HTTP Header} UInt|Date retry-after +Used in combination with a server-busy status code, like 503, to +indicate that a client should retry later. Either a number of seconds, +or a date. +@example +(parse-header 'retry-after "60") +@result{} 60 +@end example +@end deftypevr + +@deftypevr {HTTP Header} String server +A string identifying the server. +@example +(parse-header 'server "My first web server") +@result{} "My first web server" +@end example +@end deftypevr + +@deftypevr {HTTP Header} *|List vary +A set of request headers that were used in computing this response. +Used to indicate that server-side content negotiation was performed, for +example in response to the @code{accept-language} header. Can also be +the symbol @code{*}, indicating that all headers were considered. +@example +(parse-header 'vary "Accept-Language, Accept") +@result{} (accept-language accept) +@end example +@end deftypevr + +@deftypevr {HTTP Header} List www-authenticate +A list of challenges to a user, indicating the need for authentication. +@example +(parse-header 'www-authenticate "Basic realm=\"foo\"") +@result{} ((basic (realm . "foo"))) +@end example +@end deftypevr + +@node Transfer Codings +@subsection Transfer Codings + +HTTP 1.1 allows for various transfer codings to be applied to message +bodies. These include various types of compression, and HTTP chunked +encoding. Currently, only chunked encoding is supported by guile. + +Chunked coding is an optional coding that may be applied to message +bodies, to allow messages whose length is not known beforehand to be +returned. Such messages can be split into chunks, terminated by a final +zero length chunk. + +In order to make dealing with encodings more simple, guile provides +procedures to create ports that ``wrap'' existing ports, applying +transformations transparently under the hood. + +These procedures are in the @code{(web http)} module. + +@example +(use-modules (web http)) +@end example + +@deffn {Scheme Procedure} make-chunked-input-port port [#:keep-alive?=#f] +Returns a new port, that transparently reads and decodes chunk-encoded +data from @var{port}. If no more chunk-encoded data is available, it +returns the end-of-file object. When the port is closed, @var{port} will +also be closed, unless @var{keep-alive?} is true. +@end deffn + +@example +(use-modules (ice-9 rdelim)) + +(define s "5\r\nFirst\r\nA\r\n line\n Sec\r\n8\r\nond line\r\n0\r\n") +(define p (make-chunked-input-port (open-input-string s))) +(read-line s) +@result{} "First line" +(read-line s) +@result{} "Second line" +@end example + +@deffn {Scheme Procedure} make-chunked-output-port port [#:keep-alive?=#f] +Returns a new port, which transparently encodes data as chunk-encoded +before writing it to @var{port}. Whenever a write occurs on this port, +it buffers it, until the port is flushed, at which point it writes a +chunk containing all the data written so far. When the port is closed, +the data remaining is written to @var{port}, as is the terminating zero +chunk. It also causes @var{port} to be closed, unless @var{keep-alive?} +is true. + +Note. Forcing a chunked output port when there is no data is buffered +does not write a zero chunk, as this would cause the data to be +interpreted incorrectly by the client. +@end deffn + +@example +(call-with-output-string + (lambda (out) + (define out* (make-chunked-output-port out #:keep-alive? #t)) + (display "first chunk" out*) + (force-output out*) + (force-output out*) ; note this does not write a zero chunk + (display "second chunk" out*) + (close-port out*))) +@result{} "b\r\nfirst chunk\r\nc\r\nsecond chunk\r\n0\r\n" +@end example + +@node Requests +@subsection HTTP Requests + +@example +(use-modules (web request)) +@end example + +The request module contains a data type for HTTP requests. + +@subsubsection An Important Note on Character Sets + +HTTP requests consist of two parts: the request proper, consisting of a +request line and a set of headers, and (optionally) a body. The body +might have a binary content-type, and even in the textual case its +length is specified in bytes, not characters. + +Therefore, HTTP is a fundamentally binary protocol. However the request +line and headers are specified to be in a subset of ASCII, so they can +be treated as text, provided that the port's encoding is set to an +ASCII-compatible one-byte-per-character encoding. ISO-8859-1 (latin-1) +is just such an encoding, and happens to be very efficient for Guile. + +So what Guile does when reading requests from the wire, or writing them +out, is to set the port's encoding to latin-1, and treating the request +headers as text. + +The request body is another issue. For binary data, the data is +probably in a bytevector, so we use the R6RS binary output procedures to +write out the binary payload. Textual data usually has to be written +out to some character encoding, usually UTF-8, and then the resulting +bytevector is written out to the port. + +In summary, Guile reads and writes HTTP over latin-1 sockets, without +any loss of generality. + +@subsubsection Request API + +@deffn {Scheme Procedure} request? obj +@deffnx {Scheme Procedure} request-method request +@deffnx {Scheme Procedure} request-uri request +@deffnx {Scheme Procedure} request-version request +@deffnx {Scheme Procedure} request-headers request +@deffnx {Scheme Procedure} request-meta request +@deffnx {Scheme Procedure} request-port request +A predicate and field accessors for the request type. The fields are as +follows: +@table @code +@item method +The HTTP method, for example, @code{GET}. +@item uri +The URI as a URI record. +@item version +The HTTP version pair, like @code{(1 . 1)}. +@item headers +The request headers, as an alist of parsed values. +@item meta +An arbitrary alist of other data, for example information returned in +the @code{sockaddr} from @code{accept} (@pxref{Network Sockets and +Communication}). +@item port +The port on which to read or write a request body, if any. +@end table +@end deffn + +@deffn {Scheme Procedure} read-request port [meta='()] +Read an HTTP request from @var{port}, optionally attaching the given +metadata, @var{meta}. + +As a side effect, sets the encoding on @var{port} to ISO-8859-1 +(latin-1), so that reading one character reads one byte. See the +discussion of character sets above, for more information. + +Note that the body is not part of the request. Once you have read a +request, you may read the body separately, and likewise for writing +requests. +@end deffn + +@deffn {Scheme Procedure} build-request uri [#:method='GET] @ + [#:version='(1 . 1)] [#:headers='()] [#:port=#f] [#:meta='()] @ + [#:validate-headers?=#t] +Construct an HTTP request object. If @var{validate-headers?} is true, +the headers are each run through their respective validators. +@end deffn + +@deffn {Scheme Procedure} write-request r port +Write the given HTTP request to @var{port}. + +Return a new request, whose @code{request-port} will continue writing +on @var{port}, perhaps using some transfer encoding. +@end deffn + +@deffn {Scheme Procedure} read-request-body r +Reads the request body from @var{r}, as a bytevector. Return @code{#f} +if there was no request body. +@end deffn + +@deffn {Scheme Procedure} write-request-body r bv +Write @var{bv}, a bytevector, to the port corresponding to the HTTP +request @var{r}. +@end deffn + +The various headers that are typically associated with HTTP requests may +be accessed with these dedicated accessors. @xref{HTTP Headers}, for +more information on the format of parsed headers. + +@deffn {Scheme Procedure} request-accept request [default='()] +@deffnx {Scheme Procedure} request-accept-charset request [default='()] +@deffnx {Scheme Procedure} request-accept-encoding request [default='()] +@deffnx {Scheme Procedure} request-accept-language request [default='()] +@deffnx {Scheme Procedure} request-allow request [default='()] +@deffnx {Scheme Procedure} request-authorization request [default=#f] +@deffnx {Scheme Procedure} request-cache-control request [default='()] +@deffnx {Scheme Procedure} request-connection request [default='()] +@deffnx {Scheme Procedure} request-content-encoding request [default='()] +@deffnx {Scheme Procedure} request-content-language request [default='()] +@deffnx {Scheme Procedure} request-content-length request [default=#f] +@deffnx {Scheme Procedure} request-content-location request [default=#f] +@deffnx {Scheme Procedure} request-content-md5 request [default=#f] +@deffnx {Scheme Procedure} request-content-range request [default=#f] +@deffnx {Scheme Procedure} request-content-type request [default=#f] +@deffnx {Scheme Procedure} request-date request [default=#f] +@deffnx {Scheme Procedure} request-expect request [default='()] +@deffnx {Scheme Procedure} request-expires request [default=#f] +@deffnx {Scheme Procedure} request-from request [default=#f] +@deffnx {Scheme Procedure} request-host request [default=#f] +@deffnx {Scheme Procedure} request-if-match request [default=#f] +@deffnx {Scheme Procedure} request-if-modified-since request [default=#f] +@deffnx {Scheme Procedure} request-if-none-match request [default=#f] +@deffnx {Scheme Procedure} request-if-range request [default=#f] +@deffnx {Scheme Procedure} request-if-unmodified-since request [default=#f] +@deffnx {Scheme Procedure} request-last-modified request [default=#f] +@deffnx {Scheme Procedure} request-max-forwards request [default=#f] +@deffnx {Scheme Procedure} request-pragma request [default='()] +@deffnx {Scheme Procedure} request-proxy-authorization request [default=#f] +@deffnx {Scheme Procedure} request-range request [default=#f] +@deffnx {Scheme Procedure} request-referer request [default=#f] +@deffnx {Scheme Procedure} request-te request [default=#f] +@deffnx {Scheme Procedure} request-trailer request [default='()] +@deffnx {Scheme Procedure} request-transfer-encoding request [default='()] +@deffnx {Scheme Procedure} request-upgrade request [default='()] +@deffnx {Scheme Procedure} request-user-agent request [default=#f] +@deffnx {Scheme Procedure} request-via request [default='()] +@deffnx {Scheme Procedure} request-warning request [default='()] +Return the given request header, or @var{default} if none was present. +@end deffn + +@deffn {Scheme Procedure} request-absolute-uri r [default-host=#f] @ + [default-port=#f] [default-scheme=#f] +A helper routine to determine the absolute URI of a request, using the +@code{host} header and the default scheme, host and port. If there is +no default scheme and the URI is not itself absolute, an error is +signalled. +@end deffn + +@node Responses +@subsection HTTP Responses + +@example +(use-modules (web response)) +@end example + +As with requests (@pxref{Requests}), Guile offers a data type for HTTP +responses. Again, the body is represented separately from the request. + +@deffn {Scheme Procedure} response? obj +@deffnx {Scheme Procedure} response-version response +@deffnx {Scheme Procedure} response-code response +@deffnx {Scheme Procedure} response-reason-phrase response +@deffnx {Scheme Procedure} response-headers response +@deffnx {Scheme Procedure} response-port response +A predicate and field accessors for the response type. The fields are as +follows: +@table @code +@item version +The HTTP version pair, like @code{(1 . 1)}. +@item code +The HTTP response code, like @code{200}. +@item reason-phrase +The reason phrase, or the standard reason phrase for the response's +code. +@item headers +The response headers, as an alist of parsed values. +@item port +The port on which to read or write a response body, if any. +@end table +@end deffn + +@deffn {Scheme Procedure} read-response port +Read an HTTP response from @var{port}. + +As a side effect, sets the encoding on @var{port} to ISO-8859-1 +(latin-1), so that reading one character reads one byte. See the +discussion of character sets in @ref{Responses}, for more information. +@end deffn + +@deffn {Scheme Procedure} build-response [#:version='(1 . 1)] [#:code=200] [#:reason-phrase=#f] [#:headers='()] [#:port=#f] [#:validate-headers?=#t] +Construct an HTTP response object. If @var{validate-headers?} is true, +the headers are each run through their respective validators. +@end deffn + +@deffn {Scheme Procedure} adapt-response-version response version +Adapt the given response to a different HTTP version. Return a new HTTP +response. + +The idea is that many applications might just build a response for the +default HTTP version, and this method could handle a number of +programmatic transformations to respond to older HTTP versions (0.9 and +1.0). But currently this function is a bit heavy-handed, just updating +the version field. +@end deffn + +@deffn {Scheme Procedure} write-response r port +Write the given HTTP response to @var{port}. + +Return a new response, whose @code{response-port} will continue writing +on @var{port}, perhaps using some transfer encoding. +@end deffn + +@deffn {Scheme Procedure} response-must-not-include-body? r +Some responses, like those with status code 304, are specified as never +having bodies. This predicate returns @code{#t} for those responses. + +Note also, though, that responses to @code{HEAD} requests must also not +have a body. +@end deffn + +@deffn {Scheme Procedure} response-body-port r [#:decode?=#t] [#:keep-alive?=#t] +Return an input port from which the body of @var{r} can be read. The encoding +of the returned port is set according to @var{r}'s @code{content-type} header, +when it's textual, except if @var{decode?} is @code{#f}. Return @code{#f} +when no body is available. + +When @var{keep-alive?} is @code{#f}, closing the returned port also closes +@var{r}'s response port. +@end deffn + +@deffn {Scheme Procedure} read-response-body r +Read the response body from @var{r}, as a bytevector. Returns @code{#f} +if there was no response body. +@end deffn + +@deffn {Scheme Procedure} write-response-body r bv +Write @var{bv}, a bytevector, to the port corresponding to the HTTP +response @var{r}. +@end deffn + +As with requests, the various headers that are typically associated with +HTTP responses may be accessed with these dedicated accessors. +@xref{HTTP Headers}, for more information on the format of parsed +headers. + +@deffn {Scheme Procedure} response-accept-ranges response [default=#f] +@deffnx {Scheme Procedure} response-age response [default='()] +@deffnx {Scheme Procedure} response-allow response [default='()] +@deffnx {Scheme Procedure} response-cache-control response [default='()] +@deffnx {Scheme Procedure} response-connection response [default='()] +@deffnx {Scheme Procedure} response-content-encoding response [default='()] +@deffnx {Scheme Procedure} response-content-language response [default='()] +@deffnx {Scheme Procedure} response-content-length response [default=#f] +@deffnx {Scheme Procedure} response-content-location response [default=#f] +@deffnx {Scheme Procedure} response-content-md5 response [default=#f] +@deffnx {Scheme Procedure} response-content-range response [default=#f] +@deffnx {Scheme Procedure} response-content-type response [default=#f] +@deffnx {Scheme Procedure} response-date response [default=#f] +@deffnx {Scheme Procedure} response-etag response [default=#f] +@deffnx {Scheme Procedure} response-expires response [default=#f] +@deffnx {Scheme Procedure} response-last-modified response [default=#f] +@deffnx {Scheme Procedure} response-location response [default=#f] +@deffnx {Scheme Procedure} response-pragma response [default='()] +@deffnx {Scheme Procedure} response-proxy-authenticate response [default=#f] +@deffnx {Scheme Procedure} response-retry-after response [default=#f] +@deffnx {Scheme Procedure} response-server response [default=#f] +@deffnx {Scheme Procedure} response-trailer response [default='()] +@deffnx {Scheme Procedure} response-transfer-encoding response [default='()] +@deffnx {Scheme Procedure} response-upgrade response [default='()] +@deffnx {Scheme Procedure} response-vary response [default='()] +@deffnx {Scheme Procedure} response-via response [default='()] +@deffnx {Scheme Procedure} response-warning response [default='()] +@deffnx {Scheme Procedure} response-www-authenticate response [default=#f] +Return the given response header, or @var{default} if none was present. +@end deffn + +@deffn {Scheme Procedure} text-content-type? @var{type} +Return @code{#t} if @var{type}, a symbol as returned by +@code{response-content-type}, represents a textual type such as +@code{text/plain}. +@end deffn + + +@node Web Client +@subsection Web Client + +@code{(web client)} provides a simple, synchronous HTTP client, built on +the lower-level HTTP, request, and response modules. + +@example +(use-modules (web client)) +@end example + +@deffn {Scheme Procedure} open-socket-for-uri uri +Return an open input/output port for a connection to URI. Guile +dynamically loads GnuTLS for HTTPS support. +@xref{Guile Preparations, +how to install the GnuTLS bindings for Guile,, gnutls-guile, +GnuTLS-Guile}, for more information. +@end deffn + +@anchor{http-request}@deffn {Scheme Procedure} http-request @var{uri} @var{arg}@dots{} + +Connect to the server corresponding to @var{uri} and make a request over +HTTP, using @var{method} (@code{GET}, @code{HEAD}, @code{POST}, etc.). + +The following keyword arguments allow you to modify the requests in +various ways, for example attaching a body to the request, or setting +specific headers. The following table lists the keyword arguments and +their default values. + +@table @code +@item #:method 'GET +@item #:body #f +@item #:port (open-socket-for-uri @var{uri})] +@item #:version '(1 . 1) +@item #:keep-alive? #f +@item #:headers '() +@item #:decode-body? #t +@item #:streaming? #f +@end table + +If you already have a port open, pass it as @var{port}. Otherwise, a +connection will be opened to the server corresponding to @var{uri}. Any +extra headers in the alist @var{headers} will be added to the request. + +If @var{body} is not @code{#f}, a message body will also be sent with +the HTTP request. If @var{body} is a string, it is encoded according to +the content-type in @var{headers}, defaulting to UTF-8. Otherwise +@var{body} should be a bytevector, or @code{#f} for no body. Although a +message body may be sent with any request, usually only @code{POST} and +@code{PUT} requests have bodies. + +If @var{decode-body?} is true, as is the default, the body of the +response will be decoded to string, if it is a textual content-type. +Otherwise it will be returned as a bytevector. + +However, if @var{streaming?} is true, instead of eagerly reading the +response body from the server, this function only reads off the headers. +The response body will be returned as a port on which the data may be +read. + +Unless @var{keep-alive?} is true, the port will be closed after the full +response body has been read. + +Returns two values: the response read from the server, and the response +body as a string, bytevector, #f value, or as a port (if +@var{streaming?} is true). +@end deffn + +@deffn {Scheme Procedure} http-get @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-head @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-post @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-put @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-delete @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-trace @var{uri} @var{arg}@dots{} +@deffnx {Scheme Procedure} http-options @var{uri} @var{arg}@dots{} +Connect to the server corresponding to @var{uri} and make a request over +HTTP, using the appropriate method (@code{GET}, @code{HEAD}, +@code{POST}, etc.). + +These procedures are variants of @code{http-request} specialized with a +specific @var{method} argument, and have the same prototype: a URI +followed by an optional sequence of keyword arguments. +@xref{http-request}, for full documentation on the various keyword +arguments. + +@end deffn + +@code{http-get} is useful for making one-off requests to web sites. If +you are writing a web spider or some other client that needs to handle a +number of requests in parallel, it's better to build an event-driven URL +fetcher, similar in structure to the web server (@pxref{Web Server}). + +Another option, good but not as performant, would be to use threads, +possibly via par-map or futures. + +@deffn {Scheme Parameter} current-http-proxy +Either @code{#f} or a non-empty string containing the URL of the HTTP +proxy server to be used by the procedures in the @code{(web client)} +module, including @code{open-socket-for-uri}. Its initial value is +based on the @env{http_proxy} environment variable. + +@example +(current-http-proxy) @result{} "http://localhost:8123/" +(parameterize ((current-http-proxy #f)) + (http-get "http://example.com/")) ; temporarily bypass proxy +(current-http-proxy) @result{} "http://localhost:8123/" +@end example +@end deffn + + +@node Web Server +@subsection Web Server + +@code{(web server)} is a generic web server interface, along with a main +loop implementation for web servers controlled by Guile. + +@example +(use-modules (web server)) +@end example + +The lowest layer is the @code{<server-impl>} object, which defines a set +of hooks to open a server, read a request from a client, write a +response to a client, and close a server. These hooks -- @code{open}, +@code{read}, @code{write}, and @code{close}, respectively -- are bound +together in a @code{<server-impl>} object. Procedures in this module take a +@code{<server-impl>} object, if needed. + +A @code{<server-impl>} may also be looked up by name. If you pass the +@code{http} symbol to @code{run-server}, Guile looks for a variable +named @code{http} in the @code{(web server http)} module, which should +be bound to a @code{<server-impl>} object. Such a binding is made by +instantiation of the @code{define-server-impl} syntax. In this way the +run-server loop can automatically load other backends if available. + +The life cycle of a server goes as follows: + +@enumerate +@item +The @code{open} hook is called, to open the server. @code{open} takes +zero or more arguments, depending on the backend, and returns an opaque +server socket object, or signals an error. + +@item +The @code{read} hook is called, to read a request from a new client. +The @code{read} hook takes one argument, the server socket. It should +return three values: an opaque client socket, the request, and the +request body. The request should be a @code{<request>} object, from +@code{(web request)}. The body should be a string or a bytevector, or +@code{#f} if there is no body. + +If the read failed, the @code{read} hook may return #f for the client +socket, request, and body. + +@item +A user-provided handler procedure is called, with the request and body +as its arguments. The handler should return two values: the response, +as a @code{<response>} record from @code{(web response)}, and the +response body as bytevector, or @code{#f} if not present. + +The respose and response body are run through @code{sanitize-response}, +documented below. This allows the handler writer to take some +convenient shortcuts: for example, instead of a @code{<response>}, the +handler can simply return an alist of headers, in which case a default +response object is constructed with those headers. Instead of a +bytevector for the body, the handler can return a string, which will be +serialized into an appropriate encoding; or it can return a procedure, +which will be called on a port to write out the data. See the +@code{sanitize-response} documentation, for more. + +@item +The @code{write} hook is called with three arguments: the client +socket, the response, and the body. The @code{write} hook returns no +values. + +@item +At this point the request handling is complete. For a loop, we +loop back and try to read a new request. + +@item +If the user interrupts the loop, the @code{close} hook is called on +the server socket. +@end enumerate + +A user may define a server implementation with the following form: + +@deffn {Scheme Syntax} define-server-impl name open read write close +Make a @code{<server-impl>} object with the hooks @var{open}, +@var{read}, @var{write}, and @var{close}, and bind it to the symbol +@var{name} in the current module. +@end deffn + +@deffn {Scheme Procedure} lookup-server-impl impl +Look up a server implementation. If @var{impl} is a server +implementation already, it is returned directly. If it is a symbol, the +binding named @var{impl} in the @code{(web server @var{impl})} module is +looked up. Otherwise an error is signaled. + +Currently a server implementation is a somewhat opaque type, useful only +for passing to other procedures in this module, like @code{read-client}. +@end deffn + +The @code{(web server)} module defines a number of routines that use +@code{<server-impl>} objects to implement parts of a web server. Given +that we don't expose the accessors for the various fields of a +@code{<server-impl>}, indeed these routines are the only procedures with +any access to the impl objects. + +@deffn {Scheme Procedure} open-server impl open-params +Open a server for the given implementation. Return one value, the new +server object. The implementation's @code{open} procedure is applied to +@var{open-params}, which should be a list. +@end deffn + +@deffn {Scheme Procedure} read-client impl server +Read a new client from @var{server}, by applying the implementation's +@code{read} procedure to the server. If successful, return three +values: an object corresponding to the client, a request object, and the +request body. If any exception occurs, return @code{#f} for all three +values. +@end deffn + +@deffn {Scheme Procedure} handle-request handler request body state +Handle a given request, returning the response and body. + +The response and response body are produced by calling the given +@var{handler} with @var{request} and @var{body} as arguments. + +The elements of @var{state} are also passed to @var{handler} as +arguments, and may be returned as additional values. The new +@var{state}, collected from the @var{handler}'s return values, is then +returned as a list. The idea is that a server loop receives a handler +from the user, along with whatever state values the user is interested +in, allowing the user's handler to explicitly manage its state. +@end deffn + +@deffn {Scheme Procedure} sanitize-response request response body +``Sanitize'' the given response and body, making them appropriate for +the given request. + +As a convenience to web handler authors, @var{response} may be given as +an alist of headers, in which case it is used to construct a default +response. Ensures that the response version corresponds to the request +version. If @var{body} is a string, encodes the string to a bytevector, +in an encoding appropriate for @var{response}. Adds a +@code{content-length} and @code{content-type} header, as necessary. + +If @var{body} is a procedure, it is called with a port as an argument, +and the output collected as a bytevector. In the future we might try to +instead use a compressing, chunk-encoded port, and call this procedure +later, in the write-client procedure. Authors are advised not to rely on +the procedure being called at any particular time. +@end deffn + +@deffn {Scheme Procedure} write-client impl server client response body +Write an HTTP response and body to @var{client}. If the server and +client support persistent connections, it is the implementation's +responsibility to keep track of the client thereafter, presumably by +attaching it to the @var{server} argument somehow. +@end deffn + +@deffn {Scheme Procedure} close-server impl server +Release resources allocated by a previous invocation of +@code{open-server}. +@end deffn + +Given the procedures above, it is a small matter to make a web server: + +@deffn {Scheme Procedure} serve-one-client handler impl server state +Read one request from @var{server}, call @var{handler} on the request +and body, and write the response to the client. Return the new state +produced by the handler procedure. +@end deffn + +@deffn {Scheme Procedure} run-server handler @ + [impl='http] [open-params='()] @ + arg @dots{} +Run Guile's built-in web server. + +@var{handler} should be a procedure that takes two or more arguments, +the HTTP request and request body, and returns two or more values, the +response and response body. + +For examples, skip ahead to the next section, @ref{Web Examples}. + +The response and body will be run through @code{sanitize-response} +before sending back to the client. + +Additional arguments to @var{handler} are taken from @var{arg} +@enddots{}. These arguments comprise a @dfn{state}. Additional return +values are accumulated into a new state, which will be used for +subsequent requests. In this way a handler can explicitly manage its +state. +@end deffn + +The default web server implementation is @code{http}, which binds to a +socket, listening for request on that port. + +@deffn {HTTP Implementation} http [#:host=#f] @ + [#:family=AF_INET] @ + [#:addr=INADDR_LOOPBACK] @ + [#:port 8080] [#:socket] +The default HTTP implementation. We document it as a function with +keyword arguments, because that is precisely the way that it is -- all +of the @var{open-params} to @code{run-server} get passed to the +implementation's open function. + +@example +;; The defaults: localhost:8080 +(run-server handler) +;; Same thing +(run-server handler 'http '()) +;; On a different port +(run-server handler 'http '(#:port 8081)) +;; IPv6 +(run-server handler 'http '(#:family AF_INET6 #:port 8081)) +;; Custom socket +(run-server handler 'http `(#:socket ,(sudo-make-me-a-socket))) +@end example +@end deffn + +@node Web Examples +@subsection Web Examples + +Well, enough about the tedious internals. Let's make a web application! + +@subsubsection Hello, World! + +The first program we have to write, of course, is ``Hello, World!''. +This means that we have to implement a web handler that does what we +want. + +Now we define a handler, a function of two arguments and two return +values: + +@example +(define (handler request request-body) + (values @var{response} @var{response-body})) +@end example + +In this first example, we take advantage of a short-cut, returning an +alist of headers instead of a proper response object. The response body +is our payload: + +@example +(define (hello-world-handler request request-body) + (values '((content-type . (text/plain))) + "Hello World!")) +@end example + +Now let's test it, by running a server with this handler. Load up the +web server module if you haven't yet done so, and run a server with this +handler: + +@example +(use-modules (web server)) +(run-server hello-world-handler) +@end example + +By default, the web server listens for requests on +@code{localhost:8080}. Visit that address in your web browser to +test. If you see the string, @code{Hello World!}, sweet! + +@subsubsection Inspecting the Request + +The Hello World program above is a general greeter, responding to all +URIs. To make a more exclusive greeter, we need to inspect the request +object, and conditionally produce different results. So let's load up +the request, response, and URI modules, and do just that. + +@example +(use-modules (web server)) ; you probably did this already +(use-modules (web request) + (web response) + (web uri)) + +(define (request-path-components request) + (split-and-decode-uri-path (uri-path (request-uri request)))) + +(define (hello-hacker-handler request body) + (if (equal? (request-path-components request) + '("hacker")) + (values '((content-type . (text/plain))) + "Hello hacker!") + (not-found request))) + +(run-server hello-hacker-handler) +@end example + +Here we see that we have defined a helper to return the components of +the URI path as a list of strings, and used that to check for a request +to @code{/hacker/}. Then the success case is just as before -- visit +@code{http://localhost:8080/hacker/} in your browser to check. + +You should always match against URI path components as decoded by +@code{split-and-decode-uri-path}. The above example will work for +@code{/hacker/}, @code{//hacker///}, and @code{/h%61ck%65r}. + +But we forgot to define @code{not-found}! If you are pasting these +examples into a REPL, accessing any other URI in your web browser will +drop your Guile console into the debugger: + +@example +<unnamed port>:38:7: In procedure module-lookup: +<unnamed port>:38:7: Unbound variable: not-found + +Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. +scheme@@(guile-user) [1]> +@end example + +So let's define the function, right there in the debugger. As you +probably know, we'll want to return a 404 response. + +@example +;; Paste this in your REPL +(define (not-found request) + (values (build-response #:code 404) + (string-append "Resource not found: " + (uri->string (request-uri request))))) + +;; Now paste this to let the web server keep going: +,continue +@end example + +Now if you access @code{http://localhost/foo/}, you get this error +message. (Note that some popular web browsers won't show +server-generated 404 messages, showing their own instead, unless the 404 +message body is long enough.) + +@subsubsection Higher-Level Interfaces + +The web handler interface is a common baseline that all kinds of Guile +web applications can use. You will usually want to build something on +top of it, however, especially when producing HTML. Here is a simple +example that builds up HTML output using SXML (@pxref{SXML}). + +First, load up the modules: + +@example +(use-modules (web server) + (web request) + (web response) + (sxml simple)) +@end example + +Now we define a simple templating function that takes a list of HTML +body elements, as SXML, and puts them in our super template: + +@example +(define (templatize title body) + `(html (head (title ,title)) + (body ,@@body))) +@end example + +For example, the simplest Hello HTML can be produced like this: + +@example +(sxml->xml (templatize "Hello!" '((b "Hi!")))) +@print{} +<html><head><title>Hello!</title></head><body><b>Hi!</b></body></html> +@end example + +Much better to work with Scheme data types than to work with HTML as +strings. Now we define a little response helper: + +@example +(define* (respond #:optional body #:key + (status 200) + (title "Hello hello!") + (doctype "<!DOCTYPE html>\n") + (content-type-params '((charset . "utf-8"))) + (content-type 'text/html) + (extra-headers '()) + (sxml (and body (templatize title body)))) + (values (build-response + #:code status + #:headers `((content-type + . (,content-type ,@@content-type-params)) + ,@@extra-headers)) + (lambda (port) + (if sxml + (begin + (if doctype (display doctype port)) + (sxml->xml sxml port)))))) +@end example + +Here we see the power of keyword arguments with default initializers. By +the time the arguments are fully parsed, the @code{sxml} local variable +will hold the templated SXML, ready for sending out to the client. + +Also, instead of returning the body as a string, @code{respond} gives a +procedure, which will be called by the web server to write out the +response to the client. + +Now, a simple example using this responder, which lays out the incoming +headers in an HTML table. + +@example +(define (debug-page request body) + (respond + `((h1 "hello world!") + (table + (tr (th "header") (th "value")) + ,@@(map (lambda (pair) + `(tr (td (tt ,(with-output-to-string + (lambda () (display (car pair)))))) + (td (tt ,(with-output-to-string + (lambda () + (write (cdr pair)))))))) + (request-headers request)))))) + +(run-server debug-page) +@end example + +Now if you visit any local address in your web browser, we actually see +some HTML, finally. + +@subsubsection Conclusion + +Well, this is about as far as Guile's built-in web support goes, for +now. There are many ways to make a web application, but hopefully by +standardizing the most fundamental data types, users will be able to +choose the approach that suits them best, while also being able to +switch between implementations of the server. This is a relatively new +part of Guile, so if you have feedback, let us know, and we can take it +into account. Happy hacking on the web! + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: diff --git a/doc/release.org b/doc/release.org new file mode 100644 index 000000000..271286686 --- /dev/null +++ b/doc/release.org @@ -0,0 +1,177 @@ +#+TITLE: Release Process for GNU Guile 2.2 +#+AUTHOR: Ludovic Courtès +#+STARTUP: content +#+EMAIL: ludo@gnu.org + +This document describes the typical release process for Guile 2.2. + +* Preparing & uploading the tarball + +** M-x debbugs-gnu + +… or http://bugs.gnu.org/guile, for an idea of things to fix. + +** Update Gnulib + +The commit log's first line should be "Update Gnulib to X", where X is +the output of `git describe' in the Gnulib repo. + +This allows us to keep track of the source code we use, in case a bug or +security vulnerability gets fixed in Gnulib sometime later. + +Ideally update Gnulib several days prior to the release, so that +portability or build issues can be uncovered in time. + +** Make sure it works, portably, and with different configurations + +*** Check [[http://hydra.nixos.org/jobset/gnu/guile-2-0][Hydra]] + +This contains builds and cross-builds on different platforms, with +different `configure' switches, different CPPFLAGS, and different +versions of the compiler. + +As of this writing, there are unfixed failures. For instance Darwin's +compiler randomly crashes, preventing build completion; the FreeBSD 7.x +box experiences Guile crashes while running the test suite, which were +not fixed because not reproduced elsewhere. Even for these platforms, +make sure "things don't get worse", at least. + +*** Check [[http://autobuild.josefsson.org/guile/][Autobuild]] + +This contains build reports from other people, typically on lesser used +platforms, so it's worth checking. + +*** Use the [[http://gcc.gnu.org/wiki/CompileFarm][GCC Compile Farm]] + +Use the GCC Compile Farm to check on lesser used architectures or +operating systems. In particular, the Farm has ARM, SPARC64, PowerPC, +and MIPS GNU/Linux boxes (remember that this is not superfluous: Debian +builds on 11 architectures). It also has FreeBSD and NetBSD boxes. + +*** Use porter boxes + +If you're still in a good mood, you may also want to check on porter +boxes for other OSes. The GNU/Hurd people have [[http://www.gnu.org/software/hurd/public_hurd_boxen.html][porter boxes]], and so do +the [[http://www.opencsw.org/standards/build_farm][OpenCSW Solaris Team]] and the [[http://lists.gnu.org/archive/html/autoconf/2012-11/msg00039.html][Snakebite]] project. + +*** Post a pre-release announcement to `platform-testers@gnu.org' + +Send a link to [[http://hydra.nixos.org/job/gnu/guile-2-0/tarball/latest/download-by-type/file/source-dist][the latest tarball]]. This will allow readers to test on +possibly weird platforms and report any bugs. + +** Update `GUILE-VERSION' + +For stable releases, make sure to update the SONAME appropriately. To +that end, review the commit logs for libguile in search of any C ABI +changes (new functions added, existing functions deprecated, etc.) +Change `LIBGUILE_INTERFACE_*' accordingly. Re-read the Libtool manual +if in doubt. + +`libguile/libguile.map' should also be updated as new public symbols are +added. Ideally, new symbols should get under a new version +symbol---e.g., `GUILE_2.2.3' for symbols introduced in Guile 2.2.3. + +** Tag v2.2.x + +Create a signed Git tag, like this: + + $ git tag -s -u MY-KEY -m "GNU Guile 2.2.X." v2.2.X + +The tag *must* be `v2.2.X'. For the sake of consistency, always use +"GNU Guile 2.2.X." as the tag comment. + +** Push the tag and changes + + $ git push && git push --tags + +Normally nobody committed in the meantime. ;-) + +** Run "make distcheck" + +This should trigger an `autoreconf', as `build-aux/git-version-gen' +notices the new tag. Make sure you have configured with all options +enabled (Readline, --enable-deprecated, etc.) + +After "make distcheck", double-check that `./configure --version' +reports the new version number. + +** Upload + + $ ./build-aux/gnupload --to ftp.gnu.org:guile guile-2.2.X.tar.gz + +You'll get an email soon after when the upload is complete. + +Your GPG public key must be registered for this to work (info +"(maintain) Automated Upload Registration"). + +Make sure to publish your public key on public OpenPGP servers +(keys.gnupg.net, pgp.mit.edu, etc.), so that people can actually use it +to check the authenticity and integrity of the tarball. + +** Download + +Make sure the file was uploaded and is available for download as +expected: + + $ mkdir t && cd t && \ + wget ftp.gnu.org/gnu/guile/guile-2.2.X.tar.gz && \ + wget ftp.gnu.org/gnu/guile/guile-2.2.X.tar.xz + $ diff guile-2.2.X.tar.gz ../guile-2.2.X.tar.gz + $ diff guile-2.2.X.tar.xz ../guile-2.2.X.tar.xz + +You're almost done! + +* Announcements + +First, re-read the GNU Maintainers Guide on this topic (info "(maintain) +Announcements"). + +** Update web pages + + - Update the version number in ‘latest-guile-version’ in the (website + utils) module of the web site. + - Add a news item by dropping a Markdown file under posts/. + - Build the web site: =haunt build=. + - Synchronize the files under site/ over the CVS repo. + +** Update the on-line copy of the manual + +Use `build-aux/gendocs', add to the manual/ directory of the web site. + + $ cd doc/ref + $ ../../build-aux/gendocs.sh guile "GNU Guile 2.2.X Reference Manual" + +** Prepare the email announcement + + $ build-aux/announce-gen --release-type=stable --package-name=guile \ + --previous-version=2.2.1 --current-version=2.2.2 \ + --gpg-key-id=MY-KEY --url-directory=ftp://ftp.gnu.org/gnu/guile \ + --bootstrap-tools=autoconf,automake,libtool,gnulib,makeinfo \ + --gnulib-version=$( cd ~/src/gnulib ; git describe ) + +The subject must be "GNU Guile 2.2.X released". The text should remain +formal and impersonal (it is sent on behalf of the Guile and GNU +projects.) It must include a description of what Guile is (not everyone +reading info-gnu may know about it.) Use the text of previous +announcements as a template. + +Below the initial boilerplate that describes Guile should come the +output of `announce-gen', and then the `NEWS' file excerpt in its +entirety (don't call it a change log since that's not what it is.) + +** Send the email announcement + +Send to these places, preferably in the morning on a working day (UTC): + + - guile-user@gnu.org, guile-devel@gnu.org, guile-sources@gnu.org + - info-gnu@gnu.org (for stable releases only!) + - comp.lang.scheme + + + + +Copyright © 2011, 2012, 2013, 2017, 2018 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 000000000..d2b264dd9 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,8962 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2007-12-02.17} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 2007, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +% 2007 Free Software Foundation, Inc. +% +% This texinfo.tex file is free software: you can redistribute it and/or +% modify it under the terms of the GNU General Public License as +% published by the Free Software Foundation, either version 3 of the +% License, or (at your option) any later version. +% +% This texinfo.tex file is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the implied warranty +% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +% General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. (This has been our intent since Texinfo was invented.) +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org). +% The texinfo.tex in any given distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. + + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + + +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexfootnote=\footnote +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexinsert=\insert +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{l.\the\inputlineno:\space} +\fi + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi + +% Since the category of space is not known, we have to be careful. +\chardef\spacecat = 10 +\def\spaceisspace{\catcode`\ =\spacecat} + +% sometimes characters are active, so we need control sequences. +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dashChar = `\- +\chardef\dotChar = `\. +\chardef\exclamChar= `\! +\chardef\lquoteChar= `\` +\chardef\questChar = `\? +\chardef\rquoteChar= `\' +\chardef\semiChar = `\; +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} + +% Hyphenation fixes. +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines16 +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Output a mark which sets \thischapter, \thissection and \thiscolor. +% We dump everything together because we only have one kind of mark. +% This works because we only use \botmark / \topmark, not \firstmark. +% +% A mark contains a subexpression of the \ifcase ... \fi construct. +% \get*marks macros below extract the needed part using \ifcase. +% +% Another complication is to let the user choose whether \thischapter +% (\thissection) refers to the chapter (section) in effect at the top +% of a page, or that at the bottom of a page. The solution is +% described on page 260 of The TeXbook. It involves outputting two +% marks for the sectioning macros, one before the section break, and +% one after. I won't pretend I can describe this better than DEK... +\def\domark{% + \toks0=\expandafter{\lastchapterdefs}% + \toks2=\expandafter{\lastsectiondefs}% + \toks4=\expandafter{\prevchapterdefs}% + \toks6=\expandafter{\prevsectiondefs}% + \toks8=\expandafter{\lastcolordefs}% + \mark{% + \the\toks0 \the\toks2 + \noexpand\or \the\toks4 \the\toks6 + \noexpand\else \the\toks8 + }% +} +% \topmark doesn't work for the very first chapter (after the title +% page or the contents), so we use \firstmark there -- this gets us +% the mark with the chapter defs, unless the user sneaks in, e.g., +% @setcolor (or @url, or @link, etc.) between @contents and the very +% first @chapter. +\def\gettopheadingmarks{% + \ifcase0\topmark\fi + \ifx\thischapter\empty \ifcase0\firstmark\fi \fi +} +\def\getbottomheadingmarks{\ifcase1\botmark\fi} +\def\getcolormarks{\ifcase2\topmark\fi} + +% Avoid "undefined control sequence" errors. +\def\lastchapterdefs{} +\def\lastsectiondefs{} +\def\prevchapterdefs{} +\def\prevsectiondefs{} +\def\lastcolordefs{} + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + % We don't want .vr (or whatever) entries like this: + % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} + % "\acronym" won't work when it's read back in; + % it needs to be + % {\code {{\tt \backslashcurfont }acronym} + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingyyy.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 24pt + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \indexdummies + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1\relax \unvbox#1\relax +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\argtorun{#2}% + \begingroup + \obeylines + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. +} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + \argremovecomment #1\comment\ArgTerm% + }% +} + +% First remove any @comment, then any @c comment. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} + +% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, e.g., +% @end itemize @c foo +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. +% +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm +} + +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \argtorun. +% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. +% +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} + +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +% +% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my +% favourite TeX trick. --kasal, 16nov03 + +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} + +% Several utility definitions with active space: +{ + \obeyspaces + \gdef\obeyedspace{ } + + % Make each space character in the input produce a normal interword + % space in the output. Don't allow a line break at this space, as this + % is used only in environments like @example, where each line of input + % should produce a line of output anyway. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % If an index command is used in an @example environment, any spaces + % therein should become regular spaces in the raw index file, not the + % expansion of \tie (\leavevmode \penalty \@M \ ). + \gdef\unsepspaces{\let =\space} +} + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +% Define the framework for environments in texinfo.tex. It's used like this: +% +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as enviroments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At runtime, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp + \else + \badenverr + \fi +} + +% Evironment mismatch, #1 expected: +\def\badenverr{% + \errhelp = \EMsimple + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + out of any environment% + \else + in environment \expandafter\string#1% + \fi +} + +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv +% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi +} + +\newhelp\EMsimple{Press RETURN to continue.} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux/toc files. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% + \kern-.15em + \TeX +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=\endofsentencespacefactor\space} + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=\endofsentencespacefactor\space} + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% + \fi\fi +} + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\envdef\group{% + \ifnum\catcode`\^^M=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + \startsavinginserts + % + \setbox\groupbox = \vtop\bgroup + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% The \vtop produces a box with normal height and large depth; thus, TeX puts +% \baselineskip glue before it, and (when the next line of text is done) +% \lineskip glue after it. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \box\groupbox + \prevdepth = \dimen1 + \checkinserts +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +% Old definition--didn't work. +%\parseargdef\need{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\parseargdef\need{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break (and is undocumented). + +\let\br = \par + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} + +% This defn is used inside nofill environments such as @example. +\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount + \leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack + \def\thisfile{#1}% + {% + \makevalueexpandable + \def\temp{\input #1 }% + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \catcode`-=\other +} + +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\parseargdef\center{% + \ifhmode + \let\next\centerH + \else + \let\next\centerV + \fi + \next{\hfil \ignorespaces#1\unskip \hfil}% +} +\def\centerH#1{% + {% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break + }% +} +\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} + +% @sp n outputs n lines of vertical space + +\parseargdef\sp{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\parseargdef\paragraphindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\parseargdef\exampleindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indent at such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. +% We switch the definition of this back and forth according to WORD. +% By default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\def\insertword{insert} +% +\parseargdef\firstparagraphindent{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \restorefirstparagraphindent + \indent + }% + \gdef\noindent{% + \restorefirstparagraphindent + \noindent + }% + \global\everypar = {% + \kern -\parindent + \restorefirstparagraphindent + }% +} + +\gdef\restorefirstparagraphindent{% + \global \let \indent = \ptexindent + \global \let \noindent = \ptexnoindent + \global \everypar = {}% +} + + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{$\ptexbullet$} +\def\minus{$-$} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in the cm +% typewriter fonts as three actual period characters; on the other hand, +% in other typewriter fonts three periods are wider than 1.5em. So do +% whichever is larger. +% +\def\dots{% + \leavevmode + \setbox0=\hbox{...}% get width of three periods + \ifdim\wd0 > 1.5em + \dimen0 = \wd0 + \else + \dimen0 = 1.5em + \fi + \hbox to \dimen0{% + \hskip 0pt plus.25fil + .\hskip 0pt plus1fil + .\hskip 0pt plus1fil + .\hskip 0pt plus.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @comma{} is so commas can be inserted into text without messing up +% Texinfo's parsing. +% +\let\comma = , + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi % \openindices needs to do some work in any case. + \openindices + \let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + \openin 1 texinfo.cnf + \ifeof 1 \else \input texinfo.cnf \fi + \closein 1 + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as \undefined, +% borrowed from ifpdf.sty. +\ifx\pdfoutput\undefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html +% (and related messages, the final outcome is that it is up to the TeX +% user to double the backslashes and otherwise make the string valid, so +% that's what we do). + +% double active backslashes. +% +{\catcode`\@=0 \catcode`\\=\active + @gdef@activebackslashdouble{% + @catcode`@\=@active + @let\=@doublebackslash} +} + +% To handle parens, we must adopt a different approach, since parens are +% not active characters. hyperref.dtx (which has the same problem as +% us) handles it with this amazing macro to replace tokens, with minor +% changes for Texinfo. It is included here under the GPL by permission +% from the author, Heiko Oberdiek. +% +% #1 is the tokens to replace. +% #2 is the replacement. +% #3 is the control sequence with the string. +% +\def\HyPsdSubst#1#2#3{% + \def\HyPsdReplace##1#1##2\END{% + ##1% + \ifx\\##2\\% + \else + #2% + \HyReturnAfterFi{% + \HyPsdReplace##2\END + }% + \fi + }% + \xdef#3{\expandafter\HyPsdReplace#3#1\END}% +} +\long\def\HyReturnAfterFi#1\fi{\fi#1} + +% #1 is a control sequence in which to do the replacements. +\def\backslashparens#1{% + \xdef#1{#1}% redefine it as its expansion; the definition is simply + % \lastnode when called from \setref -> \pdfmkdest. + \HyPsdSubst{(}{\realbackslash(}{#1}% + \HyPsdSubst{)}{\realbackslash)}{#1}% +} + +\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images +with PDF output, and none of those formats could be found. (.eps cannot +be supported due to the design of the PDF format; use regular TeX (DVI +output) for that.)} + +\ifpdf + % + % Color manipulation macros based on pdfcolor.tex. + \def\cmykDarkRed{0.28 1 1 0.35} + \def\cmykBlack{0 0 0 1} + % + \def\pdfsetcolor#1{\pdfliteral{#1 k}} + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\cmykBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\lastcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % + \pdfcatalog{/PageMode /UseOutlines} + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % pdftex (and the PDF format) support .png, .jpg, .pdf (among + % others). Let's try in that order. + \let\pdfimgext=\empty + \begingroup + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \openin 1 #1.pdf \ifeof 1 + \errhelp = \nopdfimagehelp + \errmessage{Could not find image file #1 for pdf}% + \else \gdef\pdfimgext{pdf}% + \fi + \else \gdef\pdfimgext{JPG}% + \fi + \else \gdef\pdfimgext{jpeg}% + \fi + \else \gdef\pdfimgext{jpg}% + \fi + \else \gdef\pdfimgext{png}% + \fi + \closein 1 + \endgroup + % + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifdim \wd0 >0pt width \imagewidth \fi + \ifdim \wd2 >0pt height \imageheight \fi + \ifnum\pdftexversion<13 + #1.\pdfimgext + \else + {#1.\pdfimgext}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + % + \def\pdfmkdest#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \turnoffactive + \activebackslashdouble + \makevalueexpandable + \def\pdfdestname{#1}% + \backslashparens\pdfdestname + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + }} + % + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1} + % + % by default, use a color that is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. + \def\urlcolor{\cmykDarkRed} + \def\linkcolor{\cmykDarkRed} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by 1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + % + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worth the trouble, since most documents are normally structured. + \def\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty + \def\pdfoutlinedest{#4}% + \else + % Doubled backslashes in the name. + {\activebackslashdouble \xdef\pdfoutlinedest{#3}% + \backslashparens\pdfoutlinedest}% + \fi + % + % Also double the backslashes in the display string. + {\activebackslashdouble \xdef\pdfoutlinetext{#1}% + \backslashparens\pdfoutlinetext}% + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% + } + % + \def\pdfmakeoutlines{% + \begingroup + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \def\thissubsecnum{0}% + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% + \readdatafile{toc}% + % + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. + % + % xx to do this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Right + % now, I guess we'll just let the pdf reader have its way. + \indexnofonts + \setupdatafile + \catcode`\\=\active \otherbackslash + \input \tocreadfilename + \endgroup + } + % + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + \leavevmode\setcolor{\urlcolor}% + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \setcolor{\linkcolor}#1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\else + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\setcolor = \gobble + \let\pdfsetcolor = \gobble + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput + + +\message{fonts,} + +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname ten#1\endcsname % change the current font +} + +% Select #1 fonts with the current style. +% +\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +% can get a sort of poor man's double spacing by redefining this. +\def\baselinefactor{1} +% +\def\setleading#1{% + \dimen0 = #1\relax + \normalbaselineskip = \baselinefactor\dimen0 + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% PDF CMaps. See also LaTeX's t1.cmap. +% +% do nothing with this by default. +\expandafter\let\csname cmapOT1\endcsname\gobble +\expandafter\let\csname cmapOT1IT\endcsname\gobble +\expandafter\let\csname cmapOT1TT\endcsname\gobble + +% if we are producing pdf, and we have \pdffontattr, then define cmaps. +% (\pdffontattr was introduced many years ago, but people still run +% older pdftex's; it's easy to conditionalize, so we do.) +\ifpdf \ifx\pdffontattr\undefined \else + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1-0) +%%Title: (TeX-OT1-0 TeX OT1 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1) +/Supplement 0 +>> def +/CMapName /TeX-OT1-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<23> <26> <0023> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +40 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1IT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1IT-0) +%%Title: (TeX-OT1IT-0 TeX OT1IT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1IT) +/Supplement 0 +>> def +/CMapName /TeX-OT1IT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<25> <26> <0025> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +42 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<23> <0023> +<24> <00A3> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1IT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1TT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1TT-0) +%%Title: (TeX-OT1TT-0 TeX OT1TT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1TT) +/Supplement 0 +>> def +/CMapName /TeX-OT1TT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +5 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<21> <26> <0021> +<28> <5F> <0028> +<61> <7E> <0061> +endbfrange +32 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <2191> +<0C> <2193> +<0D> <0027> +<0E> <00A1> +<0F> <00BF> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<20> <2423> +<27> <2019> +<60> <2018> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1TT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +\fi\fi + + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor, #5 is the CMap +% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass +% empty to omit). +\def\setfont#1#2#3#4#5{% + \font#1=\fontprefix#2#3 scaled #4 + \csname cmap#5\endcsname#1% +} +% This is what gets called when #5 of \setfont is empty. +\let\cmap\gobble +% emacs-page end of cmaps + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +% Definitions for a main text size of 11pt. This is the default in +% Texinfo. +% +\def\definetextfontsizexi{% +% Text fonts (11.2pt, magstep1). +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1095} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1}{OT1} +\setfont\deftt\ttshape{10}{\magstep1}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} +\def\titleecsize{2074} + +% Chapter (and unnumbered) fonts (17.28pt). +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2}{OT1} +\setfont\chapit\itbshape{10}{\magstep3}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep3}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} +\setfont\chapsf\sfbshape{17}{1000}{OT1} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3}{OT1} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 +\def\chapecsize{1728} + +% Section fonts (14.4pt). +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1}{OT1} +\setfont\secit\itbshape{10}{\magstep2}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep2}{OT1} +\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\secsf\sfbshape{12}{\magstep1}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2}{OT1} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 +\def\sececsize{1440} + +% Subsection fonts (13.15pt). +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} +\setfont\ssecit\itbshape{10}{1315}{OT1IT} +\setfont\ssecsl\slbshape{10}{1315}{OT1} +\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} +\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1315}{OT1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +\def\ssececsize{1200} + +% Reduced fonts for @acro in text (10pt). +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000}{OT1} +\setfont\reducedtt\ttshape{10}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{1000}{OT1} +\setfont\reducedit\itshape{10}{1000}{OT1IT} +\setfont\reducedsl\slshape{10}{1000}{OT1} +\setfont\reducedsf\sfshape{10}{1000}{OT1} +\setfont\reducedsc\scshape{10}{1000}{OT1} +\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 +\def\reducedecsize{1000} + +% reset the current fonts +\textfonts +\rm +} % end of 11pt text font size definitions + + +% Definitions to make the main text be 10pt Computer Modern, with +% section, chapter, etc., sizes following suit. This is for the GNU +% Press printing of the Emacs 22 manual. Maybe other manuals in the +% future. Used with @smallbook, which sets the leading to 12pt. +% +\def\definetextfontsizex{% +% Text fonts (10pt). +\def\textnominalsize{10pt} +\edef\mainmagstep{1000} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1000} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstephalf}{OT1} +\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} +\def\titleecsize{2074} + +% Chapter fonts (14.4pt). +\def\chapnominalsize{14pt} +\setfont\chaprm\rmbshape{12}{\magstep1}{OT1} +\setfont\chapit\itbshape{10}{\magstep2}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep2}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\chapsf\sfbshape{12}{\magstep1}{OT1} +\let\chapbf\chaprm +\setfont\chapsc\scbshape{10}{\magstep2}{OT1} +\font\chapi=cmmi12 scaled \magstep1 +\font\chapsy=cmsy10 scaled \magstep2 +\def\chapecsize{1440} + +% Section fonts (12pt). +\def\secnominalsize{12pt} +\setfont\secrm\rmbshape{12}{1000}{OT1} +\setfont\secit\itbshape{10}{\magstep1}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep1}{OT1} +\setfont\sectt\ttbshape{12}{1000}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} +\setfont\secsf\sfbshape{12}{1000}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep1}{OT1} +\font\seci=cmmi12 +\font\secsy=cmsy10 scaled \magstep1 +\def\sececsize{1200} + +% Subsection fonts (10pt). +\def\ssecnominalsize{10pt} +\setfont\ssecrm\rmbshape{10}{1000}{OT1} +\setfont\ssecit\itbshape{10}{1000}{OT1IT} +\setfont\ssecsl\slbshape{10}{1000}{OT1} +\setfont\ssectt\ttbshape{10}{1000}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} +\setfont\ssecsf\sfbshape{10}{1000}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1000}{OT1} +\font\sseci=cmmi10 +\font\ssecsy=cmsy10 +\def\ssececsize{1000} + +% Reduced fonts for @acro in text (9pt). +\def\reducednominalsize{9pt} +\setfont\reducedrm\rmshape{9}{1000}{OT1} +\setfont\reducedtt\ttshape{9}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{900}{OT1} +\setfont\reducedit\itshape{9}{1000}{OT1IT} +\setfont\reducedsl\slshape{9}{1000}{OT1} +\setfont\reducedsf\sfshape{9}{1000}{OT1} +\setfont\reducedsc\scshape{10}{900}{OT1} +\setfont\reducedttsl\ttslshape{10}{900}{OT1TT} +\font\reducedi=cmmi9 +\font\reducedsy=cmsy9 +\def\reducedecsize{0900} + +% reduce space between paragraphs +\divide\parskip by 2 + +% reset the current fonts +\textfonts +\rm +} % end of 10pt text font size definitions + + +% We provide the user-level command +% @fonttextsize 10 +% (or 11) to redefine the text font size. pt is assumed. +% +\def\xword{10} +\def\xiword{11} +% +\parseargdef\fonttextsize{% + \def\textsizearg{#1}% + \wlog{doing @fonttextsize \textsizearg}% + % + % Set \globaldefs so that documents can use this inside @tex, since + % makeinfo 4.8 does not support it, but we need it nonetheless. + % + \begingroup \globaldefs=1 + \ifx\textsizearg\xword \definetextfontsizex + \else \ifx\textsizearg\xiword \definetextfontsizexi + \else + \errhelp=\EMsimple + \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} + \fi\fi + \endgroup +} + + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this because \STYLE needs to also set the +% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire +% \tenSTYLE to set the current font. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used in +% the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \let\tenttsl=\textttsl + \def\curfontsize{text}% + \def\lsize{reduced}\def\lllsize{smaller}% + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \def\curfontsize{title}% + \def\lsize{chap}\def\lllsize{subsec}% + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \let\tenttsl=\chapttsl + \def\curfontsize{chap}% + \def\lsize{sec}\def\lllsize{text}% + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \let\tenttsl=\secttsl + \def\curfontsize{sec}% + \def\lsize{subsec}\def\lllsize{reduced}% + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \let\tenttsl=\ssecttsl + \def\curfontsize{ssec}% + \def\lsize{text}\def\lllsize{small}% + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts +\def\reducedfonts{% + \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl + \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc + \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy + \let\tenttsl=\reducedttsl + \def\curfontsize{reduced}% + \def\lsize{small}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \def\curfontsize{small}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \def\curfontsize{smaller}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \scriptfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish the USA used A4 paper. +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\definetextfontsizexi + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000}{OT1} +\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000}{OT1} +\setfont\shortconttt\ttshape{12}{1000}{OT1TT} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else + \ptexslash\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally uses \ttsl. +% @var is set to this for defun arguments. +\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\slanted=\smartslanted +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic + +% @b, explicit bold. +\def\b#1{{\bf #1}} +\let\strong=\b + +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\plainfrenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends + } +\catcode`@=\other +\def\endofsentencespacefactor{3000}% default + +\def\t#1{% + {\tt \rawbackslash \plainfrenchspacing #1}% + \null +} +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000}{OT1} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +\def\key #1{{\nohyphenation \uppercase{#1}}\null} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \plainfrenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in @code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active + % + \global\def\code{\begingroup + \catcode\rquoteChar=\active \catcode\lquoteChar=\active + \let'\codequoteright \let`\codequoteleft + % + \catcode\dashChar=\active \catcode\underChar=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\realdash + \let_\realunder + \fi + \codex + } +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is undesirable in +% some manuals, especially if they don't have long identifiers in +% general. @allowcodebreaks provides a way to control this. +% +\newif\ifallowcodebreaks \allowcodebreakstrue + +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse + \else + \errhelp = \EMsimple + \errmessage{Unknown @allowcodebreaks option `\txiarg'}% + \fi\fi +} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\txiarg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\txiarg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle option `\txiarg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. +\let\indicateurl=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\selectfonts\lsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\plainfrenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% +\def\pounds{{\it\$}} + +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% Hacks for glyphs from the EC fonts similar to \euro. We don't +% use \let for the aliases, because sometimes we redefine the original +% macro, and the alias should reflect the redefinition. +\def\guillemetleft{{\ecfont \char"13}} +\def\guillemotleft{\guillemetleft} +\def\guillemetright{{\ecfont \char"14}} +\def\guillemotright{\guillemetright} +\def\guilsinglleft{{\ecfont \char"0E}} +\def\guilsinglright{{\ecfont \char"0F}} +\def\quotedblbase{{\ecfont \char"12}} +\def\quotesinglbase{{\ecfont \char"0D}} +% +\def\ecfont{% + % We can't distinguish serif/sanserif and italic/slanted, but this + % is used for crude hacks anyway (like adding French and German + % quotes to documents typeset with CM, where we lose kerning), so + % hopefully nobody will notice/care. + \edef\ecsize{\csname\curfontsize ecsize\endcsname}% + \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% + \ifx\curfontstyle\bfstylename + % bold: + \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize + \else + % regular: + \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \fi + \thisecfont +} + +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + \hfil\crcr\Orb}}% + }$% +} + +% @textdegree - the normal degrees sign. +% +\def\textdegree{$^\circ$} + +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\undefined +\def\Orb{\mathhexbox20D} +\fi + +% Quotes. +\chardef\quotedblleft="5C +\chardef\quotedblright=`\" +\chardef\quoteleft=`\` +\chardef\quoteright=`\' + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \let\page = \oldpage + \page + \null + }% +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Macros to be used within @titlepage: + +\let\subtitlerm=\tenrm +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt} + +\parseargdef\title{% + \checkenv\titlepage + \leftline{\titlefonts\rm #1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\authorfont \leftline{#1}}% + \fi +} + + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make TeX use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + + +\def\evenheading{\parsearg\evenheadingxxx} +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -12pt + \global\advance\vsize by -12pt +} + +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + +% @evenheadingmarks top \thischapter <- chapter at the top of a page +% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page +% +% The same set of arguments for: +% +% @oddheadingmarks +% @evenfootingmarks +% @oddfootingmarks +% @everyheadingmarks +% @everyfootingmarks + +\def\evenheadingmarks{\headingmarks{even}{heading}} +\def\oddheadingmarks{\headingmarks{odd}{heading}} +\def\evenfootingmarks{\headingmarks{even}{footing}} +\def\oddfootingmarks{\headingmarks{odd}{footing}} +\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} + \headingmarks{odd}{heading}{#1} } +\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} + \headingmarks{odd}{footing}{#1} } +% #1 = even/odd, #2 = heading/footing, #3 = top/bottom. +\def\headingmarks#1#2#3 {% + \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname + \global\expandafter\let\csname get#1#2marks\endcsname \temp +} + +\everyheadingmarks bottom +\everyfootingmarks bottom + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{% +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg{\gdef\thistitle}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @ftable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemindicate{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted would + % cause the example and the item to crash together. So we use this + % bizarre value of 10001 as a signal to \aboveenvbreak to insert + % \parskip glue after all. Section titles are handled this way also. + % + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} + +% @table, @ftable, @vtable. +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% +} +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley +} +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\envdef\itemize{\parsearg\doitemize} + +\def\doitemize#1{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + \def\itemcontents{#1}% + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + \let\item=\itemizeitem +} + +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + \vadjust{\penalty 1200}}% not good to break after first line of item. + \flushcr +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call \doitemize, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \doitemize{#1.}\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. +% Assignments have to be global since we are inside the implicit group +% of an alignment entry. Note that \everycr resets \everytab. +\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% +% +% A \tab used to include \hskip1sp. But then the space in a template +% line is not enough. That is bad. So let's go back to just `&' until +% we encounter the problem it was intended to solve again. +% --karl, nathan@acm.org, 20apr99. +\def\tab{\checkenv\multitable &\the\everytab}% + +% @multitable ... @end multitable definitions: +% +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% + \vskip\parskip + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + % + \everycr = {% + \noalign{% + \global\everytab={}% + \global\colcount=0 % Reset the column counter. + % Check for saved footnotes, etc. + \checkinserts + % Keeps underfull box messages off when table breaks over pages. + %\filbreak + % Maybe so, but it also creates really weird page breaks when the + % table breaks over pages. Wouldn't \vfil be better? Wait until the + % problem manifests itself, so it can be fixed for real --karl. + }% + }% + % + \parsearg\domultitable +} +\def\domultitable#1{% + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively + % marking characters. + \noindent\ignorespaces##\unskip\multistrut + }\cr +} +\def\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse +} + +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +\fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{conditionals,} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} +\def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% Ignore text until a line `@end #1', keeping track of nested conditionals. +% +% A count to remember the depth of nesting. +\newcount\doignorecount + +\def\doignore#1{\begingroup + % Scan in ``verbatim'' mode: + \obeylines + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \spaceisspace + % + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. + % + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next +} + +% Finish off ignored text. +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} + + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. +% +\parseargdef\set{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% +} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} + +% @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} +{ + \catcode`\- = \active \catcode`\_ = \active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... + \catcode`\-=\other \catcode`\_=\other + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\realdash \let_\normalunderscore + } +} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we call \makevalueexpandable in \indexdummies). +% The command has to be fully expandable (if the variable is set), since +% the result winds up in the index file. This means that if the +% variable's value contains other Texinfo commands, it's almost certain +% it will fail (although perhaps we could fix that with sufficient work +% to do a one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +% To get special treatment of `@end ifset,' call \makeond and the redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next +} +\def\ifsetfail{\doignore{ifset}} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \escapechar = `\\ % use backslash in output files. + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % I don't entirely understand this, but when an index entry is + % generated from a macro call, the \endinput which \scanmacro inserts + % causes processing to be prematurely terminated. This is, + % apparently, because \indexsorttmp is fully expanded, and \endinput + % is an expandable command. The redefinition below makes \endinput + % disappear altogether for that purpose -- although logging shows that + % processing continues to some further point. On the other hand, it + % seems \endinput does not hurt in the printed index arg, since that + % is still getting written without apparent harm. + % + % Sample source (mac-idx3.tex, reported by Graham Percival to + % help-texinfo, 22may06): + % @macro funindex {WORD} + % @findex xyz + % @end macro + % ... + % @funindex commtest + % + % The above is not enough to reproduce the bug, but it gives the flavor. + % + % Sample whatsit resulting: + % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} + % + % So: + \let\endinput = \empty + % + % Do the redefinitions. + \commondummies +} + +% For the aux and toc files, @ is the escape character. So we want to +% redefine everything using @ as the escape character (instead of +% \realbackslash, still used for index files). When everything uses @, +% this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % Do the redefinitions. + \commondummies + \otherbackslash +} + +% Called from \indexdummies and \atdummies. +% +\def\commondummies{% + % + % \definedummyword defines \#1 as \string\#1\space, thus effectively + % preventing its expansion. This is used only for control% words, + % not control letters, because the \space would be incorrect for + % control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword ##1{\def##1{\string##1\space}}% + \def\definedummyletter##1{\def##1{\string##1}}% + \let\definedummyaccent\definedummyletter + % + \commondummiesnofonts + % + \definedummyletter\_% + % + % Non-English letters. + \definedummyword\AA + \definedummyword\AE + \definedummyword\L + \definedummyword\OE + \definedummyword\O + \definedummyword\aa + \definedummyword\ae + \definedummyword\l + \definedummyword\oe + \definedummyword\o + \definedummyword\ss + \definedummyword\exclamdown + \definedummyword\questiondown + \definedummyword\ordf + \definedummyword\ordm + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt + % + \definedummyword\LaTeX + \definedummyword\TeX + % + % Assorted special characters. + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\guillemetleft + \definedummyword\guillemetright + \definedummyword\guilsinglleft + \definedummyword\guilsinglright + \definedummyword\expansion + \definedummyword\minus + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\quotedblbase + \definedummyword\quotedblleft + \definedummyword\quotedblright + \definedummyword\quoteleft + \definedummyword\quoteright + \definedummyword\quotesinglbase + \definedummyword\result + \definedummyword\textdegree + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + % + \normalturnoffactive + % + % Handle some cases of @value -- where it does not contain any + % (non-fully-expandable) commands. + \makevalueexpandable +} + +% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% +\def\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter\!% + \definedummyaccent\"% + \definedummyaccent\'% + \definedummyletter\*% + \definedummyaccent\,% + \definedummyletter\.% + \definedummyletter\/% + \definedummyletter\:% + \definedummyaccent\=% + \definedummyletter\?% + \definedummyaccent\^% + \definedummyaccent\`% + \definedummyaccent\~% + \definedummyword\u + \definedummyword\v + \definedummyword\H + \definedummyword\dotaccent + \definedummyword\ringaccent + \definedummyword\tieaccent + \definedummyword\ubaraccent + \definedummyword\udotaccent + \definedummyword\dotless + % + % Texinfo font commands. + \definedummyword\b + \definedummyword\i + \definedummyword\r + \definedummyword\sc + \definedummyword\t + % + % Commands that take arguments. + \definedummyword\acronym + \definedummyword\cite + \definedummyword\code + \definedummyword\command + \definedummyword\dfn + \definedummyword\emph + \definedummyword\env + \definedummyword\file + \definedummyword\kbd + \definedummyword\key + \definedummyword\math + \definedummyword\option + \definedummyword\pxref + \definedummyword\ref + \definedummyword\samp + \definedummyword\strong + \definedummyword\tie + \definedummyword\uref + \definedummyword\url + \definedummyword\var + \definedummyword\verb + \definedummyword\w + \definedummyword\xref +} + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexnofonts{% + % Accent commands should become @asis. + \def\definedummyaccent##1{\let##1\asis}% + % We can just ignore other control letters. + \def\definedummyletter##1{\let##1\empty}% + % Hopefully, all control words can become @asis. + \let\definedummyword\definedummyaccent + % + \commondummiesnofonts + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + % Non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + \def\ordf{a}% + \def\ordm{o}% + % + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. + % (The following {} will end up in the sort string, but that's ok.) + \def\bullet{bullet}% + \def\comma{,}% + \def\copyright{copyright}% + \def\registeredsymbol{R}% + \def\dots{...}% + \def\enddots{...}% + \def\equiv{==}% + \def\error{error}% + \def\euro{euro}% + \def\guillemetleft{<<}% + \def\guillemetright{>>}% + \def\guilsinglleft{<}% + \def\guilsinglright{>}% + \def\expansion{==>}% + \def\minus{-}% + \def\pounds{pounds}% + \def\point{.}% + \def\print{-|}% + \def\quotedblbase{"}% + \def\quotedblleft{"}% + \def\quotedblright{"}% + \def\quoteleft{`}% + \def\quoteright{'}% + \def\quotesinglbase{,}% + \def\result{=>}% + \def\textdegree{degrees}% + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% Most index entries go through here, but \dosubind is the general case. +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{\dosubind{#1}{#2}{}} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% empty if called from \doind, as we usually are (the main exception +% is with most defuns, which call us directly). +% +\def\dosubind#1#2#3{% + \iflinks + {% + % Store the main index entry text (including the third arg). + \toks0 = {#2}% + % If third arg is present, precede it with a space. + \def\thirdarg{#3}% + \ifx\thirdarg\empty \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + \edef\writeto{\csname#1indfile\endcsname}% + % + \safewhatsit\dosubindwrite + }% + \fi +} + +% Write the entry in \toks0 to the index file: +% +\def\dosubindwrite{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% + \fi + % + % Remember, we are within a group. + \indexdummies % Must do this here, since \bf, etc expand at this stage + \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\writeto{% + \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% + }% + \temp +} + +% Take care of unwanted page breaks/skips around a whatsit: +% +% If a skip is the last thing on the list now, preserve it +% by backing up by \lastskip, doing the \write, then inserting +% the skip again. Otherwise, the whatsit generated by the +% \write or \pdfdest will make \lastskip zero. The result is that +% sequences like this: +% @end defun +% @tindex whatever +% @defun ... +% will have extra space inserted, because the \medbreak in the +% start of the @defun won't see the skip inserted by the @end of +% the previous defun. +% +% But don't do any of this if we're not in vertical mode. We +% don't want to do a \vskip and prematurely end a paragraph. +% +% Avoid page breaks due to these extra skips, too. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +\newskip\whatsitskip +\newcount\whatsitpenalty +% +% ..., ready, GO: +% +\def\safewhatsit#1{% +\ifhmode + #1% +\else + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \whatsitskip = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \whatsitpenalty = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\whatsitskip glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\whatsitskip + \fi + % + #1% + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\whatsitskip + \fi +\fi +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\parseargdef\printindex{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \plainfrenchspacing + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\backslashcurfont}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \nobreak + \vskip 0pt plus 3\baselineskip + \penalty 0 + \vskip 0pt plus -3\baselineskip + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + % Do our best not to break after the initial. + \nobreak + \vskip .33\baselineskip plus .1\baselineskip +}} + +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +% A straightforward implementation would start like this: +% \def\entry#1#2{... +% But this frozes the catcodes in the argument, and can cause problems to +% @code, which sets - active. This problem was fixed by a kludge--- +% ``-'' was active throughout whole index, but this isn't really right. +% +% The right solution is to prevent \entry from swallowing the whole text. +% --kasal, 21nov03 +\def\entry{% + \begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing + % columns. + \vskip 0pt plus1pt + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\doentry{% + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. +} +\def\finishentry#1{% + % #1 is the page number. + % + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \setbox\boxA = \hbox{#1}% + \ifdim\wd\boxA = 0pt + \ % + \else + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#1.% + \ \the\toksA + \else + \ #1% + \fi + \fi + \par + \endgroup +} + +% Like plain.tex's \dotfill, except uses up at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + % The following penalty ensures that the page builder is exercised + % _before_ we change the output routine. This is necessary in the + % following situation: + % + % The last section of the index consists only of a single entry. + % Before this section, \pagetotal is less than \pagegoal, so no + % break occurs before the last section starts. However, the last + % section, consisting of \initial and the single \entry, does not + % fit on the page and has to be broken off. Without the following + % penalty the page builder will not be exercised until \eject + % below, and by that time we'll already have changed the output + % routine to the \balancecolumns version, so the next-to-last + % double-column page will be processed with \balancecolumns, which + % is wrong: The two columns will go to the main vertical list, with + % the broken-off section in the recent contributions. As soon as + % the output routine finishes, TeX starts reconsidering the page + % break. The two columns and the broken-off section both fit on the + % page, because the two columns now take up only half of the page + % goal. When TeX sees \eject from below which follows the final + % section, it invokes the new output routine that we've set after + % \balancecolumns below; \onepageout will try to fit the two columns + % and the final section into the vbox of \pageheight (see + % \pagebody), causing an overfull box. + % + % Note that glue won't work here, because glue does not exercise the + % page builder, unlike penalties (see The TeXbook, pp. 280-281). + \penalty0 + % + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +% \unnumberedno is an oxymoron, of course. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% +% \def\appendixletter{\char\the\appendixno} +% We do the following ugly conditional instead of the above simple +% construct for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +% +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines these (using marks) as the number+name, number +% and name of the chapter. Page headings and footings can use +% these. @section does likewise. +\def\thischapter{} +\def\thischapternum{} +\def\thischaptername{} +\def\thissection{} +\def\thissectionnum{} +\def\thissectionname{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achive this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unmlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 + \else + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi + \fi + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unmlevel + \chardef\unmlevel = \absseclevel + \fi + \else + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unmlevel + \def\headtype{U}% + \else + \chardef\unmlevel = 3 + \fi + \fi + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi + \else + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi + \fi + \suppressfirstparagraphindent +} + +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + \message{\putwordChapter\space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + \def\appendixnum{\putwordAppendix\space \appendixletter}% + \message{\appendixnum}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the<toks register> to achieve this: TeX expands \the<toks> only once, + % simply yielding the contents of <toks register>. (We also do this for + % the toc entries.) + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% + % + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\parseargdef\centerchap{% + % Well, we could do the following in a group, but that would break + % an assumption that \chapmacro is called at the outermost level. + % Thus we are safer this way: --kasal, 24feb04 + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax +} + +% @top is like @unnumbered. +\let\top\unnumbered + +% Sections. +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% +} + +\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% +} +\let\appendixsec\appendixsection + +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% +} + +% Subsections. +\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% +} + +% Subsubsections. +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +} + +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% + \bigskip \par\penalty 200\relax + \suppressfirstparagraphindent +} + +% @heading, @subheading, @subsubheading. +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +% Because \domark is called before \chapoddpage, the filler page will +% get the headings for the next chapter, which is wrong. But we don't +% care -- we just disable all headings on the filler page. +\def\chapoddpage{% + \chappager + \ifodd\pageno \else + \begingroup + \evenheadline={\hfil}\evenfootline={\hfil}% + \oddheadline={\hfil}\oddfootline={\hfil}% + \hbox to 0pt{}% + \chappager + \endgroup + \fi +} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{% +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +% Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yomitfromtockeyword{Yomitfromtoc} +\def\Yappendixkeyword{Yappendix} +% +\def\chapmacro#1#2#3{% + % Insert the first mark before the heading break (see notes for \domark). + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% + \gdef\thissection{}}% + % + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{\thischaptername}}% + \else\ifx\temptype\Yomitfromtockeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{}}% + \else\ifx\temptype\Yappendixkeyword + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\appendixletter}% + \gdef\noexpand\thischapter{\putwordAppendix{} \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \else + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\the\chapno}% + \gdef\noexpand\thischapter{\putwordChapter{} \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \fi\fi\fi + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert the chapter heading break. + \pchapsepmacro + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \domark + % + {% + \chapfonts \rm + % + % Have to define \lastsection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\lastsection{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. + \nobreak % Avoid page breaks at the interline glue. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt +} + + +% I don't think this chapter style is supported any more, so I'm not +% updating it with the new noderef stuff. We'll see. --karl, 11aug03. +% +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} +% +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} +\def\CHAPFopen{% + \global\let\chapmacro=\chfopen + \global\let\centerchapmacro=\centerchfopen} + + +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} + +% Subsection titles. +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} + +% Subsubsection titles. +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} + + +% Print any size, any type, section title. +% +% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is +% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the +% section number. +% +\def\seckeyword{sec} +% +\def\sectionheading#1#2#3#4{% + {% + % Switch to the right set of fonts. + \csname #2fonts\endcsname \rm + % + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + % Insert first mark before the heading break (see notes for \domark). + \let\prevsectiondefs=\lastsectiondefs + \ifx\temptype\Ynothingkeyword + \ifx\sectionlevel\seckeyword + \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% + \gdef\thissection{\thissectionname}}% + \fi + \else\ifx\temptype\Yomitfromtockeyword + % Don't redefine \thissection. + \else\ifx\temptype\Yappendixkeyword + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \else + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \fi\fi\fi + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert space above the heading. + \csname #2headingbreak\endcsname + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevsectiondefs=\lastsectiondefs + \domark + % + % Only insert the space after the number if we have a section number. + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\lastsection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \lastsection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\lastsection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\lastsection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chapmacro. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chapmacro. + \donoderef{#3}% + % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % + % Output the actual section heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% + }% + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. + \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) + \vskip-\parskip + % + % This is purely so the last item on the list is a known \penalty > + % 10000. This is so \startdefun can avoid allowing breakpoints after + % section headings. Otherwise, it would insert a valid breakpoint between: + % + % @section sec-whatever + % @deffn def-whatever + \penalty 10001 +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. +% +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. +% +\newif\iftocfileopened +\def\omitkeyword{omit}% +% +\def\writetocentry#1#2#3{% + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% + \fi + \fi + % + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one on every page because the title pages are numbered + % 1 and 2 (the page numbers aren't printed), and so are the first + % two pages of the document. Thus, we'd have two destinations named + % `1', and two named `2'. + \ifpdf \global\pdfmakepagedesttrue \fi +} + + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \tocreadfilename +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Prepare to read what we've written to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund <tege@matematik.su.se> + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \chapmacro{#1}{Yomitfromtoc}{}% + % + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + +% redefined for the two-volume lispref. We always output on +% \jobname.toc even if this is redefined. +% +\def\tocreadfilename{\jobname.toc} + +% Normal (long) toc. +% +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \tocreadfilename\space + \ifeof 1 \else + \readtocfile + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% +} + +% Appendices, in the main contents. +% Need the word Appendix, and a fixed-size box. +% +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} +% +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} + +% Unnumbered chapters. +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} + +% Sections. +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} + +% And subsubsections. +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} + +% This parameter controls the indentation of the various levels. +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\envdef\tex{% + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + \let\frenchspacing=\plainfrenchspacing + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +} +% There is no need to define \Etex. + +% Define @lisp ... @end lisp. +% @lisp environment forms a group so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty<10000 \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\envdef\cartouche{% + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt % we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing = t% + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of \def\group. +} +\def\Ecartouche{% + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \checkinserts +} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \let\exdent=\nofillexdent +} + +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp +% +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + % end paragraph for sake of leading, in case document has no blank + % line. This is redundant with what happens in \aboveenvbreak, but + % we need to do it before changing the fonts, and it's inconvenient + % to change the fonts afterward. + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \ifnum \lastpenalty=10000 \else \endgraf \fi + \smallexamplefonts \rm + \fi +} + +% We often define two environments, @foo and @smallfoo. +% Let's do it by one command: +\def\makedispenv #1#2{ + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak +} + +% Define two synonyms: +\def\maketwodispenvs #1#2#3{ + \makedispenv{#1}{#3} + \makedispenv{#2}{#3} +} + +% @lisp: indented, narrowed, typewriter font; @example: same as @lisp. +% +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +% +\maketwodispenvs {lisp}{example}{% + \nonfillstart + \tt\quoteexpand + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} +% @display/@smalldisplay: same as @lisp except keep current font. +% +\makedispenv {display}{% + \nonfillstart + \gobble +} + +% @format/@smallformat: same as @display except don't narrow margins. +% +\makedispenv{format}{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} + +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} +\let\Eflushleft = \afterenvbreak + +% @flushright. +% +\envdef\flushright{% + \let\nonarrowing = t% + \nonfillstart + \advance\leftskip by 0pt plus 1fill + \gobble +} +\let\Eflushright = \afterenvbreak + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. +% +\envdef\quotation{% + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\undefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>} +% If we want to allow any <char> as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=\other}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} + +% Allow an option to not replace quotes with a regular directed right +% quote/apostrophe (char 0x27), but instead use the undirected quote +% from cmtt (char 0x0d). The undirected quote is ugly, so don't make it +% the default, but it works for pasting with more pdf viewers (at least +% evince), the lilypond developers report. xpdf does work with the +% regular 0x27. +% +\def\codequoteright{% + \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else \char'15 \fi + \else \char'15 \fi +} +% +% and a similar option for the left quote char vs. a grave accent. +% Modern fonts display ASCII 0x60 as a grave accent, so some people like +% the code environments to do likewise. +% +\def\codequoteleft{% + \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + `% + \else \char'22 \fi + \else \char'22 \fi +} +% +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } + \catcode`\'=\active + \gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}% + % + \catcode`\`=\active + \gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}% + % + \gdef\quoteexpand{\rquoteexpand \lquoteexpand}% +\endgroup + +% start the verbatim environment. +\def\setupverbatim{% + \let\nonarrowing = t% + \nonfillstart + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + \quoteexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'<char>#1<char>'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. +\endgroup +% +\envdef\verbatim{% + \setupverbatim\doverbatim +} +\let\Everbatim = \afterenvbreak + + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} +% +\def\doverbatiminclude#1{% + {% + \makevalueexpandable + \setupverbatim + \input #1 + \afterenvbreak + }% +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\copyingtext + \endgroup +} + + +\message{defuns,} +% @defun etc. + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt +\newcount\defunpenalty + +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak + \defunpenalty=10003 % Will keep this @deffn together with the + % following @def command, see below. + \else + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \printdefunline, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + % As a minor refinement, we avoid "club" headers by signalling + % with penalty of 10003 after the very first @deffn in the + % sequence (see above), and penalty of 10002 after any following + % @def command. + \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint + \fi + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% + % + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% +} +\def\gobbledefun#1\startdefun{} + +% \printdefunline \deffnheader{text} +% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty\defunpenalty % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup +} + +\def\Edefun{\endgraf\medbreak} + +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remainnig is to define \deffnheader. +% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp +} + +% \domakedefun \deffn \deffnx \deffnheader +% +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. +% +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% +} + +%%% Untyped functions: + +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} + +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} + +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deffngeneral {subind}category name args +% +\def\deffngeneral#1#2 #3 #4\endheader{% + % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +} + +%%% Typed functions: + +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} + +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} + +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Typed variables: + +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} + +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} + +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } + +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Untyped variables: + +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } + +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} + +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } + +%%% Type: +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% +} + +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} + +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. +% +% We are followed by (but not passed) the arguments, if any. +% +\def\defname#1#2#3{% + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % How we'll format the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % (plain.tex says that \dimen1 should be used only as global.) + \parshape 2 0in \dimen0 \defargsindent \dimen2 + % + % Put the type name to the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% return value type + \ifx\temp\empty\else \tclose{\temp} \fi + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \tenrm + % + \boldbrax + % arguments will be output next, if any. +} + +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. +% +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. Let's try @var for that. + \let\var=\ttslanted + #1% + \sl\hyphenchar\font=45 +} + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& + + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} +} + +\newcount\parencount + +% If we encounter &foo, then turn on ()-hacking afterwards +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} + +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi +} +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi +} +\def\bfafterword#1 {#1 \bf} + +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword +} +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 +} + +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 +} + +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi +} +% these should not use \errmessage; the glibc manual, at least, actually +% has such constructs (when documenting function pointers). +\def\badparencount{% + \message{Warning: unbalanced parentheses in @def...}% + \global\parencount=0 +} +\def\badbrackcount{% + \message{Warning: unbalanced square brackets in @def...}% + \global\brackcount=0 +} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } +\fi + +\def\scanmacro#1{% + \begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % ... and \example + \spaceisspace + % + % Append \endinput to make sure that TeX does not see the ending newline. + % I've verified that it is necessary both for e-TeX and for ordinary TeX + % --kasal, 29nov03 + \scantokens{#1\endinput}% + \endgroup +} + +\def\scanexp#1{% + \edef\temp{\noexpand\scanmacro{#1}}% + \temp +} + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? + +% List of all defined macros in the form +% \definedummyword\macro1\definedummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\definedummyword#1}% + \xdef\macrolist{\the\toks0}% +} + +% Utility routines. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% +\def\cslet#1#2{% + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% Non-ASCII encodings make 8-bit characters active, so un-activate +% them to avoid their expansion. Must do this non-globally, to +% confine the change to the current group. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\scanctxt{% + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\@=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\~=\other + \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi +} + +\def\scanargctxt{% + \scanctxt + \catcode`\\=\other + \catcode`\^^M=\other +} + +\def\macrobodyctxt{% + \scanctxt + \catcode`\{=\other + \catcode`\}=\other + \catcode`\^^M=\other + \usembodybackslash +} + +\def\macroargctxt{% + \scanctxt + \catcode`\\=\other +} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + \addtomacrolist{\the\macname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\parseargdef\unmacro{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\definedummyword\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx #1\relax + % remove this + \else + \noexpand\definedummyword \noexpand#1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% <parameter list> is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \macnamexxx} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\parseargusing\obeyspaces\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} + + +\message{cross references,} + +\newwrite\auxfile +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} + +\let\nwnode=\node +\let\lastnode=\empty + +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty + \fi +} + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \lastsection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. +% +\def\setref#1#2{% + \pdfmkdest{#1}% + \iflinks + {% + \atdummies % preserve commands, but don't expand them + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\lastsection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during \shipout + }% + \fi +} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printedrefname{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual\unskip}% + \setbox0=\hbox{\printedrefname\unskip}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printedrefname{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printedrefname{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printedrefname{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printedrefname{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % Make link in pdf output. + \ifpdf + \leavevmode + \getfilename{#4}% + {\indexnofonts + \turnoffactive + % See comments at \activebackslashdouble. + {\activebackslashdouble \xdef\pdfxrefdest{#1}% + \backslashparens\pdfxrefdest}% + % + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{\pdfxrefdest}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{\pdfmkpgn{\pdfxrefdest}}% + \fi + }% + \setcolor{\linkcolor}% + \fi + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". We distinguish them by the + % LABEL-title being set to a magic string. + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd0 = 0pt + \refx{#1-snt}{}% + \else + \printedrefname + \fi + % + % if the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd1 > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordSection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via a macro so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi + \fi + \endlink +\endgroup} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since square brackets don't work well in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% Things referred to by \setref. +% +\def\Ynothing{} +\def\Yomitfromtoc{} +\def\Ynumbered{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +\def\Yappendix{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname XR#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. Usually it's +% just a \def (we prepend XR to the control sequence name to avoid +% collisions). But if this is a float type, we have more work to do. +% +\def\xrdef#1#2{% + {% The node name might contain 8-bit characters, which in our current + % implementation are changed to commands like @'e. Don't let these + % mess up the control sequence name. + \indexnofonts + \turnoffactive + \xdef\safexrefname{#1}% + }% + % + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR\safexrefname\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 + {\safexrefname}}% + \fi +} + +% Read the last existing aux file, if any. No error if none exists. +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readdatafile{aux}% + \global\havexrefstrue + \fi + \closein 1 +} + +\def\setupdatafile{% + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % This is to support \ in node names and titles, since the \ + % characters end up in a \csname. It's easier than + % leaving it active and making its active definition an actual \ + % character. What I don't understand is why it works in the *value* + % of the xrdef. Seems like it should be a catcode12 \, and that + % should not typeset properly. But it works, so I'm moving on for + % now. --karl, 15jan04. + \catcode`\\=\other + % + % Make the characters 128-255 be printing characters. + {% + \count1=128 + \def\loop{% + \catcode\count1=\other + \advance\count1 by 1 + \ifnum \count1<256 \loop \fi + }% + }% + % + % @ is our escape character in .aux files, and we need braces. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 +\endgroup} + + +\message{insertions,} +% including footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\gdef\dofootnote{% + \insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarily, if a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is finished. +% And the same can be done for other insert classes. --kasal, 16nov03. + +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi +} + +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. +% +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +\closein 1 +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \egroup \bigbreak \fi % space after the image +\endgroup} + + +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \lastsection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\lastsection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \atdummies + % + % since we read the caption text in the macro world, where ^^M + % is turned into a normal character, we have to scan it back, so + % we don't write the literal three characters "^^M" into the aux file. + \scanexp{% + \xdef\noexpand\gtemp{% + \ifx\thisshortcaption\empty + \thiscaption + \else + \thisshortcaption + \fi + }% + }% + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + % place the captured inserts + % + % BEWARE: when the floats start floating, we have to issue warning + % whenever an insert appears inside a float which could possibly + % float. --kasal, 26may04 + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \lastsection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup + \fi +} + +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} + + +\message{localization,} + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language (de) or locale (de_DE) +% abbreviation. It would be nice if we could set up a hyphenation file. +% +{ + \catcode`\_ = \active + \globaldefs=1 +\parseargdef\documentlanguage{\begingroup + \let_=\normalunderscore % normal _ character for filenames + \tex % read txi-??.tex file in plain TeX. + % Read the file by the name they passed if it exists. + \openin 1 txi-#1.tex + \ifeof 1 + \documentlanguagetrywithoutunderscore{#1_\finish}% + \else + \input txi-#1.tex + \fi + \closein 1 + \endgroup +\endgroup} +} +% +% If they passed de_DE, and txi-de_DE.tex doesn't exist, +% try txi-de.tex. +% +\def\documentlanguagetrywithoutunderscore#1_#2\finish{% + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \input txi-#1.tex + \fi + \closein 1 +} +% +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + +% Set the catcode of characters 128 through 255 to the specified number. +% +\def\setnonasciicharscatcode#1{% + \count255=128 + \loop\ifnum\count255<256 + \global\catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +\def\setnonasciicharscatcodenonglobal#1{% + \count255=128 + \loop\ifnum\count255<256 + \catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +% @documentencoding sets the definition of non-ASCII characters +% according to the specified encoding. +% +\parseargdef\documentencoding{% + % Encoding being declared for the document. + \def\declaredencoding{\csname #1.enc\endcsname}% + % + % Supported encodings: names converted to tokens in order to be able + % to compare them with \ifx. + \def\ascii{\csname US-ASCII.enc\endcsname}% + \def\latnine{\csname ISO-8859-15.enc\endcsname}% + \def\latone{\csname ISO-8859-1.enc\endcsname}% + \def\lattwo{\csname ISO-8859-2.enc\endcsname}% + \def\utfeight{\csname UTF-8.enc\endcsname}% + % + \ifx \declaredencoding \ascii + \asciichardefs + % + \else \ifx \declaredencoding \lattwo + \setnonasciicharscatcode\active + \lattwochardefs + % + \else \ifx \declaredencoding \latone + \setnonasciicharscatcode\active + \latonechardefs + % + \else \ifx \declaredencoding \latnine + \setnonasciicharscatcode\active + \latninechardefs + % + \else \ifx \declaredencoding \utfeight + \setnonasciicharscatcode\active + \utfeightchardefs + % + \else + \message{Unknown document encoding #1, ignoring.}% + % + \fi % utfeight + \fi % latnine + \fi % latone + \fi % lattwo + \fi % ascii +} + +% A message to be logged when using a character that isn't available +% the default font encoding (OT1). +% +\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} + +% Take account of \c (plain) vs. \, (Texinfo) difference. +\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} + +% First, make active non-ASCII characters in order for them to be +% correctly categorized when TeX reads the replacement text of +% macros containing the character definitions. +\setnonasciicharscatcode\active +% +% Latin1 (ISO-8859-1) character definitions. +\def\latonechardefs{% + \gdef^^a0{~} + \gdef^^a1{\exclamdown} + \gdef^^a2{\missingcharmsg{CENT SIGN}} + \gdef^^a3{{\pounds}} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\missingcharmsg{YEN SIGN}} + \gdef^^a6{\missingcharmsg{BROKEN BAR}} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\copyright} + \gdef^^aa{\ordf} + \gdef^^ab{\missingcharmsg{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}} + \gdef^^ac{$\lnot$} + \gdef^^ad{\-} + \gdef^^ae{\registeredsymbol} + \gdef^^af{\={}} + % + \gdef^^b0{\textdegree} + \gdef^^b1{$\pm$} + \gdef^^b2{$^2$} + \gdef^^b3{$^3$} + \gdef^^b4{\'{}} + \gdef^^b5{$\mu$} + \gdef^^b6{\P} + % + \gdef^^b7{$^.$} + \gdef^^b8{\cedilla\ } + \gdef^^b9{$^1$} + \gdef^^ba{\ordm} + % + \gdef^^bb{\missingcharmsg{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}} + \gdef^^bc{$1\over4$} + \gdef^^bd{$1\over2$} + \gdef^^be{$3\over4$} + \gdef^^bf{\questiondown} + % + \gdef^^c0{\`A} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\~A} + \gdef^^c4{\"A} + \gdef^^c5{\ringaccent A} + \gdef^^c6{\AE} + \gdef^^c7{\cedilla C} + \gdef^^c8{\`E} + \gdef^^c9{\'E} + \gdef^^ca{\^E} + \gdef^^cb{\"E} + \gdef^^cc{\`I} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\"I} + % + \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}} + \gdef^^d1{\~N} + \gdef^^d2{\`O} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\~O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\O} + \gdef^^d9{\`U} + \gdef^^da{\'U} + \gdef^^db{\^U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}} + \gdef^^df{\ss} + % + \gdef^^e0{\`a} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\~a} + \gdef^^e4{\"a} + \gdef^^e5{\ringaccent a} + \gdef^^e6{\ae} + \gdef^^e7{\cedilla c} + \gdef^^e8{\`e} + \gdef^^e9{\'e} + \gdef^^ea{\^e} + \gdef^^eb{\"e} + \gdef^^ec{\`{\dotless i}} + \gdef^^ed{\'{\dotless i}} + \gdef^^ee{\^{\dotless i}} + \gdef^^ef{\"{\dotless i}} + % + \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}} + \gdef^^f1{\~n} + \gdef^^f2{\`o} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\~o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\o} + \gdef^^f9{\`u} + \gdef^^fa{\'u} + \gdef^^fb{\^u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}} + \gdef^^ff{\"y} +} + +% Latin9 (ISO-8859-15) encoding character definitions. +\def\latninechardefs{% + % Encoding is almost identical to Latin1. + \latonechardefs + % + \gdef^^a4{\euro} + \gdef^^a6{\v S} + \gdef^^a8{\v s} + \gdef^^b4{\v Z} + \gdef^^b8{\v z} + \gdef^^bc{\OE} + \gdef^^bd{\oe} + \gdef^^be{\"Y} +} + +% Latin2 (ISO-8859-2) character definitions. +\def\lattwochardefs{% + \gdef^^a0{~} + \gdef^^a1{\missingcharmsg{LATIN CAPITAL LETTER A WITH OGONEK}} + \gdef^^a2{\u{}} + \gdef^^a3{\L} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\v L} + \gdef^^a6{\'S} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\v S} + \gdef^^aa{\cedilla S} + \gdef^^ab{\v T} + \gdef^^ac{\'Z} + \gdef^^ad{\-} + \gdef^^ae{\v Z} + \gdef^^af{\dotaccent Z} + % + \gdef^^b0{\textdegree} + \gdef^^b1{\missingcharmsg{LATIN SMALL LETTER A WITH OGONEK}} + \gdef^^b2{\missingcharmsg{OGONEK}} + \gdef^^b3{\l} + \gdef^^b4{\'{}} + \gdef^^b5{\v l} + \gdef^^b6{\'s} + \gdef^^b7{\v{}} + \gdef^^b8{\cedilla\ } + \gdef^^b9{\v s} + \gdef^^ba{\cedilla s} + \gdef^^bb{\v t} + \gdef^^bc{\'z} + \gdef^^bd{\H{}} + \gdef^^be{\v z} + \gdef^^bf{\dotaccent z} + % + \gdef^^c0{\'R} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\u A} + \gdef^^c4{\"A} + \gdef^^c5{\'L} + \gdef^^c6{\'C} + \gdef^^c7{\cedilla C} + \gdef^^c8{\v C} + \gdef^^c9{\'E} + \gdef^^ca{\missingcharmsg{LATIN CAPITAL LETTER E WITH OGONEK}} + \gdef^^cb{\"E} + \gdef^^cc{\v E} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\v D} + % + \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}} + \gdef^^d1{\'N} + \gdef^^d2{\v N} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\H O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\v R} + \gdef^^d9{\ringaccent U} + \gdef^^da{\'U} + \gdef^^db{\H U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\cedilla T} + \gdef^^df{\ss} + % + \gdef^^e0{\'r} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\u a} + \gdef^^e4{\"a} + \gdef^^e5{\'l} + \gdef^^e6{\'c} + \gdef^^e7{\cedilla c} + \gdef^^e8{\v c} + \gdef^^e9{\'e} + \gdef^^ea{\missingcharmsg{LATIN SMALL LETTER E WITH OGONEK}} + \gdef^^eb{\"e} + \gdef^^ec{\v e} + \gdef^^ed{\'\i} + \gdef^^ee{\^\i} + \gdef^^ef{\v d} + % + \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}} + \gdef^^f1{\'n} + \gdef^^f2{\v n} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\H o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\v r} + \gdef^^f9{\ringaccent u} + \gdef^^fa{\'u} + \gdef^^fb{\H u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\cedilla t} + \gdef^^ff{\dotaccent{}} +} + +% UTF-8 character definitions. +% +% This code to support UTF-8 is based on LaTeX's utf8.def, with some +% changes for Texinfo conventions. It is included here under the GPL by +% permission from Frank Mittelbach and the LaTeX team. +% +\newcount\countUTFx +\newcount\countUTFy +\newcount\countUTFz + +\gdef\UTFviiiTwoOctets#1#2{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\endcsname} +% +\gdef\UTFviiiThreeOctets#1#2#3{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} +% +\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} + +\gdef\UTFviiiDefined#1{% + \ifx #1\relax + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \else + \expandafter #1% + \fi +} + +\begingroup + \catcode`\~13 + \catcode`\"12 + + \def\UTFviiiLoop{% + \global\catcode\countUTFx\active + \uccode`\~\countUTFx + \uppercase\expandafter{\UTFviiiTmp}% + \advance\countUTFx by 1 + \ifnum\countUTFx < \countUTFy + \expandafter\UTFviiiLoop + \fi} + + \countUTFx = "C2 + \countUTFy = "E0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiTwoOctets\string~}} + \UTFviiiLoop + + \countUTFx = "E0 + \countUTFy = "F0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiThreeOctets\string~}} + \UTFviiiLoop + + \countUTFx = "F0 + \countUTFy = "F4 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiFourOctets\string~}} + \UTFviiiLoop +\endgroup + +\begingroup + \catcode`\"=12 + \catcode`\<=12 + \catcode`\.=12 + \catcode`\,=12 + \catcode`\;=12 + \catcode`\!=12 + \catcode`\~=13 + + \gdef\DeclareUnicodeCharacter#1#2{% + \countUTFz = "#1\relax + \wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% + \begingroup + \parseXMLCharref + \def\UTFviiiTwoOctets##1##2{% + \csname u8:##1\string ##2\endcsname}% + \def\UTFviiiThreeOctets##1##2##3{% + \csname u8:##1\string ##2\string ##3\endcsname}% + \def\UTFviiiFourOctets##1##2##3##4{% + \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \gdef\UTFviiiTmp{#2}% + \endgroup} + + \gdef\parseXMLCharref{% + \ifnum\countUTFz < "A0\relax + \errhelp = \EMsimple + \errmessage{Cannot define Unicode char value < 00A0}% + \else\ifnum\countUTFz < "800\relax + \parseUTFviiiA,% + \parseUTFviiiB C\UTFviiiTwoOctets.,% + \else\ifnum\countUTFz < "10000\relax + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% + \else + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiA!% + \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% + \fi\fi\fi + } + + \gdef\parseUTFviiiA#1{% + \countUTFx = \countUTFz + \divide\countUTFz by 64 + \countUTFy = \countUTFz + \multiply\countUTFz by 64 + \advance\countUTFx by -\countUTFz + \advance\countUTFx by 128 + \uccode `#1\countUTFx + \countUTFz = \countUTFy} + + \gdef\parseUTFviiiB#1#2#3#4{% + \advance\countUTFz by "#10\relax + \uccode `#3\countUTFz + \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} +\endgroup + +\def\utfeightchardefs{% + \DeclareUnicodeCharacter{00A0}{\tie} + \DeclareUnicodeCharacter{00A1}{\exclamdown} + \DeclareUnicodeCharacter{00A3}{\pounds} + \DeclareUnicodeCharacter{00A8}{\"{ }} + \DeclareUnicodeCharacter{00A9}{\copyright} + \DeclareUnicodeCharacter{00AA}{\ordf} + \DeclareUnicodeCharacter{00AB}{\guillemetleft} + \DeclareUnicodeCharacter{00AD}{\-} + \DeclareUnicodeCharacter{00AE}{\registeredsymbol} + \DeclareUnicodeCharacter{00AF}{\={ }} + + \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} + \DeclareUnicodeCharacter{00B4}{\'{ }} + \DeclareUnicodeCharacter{00B8}{\cedilla{ }} + \DeclareUnicodeCharacter{00BA}{\ordm} + \DeclareUnicodeCharacter{00BB}{\guillemetright} + \DeclareUnicodeCharacter{00BF}{\questiondown} + + \DeclareUnicodeCharacter{00C0}{\`A} + \DeclareUnicodeCharacter{00C1}{\'A} + \DeclareUnicodeCharacter{00C2}{\^A} + \DeclareUnicodeCharacter{00C3}{\~A} + \DeclareUnicodeCharacter{00C4}{\"A} + \DeclareUnicodeCharacter{00C5}{\AA} + \DeclareUnicodeCharacter{00C6}{\AE} + \DeclareUnicodeCharacter{00C7}{\cedilla{C}} + \DeclareUnicodeCharacter{00C8}{\`E} + \DeclareUnicodeCharacter{00C9}{\'E} + \DeclareUnicodeCharacter{00CA}{\^E} + \DeclareUnicodeCharacter{00CB}{\"E} + \DeclareUnicodeCharacter{00CC}{\`I} + \DeclareUnicodeCharacter{00CD}{\'I} + \DeclareUnicodeCharacter{00CE}{\^I} + \DeclareUnicodeCharacter{00CF}{\"I} + + \DeclareUnicodeCharacter{00D1}{\~N} + \DeclareUnicodeCharacter{00D2}{\`O} + \DeclareUnicodeCharacter{00D3}{\'O} + \DeclareUnicodeCharacter{00D4}{\^O} + \DeclareUnicodeCharacter{00D5}{\~O} + \DeclareUnicodeCharacter{00D6}{\"O} + \DeclareUnicodeCharacter{00D8}{\O} + \DeclareUnicodeCharacter{00D9}{\`U} + \DeclareUnicodeCharacter{00DA}{\'U} + \DeclareUnicodeCharacter{00DB}{\^U} + \DeclareUnicodeCharacter{00DC}{\"U} + \DeclareUnicodeCharacter{00DD}{\'Y} + \DeclareUnicodeCharacter{00DF}{\ss} + + \DeclareUnicodeCharacter{00E0}{\`a} + \DeclareUnicodeCharacter{00E1}{\'a} + \DeclareUnicodeCharacter{00E2}{\^a} + \DeclareUnicodeCharacter{00E3}{\~a} + \DeclareUnicodeCharacter{00E4}{\"a} + \DeclareUnicodeCharacter{00E5}{\aa} + \DeclareUnicodeCharacter{00E6}{\ae} + \DeclareUnicodeCharacter{00E7}{\cedilla{c}} + \DeclareUnicodeCharacter{00E8}{\`e} + \DeclareUnicodeCharacter{00E9}{\'e} + \DeclareUnicodeCharacter{00EA}{\^e} + \DeclareUnicodeCharacter{00EB}{\"e} + \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} + \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} + \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} + \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} + + \DeclareUnicodeCharacter{00F1}{\~n} + \DeclareUnicodeCharacter{00F2}{\`o} + \DeclareUnicodeCharacter{00F3}{\'o} + \DeclareUnicodeCharacter{00F4}{\^o} + \DeclareUnicodeCharacter{00F5}{\~o} + \DeclareUnicodeCharacter{00F6}{\"o} + \DeclareUnicodeCharacter{00F8}{\o} + \DeclareUnicodeCharacter{00F9}{\`u} + \DeclareUnicodeCharacter{00FA}{\'u} + \DeclareUnicodeCharacter{00FB}{\^u} + \DeclareUnicodeCharacter{00FC}{\"u} + \DeclareUnicodeCharacter{00FD}{\'y} + \DeclareUnicodeCharacter{00FF}{\"y} + + \DeclareUnicodeCharacter{0100}{\=A} + \DeclareUnicodeCharacter{0101}{\=a} + \DeclareUnicodeCharacter{0102}{\u{A}} + \DeclareUnicodeCharacter{0103}{\u{a}} + \DeclareUnicodeCharacter{0106}{\'C} + \DeclareUnicodeCharacter{0107}{\'c} + \DeclareUnicodeCharacter{0108}{\^C} + \DeclareUnicodeCharacter{0109}{\^c} + \DeclareUnicodeCharacter{010A}{\dotaccent{C}} + \DeclareUnicodeCharacter{010B}{\dotaccent{c}} + \DeclareUnicodeCharacter{010C}{\v{C}} + \DeclareUnicodeCharacter{010D}{\v{c}} + \DeclareUnicodeCharacter{010E}{\v{D}} + + \DeclareUnicodeCharacter{0112}{\=E} + \DeclareUnicodeCharacter{0113}{\=e} + \DeclareUnicodeCharacter{0114}{\u{E}} + \DeclareUnicodeCharacter{0115}{\u{e}} + \DeclareUnicodeCharacter{0116}{\dotaccent{E}} + \DeclareUnicodeCharacter{0117}{\dotaccent{e}} + \DeclareUnicodeCharacter{011A}{\v{E}} + \DeclareUnicodeCharacter{011B}{\v{e}} + \DeclareUnicodeCharacter{011C}{\^G} + \DeclareUnicodeCharacter{011D}{\^g} + \DeclareUnicodeCharacter{011E}{\u{G}} + \DeclareUnicodeCharacter{011F}{\u{g}} + + \DeclareUnicodeCharacter{0120}{\dotaccent{G}} + \DeclareUnicodeCharacter{0121}{\dotaccent{g}} + \DeclareUnicodeCharacter{0124}{\^H} + \DeclareUnicodeCharacter{0125}{\^h} + \DeclareUnicodeCharacter{0128}{\~I} + \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} + \DeclareUnicodeCharacter{012A}{\=I} + \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} + \DeclareUnicodeCharacter{012C}{\u{I}} + \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} + + \DeclareUnicodeCharacter{0130}{\dotaccent{I}} + \DeclareUnicodeCharacter{0131}{\dotless{i}} + \DeclareUnicodeCharacter{0132}{IJ} + \DeclareUnicodeCharacter{0133}{ij} + \DeclareUnicodeCharacter{0134}{\^J} + \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} + \DeclareUnicodeCharacter{0139}{\'L} + \DeclareUnicodeCharacter{013A}{\'l} + + \DeclareUnicodeCharacter{0141}{\L} + \DeclareUnicodeCharacter{0142}{\l} + \DeclareUnicodeCharacter{0143}{\'N} + \DeclareUnicodeCharacter{0144}{\'n} + \DeclareUnicodeCharacter{0147}{\v{N}} + \DeclareUnicodeCharacter{0148}{\v{n}} + \DeclareUnicodeCharacter{014C}{\=O} + \DeclareUnicodeCharacter{014D}{\=o} + \DeclareUnicodeCharacter{014E}{\u{O}} + \DeclareUnicodeCharacter{014F}{\u{o}} + + \DeclareUnicodeCharacter{0150}{\H{O}} + \DeclareUnicodeCharacter{0151}{\H{o}} + \DeclareUnicodeCharacter{0152}{\OE} + \DeclareUnicodeCharacter{0153}{\oe} + \DeclareUnicodeCharacter{0154}{\'R} + \DeclareUnicodeCharacter{0155}{\'r} + \DeclareUnicodeCharacter{0158}{\v{R}} + \DeclareUnicodeCharacter{0159}{\v{r}} + \DeclareUnicodeCharacter{015A}{\'S} + \DeclareUnicodeCharacter{015B}{\'s} + \DeclareUnicodeCharacter{015C}{\^S} + \DeclareUnicodeCharacter{015D}{\^s} + \DeclareUnicodeCharacter{015E}{\cedilla{S}} + \DeclareUnicodeCharacter{015F}{\cedilla{s}} + + \DeclareUnicodeCharacter{0160}{\v{S}} + \DeclareUnicodeCharacter{0161}{\v{s}} + \DeclareUnicodeCharacter{0162}{\cedilla{t}} + \DeclareUnicodeCharacter{0163}{\cedilla{T}} + \DeclareUnicodeCharacter{0164}{\v{T}} + + \DeclareUnicodeCharacter{0168}{\~U} + \DeclareUnicodeCharacter{0169}{\~u} + \DeclareUnicodeCharacter{016A}{\=U} + \DeclareUnicodeCharacter{016B}{\=u} + \DeclareUnicodeCharacter{016C}{\u{U}} + \DeclareUnicodeCharacter{016D}{\u{u}} + \DeclareUnicodeCharacter{016E}{\ringaccent{U}} + \DeclareUnicodeCharacter{016F}{\ringaccent{u}} + + \DeclareUnicodeCharacter{0170}{\H{U}} + \DeclareUnicodeCharacter{0171}{\H{u}} + \DeclareUnicodeCharacter{0174}{\^W} + \DeclareUnicodeCharacter{0175}{\^w} + \DeclareUnicodeCharacter{0176}{\^Y} + \DeclareUnicodeCharacter{0177}{\^y} + \DeclareUnicodeCharacter{0178}{\"Y} + \DeclareUnicodeCharacter{0179}{\'Z} + \DeclareUnicodeCharacter{017A}{\'z} + \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} + \DeclareUnicodeCharacter{017C}{\dotaccent{z}} + \DeclareUnicodeCharacter{017D}{\v{Z}} + \DeclareUnicodeCharacter{017E}{\v{z}} + + \DeclareUnicodeCharacter{01C4}{D\v{Z}} + \DeclareUnicodeCharacter{01C5}{D\v{z}} + \DeclareUnicodeCharacter{01C6}{d\v{z}} + \DeclareUnicodeCharacter{01C7}{LJ} + \DeclareUnicodeCharacter{01C8}{Lj} + \DeclareUnicodeCharacter{01C9}{lj} + \DeclareUnicodeCharacter{01CA}{NJ} + \DeclareUnicodeCharacter{01CB}{Nj} + \DeclareUnicodeCharacter{01CC}{nj} + \DeclareUnicodeCharacter{01CD}{\v{A}} + \DeclareUnicodeCharacter{01CE}{\v{a}} + \DeclareUnicodeCharacter{01CF}{\v{I}} + + \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} + \DeclareUnicodeCharacter{01D1}{\v{O}} + \DeclareUnicodeCharacter{01D2}{\v{o}} + \DeclareUnicodeCharacter{01D3}{\v{U}} + \DeclareUnicodeCharacter{01D4}{\v{u}} + + \DeclareUnicodeCharacter{01E2}{\={\AE}} + \DeclareUnicodeCharacter{01E3}{\={\ae}} + \DeclareUnicodeCharacter{01E6}{\v{G}} + \DeclareUnicodeCharacter{01E7}{\v{g}} + \DeclareUnicodeCharacter{01E8}{\v{K}} + \DeclareUnicodeCharacter{01E9}{\v{k}} + + \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} + \DeclareUnicodeCharacter{01F1}{DZ} + \DeclareUnicodeCharacter{01F2}{Dz} + \DeclareUnicodeCharacter{01F3}{dz} + \DeclareUnicodeCharacter{01F4}{\'G} + \DeclareUnicodeCharacter{01F5}{\'g} + \DeclareUnicodeCharacter{01F8}{\`N} + \DeclareUnicodeCharacter{01F9}{\`n} + \DeclareUnicodeCharacter{01FC}{\'{\AE}} + \DeclareUnicodeCharacter{01FD}{\'{\ae}} + \DeclareUnicodeCharacter{01FE}{\'{\O}} + \DeclareUnicodeCharacter{01FF}{\'{\o}} + + \DeclareUnicodeCharacter{021E}{\v{H}} + \DeclareUnicodeCharacter{021F}{\v{h}} + + \DeclareUnicodeCharacter{0226}{\dotaccent{A}} + \DeclareUnicodeCharacter{0227}{\dotaccent{a}} + \DeclareUnicodeCharacter{0228}{\cedilla{E}} + \DeclareUnicodeCharacter{0229}{\cedilla{e}} + \DeclareUnicodeCharacter{022E}{\dotaccent{O}} + \DeclareUnicodeCharacter{022F}{\dotaccent{o}} + + \DeclareUnicodeCharacter{0232}{\=Y} + \DeclareUnicodeCharacter{0233}{\=y} + \DeclareUnicodeCharacter{0237}{\dotless{j}} + + \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} + \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} + \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} + \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} + \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} + \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} + \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} + \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} + \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} + \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} + \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} + \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} + + \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} + \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} + + \DeclareUnicodeCharacter{1E20}{\=G} + \DeclareUnicodeCharacter{1E21}{\=g} + \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} + \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} + \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} + \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} + \DeclareUnicodeCharacter{1E26}{\"H} + \DeclareUnicodeCharacter{1E27}{\"h} + + \DeclareUnicodeCharacter{1E30}{\'K} + \DeclareUnicodeCharacter{1E31}{\'k} + \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} + \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} + \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} + \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} + \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} + \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} + \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} + \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} + \DeclareUnicodeCharacter{1E3E}{\'M} + \DeclareUnicodeCharacter{1E3F}{\'m} + + \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} + \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} + \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} + \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} + \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} + \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} + \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} + \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} + \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} + \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} + + \DeclareUnicodeCharacter{1E54}{\'P} + \DeclareUnicodeCharacter{1E55}{\'p} + \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} + \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} + \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} + \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} + \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} + \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} + \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} + \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} + + \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} + \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} + \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} + \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} + \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} + \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} + \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} + \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} + \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} + \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} + + \DeclareUnicodeCharacter{1E7C}{\~V} + \DeclareUnicodeCharacter{1E7D}{\~v} + \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} + \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} + + \DeclareUnicodeCharacter{1E80}{\`W} + \DeclareUnicodeCharacter{1E81}{\`w} + \DeclareUnicodeCharacter{1E82}{\'W} + \DeclareUnicodeCharacter{1E83}{\'w} + \DeclareUnicodeCharacter{1E84}{\"W} + \DeclareUnicodeCharacter{1E85}{\"w} + \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} + \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} + \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} + \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} + \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} + \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} + \DeclareUnicodeCharacter{1E8C}{\"X} + \DeclareUnicodeCharacter{1E8D}{\"x} + \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} + \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} + + \DeclareUnicodeCharacter{1E90}{\^Z} + \DeclareUnicodeCharacter{1E91}{\^z} + \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} + \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} + \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} + \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} + \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} + \DeclareUnicodeCharacter{1E97}{\"t} + \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} + \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} + + \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} + \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} + + \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} + \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} + \DeclareUnicodeCharacter{1EBC}{\~E} + \DeclareUnicodeCharacter{1EBD}{\~e} + + \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} + \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} + \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} + \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} + + \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} + \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} + + \DeclareUnicodeCharacter{1EF2}{\`Y} + \DeclareUnicodeCharacter{1EF3}{\`y} + \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} + + \DeclareUnicodeCharacter{1EF8}{\~Y} + \DeclareUnicodeCharacter{1EF9}{\~y} + + \DeclareUnicodeCharacter{2013}{--} + \DeclareUnicodeCharacter{2014}{---} + \DeclareUnicodeCharacter{2018}{\quoteleft} + \DeclareUnicodeCharacter{2019}{\quoteright} + \DeclareUnicodeCharacter{201A}{\quotesinglbase} + \DeclareUnicodeCharacter{201C}{\quotedblleft} + \DeclareUnicodeCharacter{201D}{\quotedblright} + \DeclareUnicodeCharacter{201E}{\quotedblbase} + \DeclareUnicodeCharacter{2022}{\bullet} + \DeclareUnicodeCharacter{2026}{\dots} + \DeclareUnicodeCharacter{2039}{\guilsinglleft} + \DeclareUnicodeCharacter{203A}{\guilsinglright} + \DeclareUnicodeCharacter{20AC}{\euro} + + \DeclareUnicodeCharacter{2192}{\expansion} + \DeclareUnicodeCharacter{21D2}{\result} + + \DeclareUnicodeCharacter{2212}{\minus} + \DeclareUnicodeCharacter{2217}{\point} + \DeclareUnicodeCharacter{2261}{\equiv} +}% end of \utfeightchardefs + + +% US-ASCII character definitions. +\def\asciichardefs{% nothing need be done + \relax +} + +% Make non-ASCII characters printable again for compatibility with +% existing Texinfo documents that may use them, even without declaring a +% document encoding. +% +\setnonasciicharscatcode \other + + +\message{formatting,} + +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + % if we don't reset these, they will remain at "1 true in" of + % whatever layout pdftex was dumped with. + \pdfhorigin = 1 true in + \pdfvorigin = 1 true in + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{607.2pt}{6in}% that's 46 lines + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.25 trim size. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {-.2in}{0in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .4cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{673.2pt}{160mm}% that's 51 lines + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1\relax + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +\let\realunder=_ +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} + +\catcode`\@=0 + +% \backslashcurfont outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\backslashcurfont=`\\ +\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work + +% \realbackslash is an actual character `\' with catcode other, and +% \doublebackslash is two of them (for the pdf outlines). +{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} + +% In texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active +@def@normalbackslash{{@tt@backslashcurfont}} +% On startup, @fixbackslash assigns: +% @let \ = @normalbackslash + +% \rawbackslash defines an active \ to do \backslashcurfont. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +@gdef@rawbackslash{@let\=@backslashcurfont} +@gdef@otherbackslash{@let\=@realbackslash} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. +% +@def@normalturnoffactive{% + @let\=@normalbackslash + @let"=@normaldoublequote + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix + @unsepspaces +} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\' in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also turn back on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: + +@c vim:sw=2: + +@ignore + arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 +@end ignore diff --git a/doc/use-cases.fig b/doc/use-cases.fig new file mode 100644 index 000000000..24118ff31 --- /dev/null +++ b/doc/use-cases.fig @@ -0,0 +1,199 @@ +#FIG 3.2 +Portrait +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +0 32 #424242 +0 33 #848484 +0 34 #c6c6c6 +0 35 #8c8c8c +0 36 #c6c6c6 +0 37 #848484 +0 38 #8c8c8c +0 39 #424242 +0 40 #848484 +0 41 #c6c6c6 +0 42 #e7e7e7 +0 43 #c6b594 +0 44 #efffff +0 45 #decea5 +0 46 #adadad +0 47 #525252 +0 48 #8c8c8c +0 49 #424242 +0 50 #848484 +0 51 #c6c6c6 +0 52 #e7e7e7 +0 53 #424242 +0 54 #848484 +0 55 #c6c6c6 +0 56 #e7e7e7 +0 57 #424242 +0 58 #848484 +0 59 #c6c6c6 +0 60 #e7e7e7 +0 61 #424242 +0 62 #848484 +0 63 #c6c6c6 +0 64 #e7e7e7 +0 65 #424242 +0 66 #848484 +0 67 #c6c6c6 +0 68 #e7e7e7 +0 69 #8c8c8c +0 70 #424242 +0 71 #848484 +0 72 #c6c6c6 +0 73 #424242 +0 74 #c6c6c6 +0 75 #e7e7e7 +0 76 #424242 +0 77 #848484 +0 78 #c6c6c6 +0 79 #848484 +0 80 #c6c6c6 +0 81 #e7e7e7 +0 82 #424242 +0 83 #8c8c8c +0 84 #424242 +0 85 #8c8c8c +0 86 #424242 +0 87 #8c8c8c +0 88 #424242 +0 89 #8c8c8c +0 90 #424242 +0 91 #8c8c8c +0 92 #424242 +0 93 #8c8c8c +0 94 #424242 +0 95 #8c8c8c +0 96 #424242 +0 97 #8c8c8c +0 98 #c6c6c6 +0 99 #e7e7e7 +0 100 #848484 +0 101 #c6c6c6 +0 102 #e7e7e7 +0 103 #8c8c8c +0 104 #424242 +0 105 #8c8c8c +0 106 #424242 +0 107 #848484 +0 108 #c6c6c6 +0 109 #e7e7e7 +0 110 #8c8c8c +0 111 #424242 +0 112 #8c8c8c +0 113 #8c8c8c +0 114 #8c8c8c +0 115 #424242 +0 116 #adadad +6 450 225 1350 1710 +1 4 0 1 0 7 100 0 -1 4.000 1 0.0000 900 406 176 176 765 294 1035 519 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 3 + 450 1710 900 1260 1350 1710 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 16 + 900 1260 900 1215 900 1170 900 1125 900 1080 900 1035 + 900 990 900 945 900 900 900 855 900 810 900 765 + 900 720 900 675 900 630 900 585 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 450 810 1350 810 +-6 +6 450 2250 1350 3735 +1 4 0 1 0 7 100 0 -1 4.000 1 0.0000 900 2431 176 176 765 2319 1035 2544 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 3 + 450 3735 900 3285 1350 3735 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 16 + 900 3285 900 3240 900 3195 900 3150 900 3105 900 3060 + 900 3015 900 2970 900 2925 900 2880 900 2835 900 2790 + 900 2745 900 2700 900 2655 900 2610 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 450 2835 1350 2835 +-6 +6 450 4275 1350 5760 +1 4 0 1 0 7 100 0 -1 4.000 1 0.0000 900 4456 176 176 765 4344 1035 4569 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 3 + 450 5760 900 5310 1350 5760 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 16 + 900 5310 900 5265 900 5220 900 5175 900 5130 900 5085 + 900 5040 900 4995 900 4950 900 4905 900 4860 900 4815 + 900 4770 900 4725 900 4680 900 4635 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 450 4860 1350 4860 +-6 +6 2250 540 3645 1305 +1 2 0 1 0 7 100 0 20 4.000 1 0.0000 2947 922 697 382 2250 540 3645 1305 +4 0 0 100 0 16 12 0.0000 4 135 1245 2340 990 Hack On Guile\001 +-6 +6 2250 2745 3645 3510 +1 2 0 1 0 7 100 0 20 4.000 1 0.0000 2947 3127 697 382 2250 2745 3645 3510 +4 0 0 100 0 16 12 0.0000 4 135 915 2520 3060 Write Guile\001 +4 0 0 50 0 16 12 0.0000 4 135 900 2520 3285 Extensions\001 +-6 +6 2250 4770 3645 5535 +1 2 0 1 0 7 100 0 20 4.000 1 0.0000 2947 5152 697 382 2250 4770 3645 5535 +4 0 0 100 0 16 12 0.0000 4 135 1065 2430 5220 Embed Guile\001 +-6 +6 2250 3690 3645 4455 +1 2 0 1 0 7 100 0 20 4.000 1 0.0000 2947 4072 697 382 2250 3690 3645 4455 +4 0 0 100 0 16 12 0.0000 4 180 1215 2385 4140 Use Guile App\001 +-6 +6 2250 1620 3645 2385 +1 2 0 1 0 7 100 0 20 4.000 1 0.0000 2947 2002 697 382 2250 1620 3645 2385 +4 0 0 100 0 16 12 0.0000 4 180 1050 2430 2070 Write Scripts\001 +-6 +6 4635 1350 5535 2835 +1 4 0 1 0 7 100 0 -1 4.000 1 0.0000 5085 1531 176 176 4950 1419 5220 1644 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 3 + 4635 2835 5085 2385 5535 2835 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 16 + 5085 2385 5085 2340 5085 2295 5085 2250 5085 2205 5085 2160 + 5085 2115 5085 2070 5085 2025 5085 1980 5085 1935 5085 1890 + 5085 1845 5085 1800 5085 1755 5085 1710 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 4635 1935 5535 1935 +-6 +6 4635 3375 5535 4860 +1 4 0 1 0 7 100 0 -1 4.000 1 0.0000 5085 3556 176 176 4950 3444 5220 3669 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 3 + 4635 4860 5085 4410 5535 4860 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 16 + 5085 4410 5085 4365 5085 4320 5085 4275 5085 4230 5085 4185 + 5085 4140 5085 4095 5085 4050 5085 4005 5085 3960 5085 3915 + 5085 3870 5085 3825 5085 3780 5085 3735 +2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 0 0 2 + 4635 3960 5535 3960 +-6 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 1395 945 2272 945 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 1395 3150 2272 3150 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 1395 5130 2272 5130 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 1395 4860 2295 3330 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 1395 1215 2385 2880 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 4545 1980 3668 1980 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 314.32 228.60 + 4545 4050 3668 4050 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1980 135 3960 135 3960 6075 1980 6075 1980 135 +4 0 0 50 0 16 12 0.0000 4 180 1365 225 1935 Guile Developer\001 +4 0 0 50 0 16 12 0.0000 4 180 1740 90 3960 Extension Developer\001 +4 0 0 50 0 16 12 0.0000 4 180 1875 45 5985 Application Developer\001 +4 0 0 50 0 16 12 0.0000 4 135 435 2790 360 Guile\001 +4 0 0 50 0 16 12 0.0000 4 180 1725 4230 3060 Scheme Programmer\001 +4 0 0 50 0 16 12 0.0000 4 180 1380 4410 5085 Application User\001 diff --git a/doc/use-cases.txt b/doc/use-cases.txt new file mode 100644 index 000000000..e455fd1b8 --- /dev/null +++ b/doc/use-cases.txt @@ -0,0 +1,22 @@ + +-------------------+ + | Guile | + O | | + -+- | .---------------. | + | -------->| Hack On Guile | | + / \ \ | `---------------' | O +Guile Developer | .---------------. | -+- + \ | | Write Scripts |<------ | + O \ | `---------------' | / \ + -+- `--->.---------------. | Scheme Programmer + | -------->| Write Guile | | + / \ .-->| Extensions | | + Extension / | `---------------' | O + Developer / | .---------------. | -+- + / | | Use Guile App |<------ | + O / | `---------------' | / \ + -+- / | .---------------. | Application User + | -------->| Embed Guile | | + / \ | `---------------' | + Application | | + Developer | | + +-------------------+ |