diff options
Diffstat (limited to 'doc/ref')
-rw-r--r-- | doc/ref/Makefile.am | 21 | ||||
-rw-r--r-- | doc/ref/api-binding.texi | 16 | ||||
-rw-r--r-- | doc/ref/api-compound.texi | 56 | ||||
-rwxr-xr-x | doc/ref/api-data.texi | 444 | ||||
-rw-r--r-- | doc/ref/api-init.texi | 2 | ||||
-rw-r--r-- | doc/ref/api-io.texi | 270 | ||||
-rw-r--r-- | doc/ref/api-memory.texi | 4 | ||||
-rw-r--r-- | doc/ref/api-procedures.texi | 28 | ||||
-rw-r--r-- | doc/ref/api-undocumented.texi | 2 | ||||
-rw-r--r-- | doc/ref/autoconf.texi | 10 | ||||
-rw-r--r-- | doc/ref/compiler.texi | 840 | ||||
-rw-r--r-- | doc/ref/intro.texi | 12 | ||||
-rw-r--r-- | doc/ref/libguile-concepts.texi | 2 | ||||
-rw-r--r-- | doc/ref/posix.texi | 4 | ||||
-rw-r--r-- | doc/ref/preface.texi | 6 | ||||
-rw-r--r-- | doc/ref/srfi-modules.texi | 20 | ||||
-rw-r--r-- | doc/ref/vm.texi | 466 |
17 files changed, 1563 insertions, 640 deletions
diff --git a/doc/ref/Makefile.am b/doc/ref/Makefile.am index 9799a5e0b..abf42edfe 100644 --- a/doc/ref/Makefile.am +++ b/doc/ref/Makefile.am @@ -4,20 +4,20 @@ ## ## This file is part of GUILE. ## -## GUILE 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 2, or +## 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 General Public License for more details. +## GNU Lesser General Public License for more details. ## -## You should have received a copy of the GNU General Public -## License along with GUILE; see the file COPYING. If not, write -## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth -## Floor, Boston, MA 02110-1301 USA +## 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 @@ -89,8 +89,9 @@ include $(top_srcdir)/am/pre-inst-guile # Automated snarfing autoconf.texi: autoconf-macros.texi -autoconf-macros.texi: $(top_srcdir)/guile-config/guile.m4 - $(preinstguiletool)/snarf-guile-m4-docs $(top_srcdir)/guile-config/guile.m4 \ +autoconf-macros.texi: $(top_srcdir)/meta/guile.m4 + GUILE_AUTO_COMPILE=0 $(top_builddir)/meta/uninstalled-env guile-tools \ + snarf-guile-m4-docs $(top_srcdir)/meta/guile.m4 \ > $(srcdir)/$@ lib-version.texi: $(top_srcdir)/GUILE-VERSION diff --git a/doc/ref/api-binding.texi b/doc/ref/api-binding.texi index b42f5567f..e53c48040 100644 --- a/doc/ref/api-binding.texi +++ b/doc/ref/api-binding.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -271,10 +271,16 @@ with duplicate bindings. Guile provides a procedure for checking whether a symbol is bound in the top level environment. -@c NJFIXME explain [env] -@deffn {Scheme Procedure} defined? sym [env] -@deffnx {C Function} scm_defined_p (sym, env) -Return @code{#t} if @var{sym} is defined in the lexical environment @var{env}. When @var{env} is not specified, look in the top-level environment as defined by the current module. +@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}. + +Up to Guile 1.8, the second optional argument had to be @dfn{lexical +environment} as returned by @code{the-environment}, for example. The +behavior of this function remains unchanged when the second argument is +omitted. @end deffn diff --git a/doc/ref/api-compound.texi b/doc/ref/api-compound.texi index f3fe9584a..7eccb8690 100644 --- a/doc/ref/api-compound.texi +++ b/doc/ref/api-compound.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -1405,6 +1405,12 @@ C}), but returns a pointer to the elements of a uniform numeric vector of the indicated kind. @end deftypefn +Uniform numeric vectors can be written to and read from input/output +ports using the procedures listed below. However, bytevectors may often +be more convenient for binary input/output since they provide more +flexibility in the interpretation of raw byte sequences +(@pxref{Bytevectors}). + @deffn {Scheme Procedure} uniform-vector-read! uvec [port_or_fd [start [end]]] @deffnx {C Function} scm_uniform_vector_read_x (uvec, port_or_fd, start, end) Fill the elements of @var{uvec} by reading @@ -1643,18 +1649,18 @@ and writing. @subsection Generalized Vectors Guile has a number of data types that are generally vector-like: -strings, uniform numeric vectors, bitvectors, and of course ordinary -vectors of arbitrary Scheme values. These types are disjoint: a -Scheme value belongs to at most one of the four types listed above. +strings, uniform numeric vectors, bytevectors, bitvectors, and of course +ordinary vectors of arbitrary Scheme values. These types are disjoint: +a Scheme value belongs to at most one of the five types listed above. If you want to gloss over this distinction and want to treat all four types with common code, you can use the procedures in this section. They work with the @emph{generalized vector} type, which is the union -of the four vector-like types. +of the five vector-like types. @deffn {Scheme Procedure} generalized-vector? obj @deffnx {C Function} scm_generalized_vector_p (obj) -Return @code{#t} if @var{obj} is a vector, string, +Return @code{#t} if @var{obj} is a vector, bytevector, string, bitvector, or uniform numeric vector. @end deffn @@ -1743,9 +1749,9 @@ 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. -Generalized vectors, such as strings, uniform numeric vectors, bit -vectors and ordinary vectors, are the special case of one dimensional -arrays. +Generalized vectors, such as strings, uniform numeric vectors, +bytevectors, bit vectors and ordinary vectors, are the special case of +one dimensional arrays. @menu * Array Syntax:: @@ -1828,6 +1834,16 @@ 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 @@ -2342,21 +2358,13 @@ 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, -also in the presence of non-local exits. To simplify this, reserving -and unreserving work like a dynwind context (@pxref{Dynamic Wind}): a -call to @code{scm_array_get_handle} can be thought of as beginning a -dynwind context and @code{scm_array_handle_release} as ending it. -When a non-local exit happens between these two calls, the array is -implicitely unreserved. - -That is, you need to properly pair reserving and unreserving in your -code, but you don't need to worry about non-local exits. - -These calls and other pairs of calls that establish dynwind contexts -need to be properly nested. If you begin a context prior to reserving -an array, you need to unreserve the array before ending the context. -Likewise, when reserving two or more arrays in a certain order, you -need to unreserve them in the opposite order. +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. diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi index e1db2a612..6e1a67ae1 100755 --- a/doc/ref/api-data.texi +++ b/doc/ref/api-data.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -45,6 +45,7 @@ For the documentation of such @dfn{compound} data types, see * Characters:: Single characters. * Character Sets:: Sets of characters. * Strings:: Sequences of characters. +* Bytevectors:: Sequences of bytes. * Regular Expressions:: Pattern matching and substitution. * Symbols:: Symbols. * Keywords:: Self-quoting, customizable display keywords. @@ -331,7 +332,7 @@ 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 explicitely insert a call to @code{inexact->exact} or to its C +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.) @@ -3746,6 +3747,445 @@ 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 +@node Bytevectors +@subsection Bytevectors + +@cindex bytevector +@cindex R6RS + +A @dfn{bytevector} is a raw bit string. The @code{(rnrs bytevector)} +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 of the +R6RS (@pxref{R6RS I/O Ports}). + +@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 Generalized Vectors:: Guile extension to the bytevector API. +@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}. +@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 {Scheme Procedure} bytevector-sint-ref bv index endianness size +@deffnx {C Function} scm_bytevector_uint_ref (bv, index, endianness, size) +@deffnx {C Function} scm_bytevector_sint_ref (bv, index, endianness, size) +Return the @var{size}-byte long unsigned (resp. 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 {Scheme Procedure} bytevector-sint-set! bv index value endianness size +@deffnx {C Function} scm_bytevector_uint_set_x (bv, index, value, endianness, size) +@deffnx {C Function} scm_bytevector_sint_set_x (bv, index, value, endianness, size) +Set the @var{size}-byte long unsigned (resp. 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} +accessors, for obvious reasons): + +@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 {Scheme Procedure} bytevector->sint-list bv endianness size +@deffnx {C Function} scm_bytevector_to_uint_list (bv, endianness, size) +@deffnx {C Function} scm_bytevector_to_sint_list (bv, endianness, size) +Return a list of unsigned (resp. 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 {Scheme Procedure} sint-list->bytevector lst endianness size +@deffnx {C Function} scm_uint_list_to_bytevector (lst, endianness, size) +@deffnx {C Function} scm_sint_list_to_bytevector (lst, endianness, size) +Return a new bytevector containing the unsigned (resp. 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@footnote{Guile +1.8 does @emph{not} support Unicode strings. Therefore, the procedures +described here assume that Guile strings are internally encoded +according to the current locale. For instance, if @code{$LC_CTYPE} is +@code{fr_FR.ISO-8859-1}, then @code{string->utf-8} @i{et al.} will +assume that Guile strings are Latin-1-encoded.}. + +@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 + +@deffn {Scheme Procedure} string->utf8 str +@deffnx {Scheme Procedure} string->utf16 str +@deffnx {Scheme Procedure} string->utf32 str +@deffnx {C Function} scm_string_to_utf8 (str) +@deffnx {C Function} scm_string_to_utf16 (str) +@deffnx {C Function} scm_string_to_utf32 (str) +Return a newly allocated bytevector that contains the UTF-8, UTF-16, or +UTF-32 (aka. UCS-4) encoding of @var{str}. +@end deffn + +@deffn {Scheme Procedure} utf8->string utf +@deffnx {Scheme Procedure} utf16->string utf +@deffnx {Scheme Procedure} utf32->string utf +@deffnx {C Function} scm_utf8_to_string (utf) +@deffnx {C Function} scm_utf16_to_string (utf) +@deffnx {C Function} scm_utf32_to_string (utf) +Return a newly allocated string that contains from the UTF-8-, UTF-16-, +or UTF-32-decoded contents of bytevector @var{utf}. +@end deffn + +@node Bytevectors as Generalized Vectors +@subsubsection Accessing Bytevectors with the Generalized Vector API + +As an extension to the R6RS, Guile allows bytevectors to be manipulated +with the @dfn{generalized vector} procedures (@pxref{Generalized +Vectors}). This also allows bytevectors to be accessed using the +generic @dfn{array} procedures (@pxref{Array Procedures}). When using +these APIs, bytes are accessed one at a time as 8-bit unsigned integers: + +@example +(define bv #vu8(0 1 2 3)) + +(generalized-vector? bv) +@result{} #t + +(generalized-vector-ref bv 2) +@result{} 2 + +(generalized-vector-set! bv 2 77) +(array-ref bv 2) +@result{} 77 + +(array-type bv) +@result{} vu8 +@end example + + @node Regular Expressions @subsection Regular Expressions @tpindex Regular expressions diff --git a/doc/ref/api-init.texi b/doc/ref/api-init.texi index 0e4e8b8b7..f9714c3b6 100644 --- a/doc/ref/api-init.texi +++ b/doc/ref/api-init.texi @@ -61,7 +61,7 @@ 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 explicitely left guile mode, of course). +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 diff --git a/doc/ref/api-io.texi b/doc/ref/api-io.texi index f69d07ede..b0b57412a 100644 --- a/doc/ref/api-io.texi +++ b/doc/ref/api-io.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -18,6 +18,7 @@ * Block Reading and Writing:: Reading and writing blocks of text. * Default Ports:: Defaults for input, output and errors. * Port Types:: Types of port and how to make them. +* R6RS I/O Ports:: The R6RS port API. * I/O Extensions:: Using and extending ports in C. @end menu @@ -1023,6 +1024,269 @@ documentation for @code{open-file} in @ref{File Ports}. @end deffn +@node R6RS I/O Ports +@subsection R6RS I/O Ports + +@cindex R6RS +@cindex R6RS ports + +The I/O port API of the @uref{http://www.r6rs.org/, Revised Report^6 on +the Algorithmic Language Scheme (R6RS)} is provided by the @code{(rnrs +io ports)} module. It provides features, such as binary I/O and Unicode +string I/O, that complement or refine Guile's historical port API +presented above (@pxref{Input and Output}). + +@c FIXME: Update description when implemented. +@emph{Note}: The implementation of this R6RS API is currently far from +complete, notably due to the lack of support for Unicode I/O and strings. + +@menu +* R6RS End-of-File:: The end-of-file object. +* R6RS Port Manipulation:: Manipulating R6RS ports. +* R6RS Binary Input:: Binary input. +* R6RS Binary Output:: Binary output. +@end menu + +@node R6RS End-of-File +@subsubsection The End-of-File Object + +@cindex EOF +@cindex end-of-file + +R5RS' @code{eof-object?} procedure is provided by the @code{(rnrs io +ports)} module: + +@deffn {Scheme Procedure} eof-object? obj +@deffnx {C Function} scm_eof_object_p (obj) +Return true if @var{obj} is the end-of-file (EOF) object. +@end deffn + +In addition, the following procedure is provided: + +@deffn {Scheme Procedure} eof-object +@deffnx {C Function} scm_eof_object () +Return the end-of-file (EOF) object. + +@lisp +(eof-object? (eof-object)) +@result{} #t +@end lisp +@end deffn + + +@node R6RS Port Manipulation +@subsubsection Port Manipulation + +The procedures listed below operate on any kind of R6RS I/O port. + +@deffn {Scheme Procedure} port-position port +If @var{port} supports it (see below), return the offset (an integer) +indicating where the next octet will be read from/written to in +@var{port}. If @var{port} does not support this operation, an error +condition is raised. + +This is similar to Guile's @code{seek} procedure with the +@code{SEEK_CUR} argument (@pxref{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 +If @var{port} supports it (see below), set the position where the next +octet will be read from/written to @var{port} to @var{offset} (an +integer). If @var{port} does not support this operation, an error +condition is raised. + +This is similar to Guile's @code{seek} procedure with the +@code{SEEK_SET} argument (@pxref{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 + + +@node R6RS Binary Input +@subsubsection Binary Input + +@cindex binary input + +R6RS binary input ports can be created with the procedures described +below. + +@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 + +@cindex custom binary input ports + +@deffn {Scheme Procedure} make-custom-binary-input-port id read! get-position set-position! close +@deffnx {C Function} scm_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 @var{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 @var{port-position}. + +Likewise, if @var{set-position!} is not @code{#f}, it should be a +one-argument procedure. When @var{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. + +Using a custom binary input port, the @code{open-bytevector-input-port} +procedure 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!)) + +(read (open-bytevector-input-port (string->utf8 "hello"))) +@result{} hello +@end lisp +@end deffn + +@cindex binary input +Binary input is achieved using the procedures below: + +@deffn {Scheme Procedure} get-u8 port +@deffnx {C Function} scm_get_u8 (port) +Return an octet read from @var{port}, a binary 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 + +@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 data are available or +and end-of-file is reached. Return either a new bytevector containing +the data read or the end-of-file object. +@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 + +@node R6RS Binary Output +@subsubsection Binary Output + +Binary output ports can be created with the procedures below. + +@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 + +@cindex custom binary output ports + +@deffn {Scheme Procedure} make-custom-binary-output-port id write! get-position set-position! close +@deffnx {C Function} scm_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} +(@pxref{R6RS Binary Input, @code{make-custom-binary-input-port}}). +@end deffn + +@cindex binary output +Writing to a binary output port can be done using the following +procedures: + +@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 I/O Extensions @subsection Using and Extending Ports in C @@ -1267,7 +1531,7 @@ implementations take care to avoid this problem. The procedure is set using -@deftypefun void scm_set_port_seek (scm_t_bits tc, off_t (*seek) (SCM port, off_t offset, int whence)) +@deftypefun void scm_set_port_seek (scm_t_bits tc, scm_t_off (*seek) (SCM port, scm_t_off offset, int whence)) @end deftypefun @item truncate @@ -1275,7 +1539,7 @@ Truncate the port data to be specified length. It can be assumed that the current state of @code{rw_active} is @code{SCM_PORT_NEITHER}. Set using -@deftypefun void scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM port, off_t length)) +@deftypefun void scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM port, scm_t_off length)) @end deftypefun @end table diff --git a/doc/ref/api-memory.texi b/doc/ref/api-memory.texi index 32d39982c..f492203f7 100644 --- a/doc/ref/api-memory.texi +++ b/doc/ref/api-memory.texi @@ -10,7 +10,7 @@ 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 explicitely. +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. @@ -201,7 +201,7 @@ below for a motivation. @deftypefn {C Function} void scm_gc_free (void *@var{mem}, size_t @var{size}, const char *@var{what}) Like @code{free}, but also call @code{scm_gc_unregister_collectable_memory}. -Note that you need to explicitely pass the @var{size} parameter. This +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 this frees us from tracking this value in the GC itself, which will keep diff --git a/doc/ref/api-procedures.texi b/doc/ref/api-procedures.texi index e3cf25823..8098b4ffb 100644 --- a/doc/ref/api-procedures.texi +++ b/doc/ref/api-procedures.texi @@ -162,18 +162,10 @@ appropriate module first, though: Returns @code{#t} iff @var{obj} is a compiled procedure. @end deffn -@deffn {Scheme Procedure} program-bytecode program -@deffnx {C Function} scm_program_bytecode (program) -Returns the object code associated with this program, as a -@code{u8vector}. -@end deffn - -@deffn {Scheme Procedure} program-base program -@deffnx {C Function} scm_program_base (program) -Returns the address in memory corresponding to the start of -@var{program}'s object code, as an integer. This is useful mostly when -you map the value of an instruction pointer from the VM to actual -instructions. +@deffn {Scheme Procedure} program-objcode program +@deffnx {C Function} scm_program_objcode (program) +Returns the object code associated with this program. @xref{Bytecode +and Objcode}, for more information. @end deffn @deffn {Scheme Procedure} program-objects program @@ -184,9 +176,9 @@ vector. @xref{VM Programs}, for more information. @deffn {Scheme Procedure} program-module program @deffnx {C Function} scm_program_module (program) -Returns the module that was current when this program was created. -Free variables in this program are looked up with respect to this -module. +Returns the module that was current when this program was created. Can +return @code{#f} if the compiler could determine that this information +was unnecessary. @end deffn @deffn {Scheme Procedure} program-external program @@ -250,9 +242,9 @@ REPL. The only tricky bit is that @var{extp} is a boolean, declaring whether the binding is heap-allocated or not. @xref{VM Concepts}, for more information. -Note that bindings information are stored in a program as part of its -metadata thunk, so including them in the generated object code does -not impose a runtime performance penalty. +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 diff --git a/doc/ref/api-undocumented.texi b/doc/ref/api-undocumented.texi index 826b4d38b..ef1df19c5 100644 --- a/doc/ref/api-undocumented.texi +++ b/doc/ref/api-undocumented.texi @@ -257,7 +257,7 @@ otherwise return the first argument. @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 explicitely creating an async object. +instead of explicitly creating an async object. @end deffn diff --git a/doc/ref/autoconf.texi b/doc/ref/autoconf.texi index 83686dada..ba5800fc0 100644 --- a/doc/ref/autoconf.texi +++ b/doc/ref/autoconf.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -49,7 +49,7 @@ checks. @cindex autoconf GNU Guile provides a @dfn{pkg-config} description file, installed as -@file{@var{prefix}/lib/pkgconfig/guile-1.8.pc}, which contains all the +@file{@var{prefix}/lib/pkgconfig/guile-2.0.pc}, which contains all the information necessary to compile and link C applications that use Guile. The @code{pkg-config} program is able to read this file and provide this information to application programmers; it can be obtained at @@ -59,8 +59,8 @@ The following command lines give respectively the C compilation and link flags needed to build Guile-using programs: @example -pkg-config guile-1.8 --cflags -pkg-config guile-1.8 --libs +pkg-config guile-2.0 --cflags +pkg-config guile-2.0 --libs @end example To ease use of pkg-config with Autoconf, pkg-config comes with a @@ -71,7 +71,7 @@ accordingly, or prints an error and exits if Guile was not found: @findex PKG_CHECK_MODULES @example -PKG_CHECK_MODULES([GUILE], [guile-1.8]) +PKG_CHECK_MODULES([GUILE], [guile-2.0]) @end example Guile comes with additional Autoconf macros providing more information, diff --git a/doc/ref/compiler.texi b/doc/ref/compiler.texi index 27d8f79c8..0aea4e754 100644 --- a/doc/ref/compiler.texi +++ b/doc/ref/compiler.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 2008 +@c Copyright (C) 2008, 2009 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -17,14 +17,16 @@ This section aims to pay attention to the small man behind the curtain. @xref{Read/Load/Eval/Compile}, if you're lost and you just wanted to -know how to compile your .scm file. +know how to compile your @code{.scm} file. @menu * Compiler Tower:: * The Scheme Compiler:: -* GHIL:: +* Tree-IL:: * GLIL:: -* Object Code:: +* Assembly:: +* Bytecode and Objcode:: +* Writing New High-Level Languages:: * Extending the Compiler:: @end menu @@ -52,7 +54,7 @@ They are registered with the @code{define-language} form. @deffn {Scheme Syntax} define-language @ name title version reader printer @ -[parser=#f] [read-file=#f] [compilers='()] [evaluator=#f] +[parser=#f] [compilers='()] [decompilers='()] [evaluator=#f] Define a language. This syntax defines a @code{#<language>} object, bound to @var{name} @@ -62,17 +64,14 @@ for Scheme: @example (define-language scheme - #:title "Guile Scheme" - #:version "0.5" - #:reader read - #:read-file read-file - #:compilers `((,ghil . ,compile-ghil)) - #:evaluator (lambda (x module) (primitive-eval x)) - #:printer write) + #:title "Guile Scheme" + #:version "0.5" + #:reader read + #:compilers `((tree-il . ,compile-tree-il)) + #:decompilers `((tree-il . ,decompile-tree-il)) + #:evaluator (lambda (x module) (primitive-eval x)) + #:printer write) @end example - -In this example, from @code{(language scheme spec)}, @code{read-file} -reads expressions from a port and wraps them in a @code{begin} block. @end deffn The interesting thing about having languages defined this way is that @@ -85,12 +84,12 @@ Guile Scheme interpreter 0.5 on Guile 1.9.0 Copyright (C) 2001-2008 Free Software Foundation, Inc. Enter `,help' for help. -scheme@@(guile-user)> ,language ghil -Guile High Intermediate Language (GHIL) interpreter 0.3 on Guile 1.9.0 +scheme@@(guile-user)> ,language tree-il +Tree Intermediate Language interpreter 1.0 on Guile 1.9.0 Copyright (C) 2001-2008 Free Software Foundation, Inc. Enter `,help' for help. -ghil@@(guile-user)> +tree-il@@(guile-user)> @end example Languages can be looked up by name, as they were above. @@ -128,17 +127,25 @@ The normal tower of languages when compiling Scheme goes like this: @itemize @item Scheme, which we know and love -@item Guile High Intermediate Language (GHIL) +@item Tree Intermediate Language (Tree-IL) @item Guile Low Intermediate Language (GLIL) -@item Object code +@item Assembly +@item Bytecode +@item Objcode @end itemize Object code may be serialized to disk directly, though it has a cookie -and version prepended to the front. But when compiling Scheme at -run time, you want a Scheme value, e.g. a compiled procedure. For this -reason, so as not to break the abstraction, Guile defines a fake -language, @code{value}. Compiling to @code{value} loads the object -code into a procedure, and wakes the sleeping giant. +and version prepended to the front. 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 object code into a procedure, and +wakes the sleeping giant. Perhaps this strangeness can be explained by example: @code{compile-file} defaults to compiling to object code, because it @@ -156,350 +163,287 @@ different worlds indefinitely, as shown by the following quine: @node The Scheme Compiler @subsection The Scheme Compiler -The job of the Scheme compiler is to expand all macros and to resolve -all symbols to lexical variables. Its target language, GHIL, is fairly -close to Scheme itself, so this process is not very complicated. - -The Scheme compiler is driven by a table of @dfn{translators}, -declared with the @code{define-scheme-translator} form, defined in the -module, @code{(language scheme compile-ghil)}. - -@deffn {Scheme Syntax} define-scheme-translator head clause1 clause2... -The best documentation of this form is probably an example. Here is -the translator for @code{if}: - -@example -(define-scheme-translator if - ;; (if TEST THEN [ELSE]) - ((,test ,then) - (make-ghil-if e l (retrans test) (retrans then) (retrans '(begin)))) - ((,test ,then ,else) - (make-ghil-if e l (retrans test) (retrans then) (retrans else)))) -@end example - -The match syntax is from the @code{pmatch} macro, defined in -@code{(system base pmatch)}. The result of a clause should be a valid -GHIL value. If no clause matches, a syntax error is signalled. - -In the body of the clauses, the following bindings are introduced: -@itemize -@item @code{e}, the current environment -@item @code{l}, the current source location (or @code{#f}) -@item @code{retrans}, a procedure that may be called to compile -subexpressions -@end itemize - -Note that translators are looked up by @emph{value}, not by name. That -is to say, the translator is keyed under the @emph{value} of -@code{if}, which normally prints as @code{#<primitive-builtin-macro! -if>}. -@end deffn - -Users can extend the compiler by defining new translators. -Additionally, some forms can be inlined directly to -instructions -- @xref{Inlined Scheme Instructions}, for a list. The -actual inliners are defined in @code{(language scheme inline)}: - -@deffn {Scheme Syntax} define-inline head arity1 result1 arity2 result2... -Defines an inliner for @code{head}. As in -@code{define-scheme-translator}, inliners are keyed by value and not -by name. - -Expressions are matched on their arities. For example: - -@example -(define-inline eq? - (x y) (eq? x y)) -@end example - -This inlines calls to the Scheme procedure, @code{eq?}, to the -instruction @code{eq?}. - -A more complicated example would be: - -@example -(define-inline + - () 0 - (x) x - (x y) (add x y) - (x y . rest) (add x (+ y . rest))) -@end example -@end deffn - -Compilers take two arguments, an expression and an environment, and -return two values as well: an expression in the target language, and -an environment suitable for the target language. The format of the -environment is language-dependent. - -For Scheme, an environment may be one of three things: +The job of the Scheme compiler is to expand all macros and all of +Scheme to its most primitive expressions. The definition of +``primitive'' is given by the inventory of constructs provided by +Tree-IL, the target language of the Scheme compiler: procedure +applications, conditionals, lexical references, etc. 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{} + #<<application> src: #f + proc: #<<toplevel-ref> src: #f name: +> + args: (#<<const> src: #f exp: 1> + #<<const> src: #f exp: 2>)> +@end lisp + +Or, since Tree-IL is so close to Scheme, it is often useful to expand +Scheme to Tree-IL, then translate back to Scheme. For that reason the +expander provides two interfaces. The former is equivalent to calling +@code{(sc-expand '(+ 1 2) 'c)}, where the @code{'c} is for +``compile''. With @code{'e} (the default), the result is translated +back to Scheme: + +@lisp +(sc-expand '(+ 1 2)) +@result{} (+ 1 2) +(sc-expand '(let ((x 10)) (* x x))) +@result{} (let ((x84 10)) (* x84 x84)) +@end lisp + +The second example shows that as part of its job, the macro expander +renames lexically-bound variables. The original names are preserved +when compiling to Tree-IL, but can't be represented in Scheme: a +lexical binding only has one name. It is for this reason that the +@emph{native} output of the expander is @emph{not} Scheme. There's too +much information we would lose if we translated to Scheme directly: +lexical variable names, source locations, and module hygiene. + +Note however that @code{sc-expand} does not have the same signature as +@code{compile-tree-il}. @code{compile-tree-il} is a small wrapper +around @code{sc-expand}, 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 may be one of two things: @itemize @item @code{#f}, in which case compilation is performed in the context -of the current module; -@item a module, which specifies the context of the compilation; or -@item a @dfn{compile environment}, which specifies lexical variables -as well. +of the current module; or +@item a module, which specifies the context of the compilation. @end itemize -The format of a compile environment for scheme is @code{(@var{module} -@var{lexicals} . @var{externals})}, though users are strongly -discouraged from constructing these environments themselves. Instead, -if you need this functionality -- as in GOOPS' dynamic method compiler --- capture an environment with @code{compile-time-environment}, then -pass that environment to @code{compile}. - -@deffn {Scheme Procedure} compile-time-environment -A special function known to the compiler that, when compiled, will -return a representation of the lexical environment in place at compile -time. Useful for supporting some forms of dynamic compilation. Returns -@code{#f} if called from the interpreter. -@end deffn - -@node GHIL -@subsection GHIL +@node Tree-IL +@subsection Tree-IL -Guile High Intermediate Language (GHIL) is a structured intermediate +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. -GHIL 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. Practically speaking, consider the -GHIL type, @code{<ghil-quote>}, which has fields named @code{env}, -@code{loc}, and @code{exp}. Instances of this type are records created -via @code{make-ghil-quote}, and whose fields are accessed as -@code{ghil-quote-env}, @code{ghil-quote-loc}, and -@code{ghil-quote-exp}. There is also a predicate, @code{ghil-quote?}. -@xref{Records}, for more information on records. - -Expressions of GHIL name their environments explicitly, and all -variables are referenced by identity in addition to by name. -@code{(language ghil)} defines a number of routines to deal explicitly -with variables and environments: - -@deftp {Scheme Variable} <ghil-toplevel-env> [table='()] -A toplevel environment. The @var{table} holds all toplevel variables -that have been resolved in this environment. -@end deftp -@deftp {Scheme Variable} <ghil-env> parent [table='()] [variables='()] -A lexical environment. @var{parent} will be the enclosing lexical -environment, or a toplevel environment. @var{table} holds an alist -mapping symbols to variables bound in this environment, while -@var{variables} holds a cumulative list of all variables ever defined -in this environment. - -Lexical environments correspond to procedures. Bindings introduced -e.g. by Scheme's @code{let} add to the bindings in a lexical -environment. An example of a case in which a variable might be in -@var{variables} but not in @var{table} would be a variable that is in -the same procedure, but is out of scope. -@end deftp -@deftp {Scheme Variable} <ghil-var> env name kind [index=#f] -A variable. @var{kind} is one of @code{argument}, @code{local}, -@code{external}, @code{toplevel}, @code{public}, or @code{private}; -see the procedures below for more information. @var{index} is used in -compilation. -@end deftp - -@deffn {Scheme Procedure} ghil-var-is-bound? env sym -Recursively look up a variable named @var{sym} in @var{env}, and -return it or @code{#f} if none is found. -@end deffn -@deffn {Scheme Procedure} ghil-var-for-ref! env sym -Recursively look up a variable named @var{sym} in @var{env}, and -return it. If the symbol was not bound, return a new toplevel -variable. -@end deffn -@deffn {Scheme Procedure} ghil-var-for-set! env sym -Like @code{ghil-var-for-ref!}, except that the returned variable will -be marked as @code{external}. @xref{Variables and the VM}. -@end deffn -@deffn {Scheme Procedure} ghil-var-define! toplevel-env sym -Return an existing or new toplevel variable named @var{sym}. -@var{toplevel-env} must be a toplevel environment. -@end deffn -@deffn {Scheme Procedure} ghil-var-at-module! env modname sym interface? -Return a variable that will be resolved at run-time with respect to a -specific module named @var{modname}. If @var{interface?} is true, the -variable will be of type @code{public}, otherwise @code{private}. -@end deffn -@deffn {Scheme Procedure} call-with-ghil-environment env syms func -Bind @var{syms} to fresh variables within a new lexical environment -whose parent is @var{env}, and call @var{func} as @code{(@var{func} -@var{new-env} @var{new-vars})}. -@end deffn -@deffn {Scheme Procedure} call-with-ghil-bindings env syms func -Like @code{call-with-ghil-environment}, except the existing -environment @var{env} is re-used. For that reason, @var{func} is -invoked as @code{(@var{func} @var{new-vars})} -@end deffn - -In the aforementioned @code{<ghil-quote>} type, the @var{env} slot -holds a pointer to the environment in which the expression occurs. The -@var{loc} slot holds source location information, so that errors -corresponding to this expression can be mapped back to the initial -expression in the higher-level language, e.g. Scheme. @xref{Compiled -Procedures}, for more information on source location objects. - -GHIL also has a declarative serialization format, which makes writing -and reading it a tractable problem for the human mind. Since all GHIL -language constructs contain @code{env} and @code{loc} pointers, they -are left out of the serialization. (Serializing @code{env} structures -would be difficult, as they are often circular.) What is left is the -type of expression, and the remaining slots defined in the expression -type. - -For example, an S-expression representation of the @code{<ghil-quote>} -expression would be: +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. Practically speaking, +consider the Tree-IL type, @code{<const>}, which has two fields, +@code{src} and @code{exp}. Instances of this type are records created +via @code{make-const}, and whose fields are accessed as +@code{const-src}, and @code{const-exp}. 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, an the S-expression representation +of @code{#<const src: #f exp: 3>} expression would be: @example -(quote 3) +(const 3) @end example -It's deceptively like Scheme. The general rule is, for a type defined -as @code{<ghil-@var{foo}> env loc @var{slot1} @var{slot2}...}, the -S-expression representation will be @code{(@var{foo} @var{slot1} -@var{slot2}...)}. Users may program with this format directly at the -REPL: +Users may program with this format directly at the REPL: @example -scheme@@(guile-user)> ,language ghil -Guile High Intermediate Language (GHIL) interpreter 0.3 on Guile 1.9.0 +scheme@@(guile-user)> ,language tree-il +Tree Intermediate Language interpreter 1.0 on Guile 1.9.0 Copyright (C) 2001-2008 Free Software Foundation, Inc. Enter `,help' for help. -ghil@@(guile-user)> (call (ref +) (quote 32) (quote 10)) +tree-il@@(guile-user)> (apply (primitive +) (const 32) (const 10)) @result{} 42 @end example -For convenience, some slots are serialized as rest arguments; those -are noted below. The other caveat is that variables are serialized as -their names only, and not their identities. - -@deftp {Scheme Variable} <ghil-void> env loc -The unspecified value. -@end deftp -@deftp {Scheme Variable} <ghil-quote> env loc exp -A quoted expression. - -Note that unlike in Scheme, there are no self-quoting expressions; all -constants must come from @code{quote} expressions. -@end deftp -@deftp {Scheme Variable} <ghil-quasiquote> env loc exp -A quasiquoted expression. The expression is treated as a constant, -except for embedded @code{unquote} and @code{unquote-splicing} forms. -@end deftp -@deftp {Scheme Variable} <ghil-unquote> env loc exp -Like Scheme's @code{unquote}; only valid within a quasiquote. -@end deftp -@deftp {Scheme Variable} <ghil-unquote-splicing> env loc exp -Like Scheme's @code{unquote-splicing}; only valid within a quasiquote. -@end deftp -@deftp {Scheme Variable} <ghil-ref> env loc var -A variable reference. Note that for purposes of serialization, -@var{var} is serialized as its name, as a symbol. -@end deftp -@deftp {Scheme Variable} <ghil-set> env loc var val -A variable mutation. @var{var} is serialized as a symbol. -@end deftp -@deftp {Scheme Variable} <ghil-define> env loc var val -A toplevel variable definition. See @code{ghil-var-define!}. -@end deftp -@deftp {Scheme Variable} <ghil-if> env loc test then else +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 applications of 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 (toplevel @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} <ghil-and> env loc . exps -Like Scheme's @code{and}. -@end deftp -@deftp {Scheme Variable} <ghil-or> env loc . exps -Like Scheme's @code{or}. +@deftp {Scheme Variable} <application> src proc args +@deftpx {External Representation} (apply @var{proc} . @var{args}) +A procedure call. @end deftp -@deftp {Scheme Variable} <ghil-begin> env loc . body +@deftp {Scheme Variable} <sequence> src exps +@deftpx {External Representation} (begin . @var{exps}) Like Scheme's @code{begin}. @end deftp -@deftp {Scheme Variable} <ghil-bind> env loc vars exprs . body -Like a deconstructed @code{let}: each element of @var{vars} will be -bound to the corresponding GHIL expression in @var{exprs}. - -Note that for purposes of the serialization format, @var{exprs} are -evaluated before the new bindings are added to the environment. For -@code{letrec} semantics, there also exists a @code{bindrec} parse -flavor. This is useful for writing GHIL at the REPL, but the -serializer does not currently have the cleverness needed to determine -whether a @code{<ghil-bind>} has @code{let} or @code{letrec} -semantics, and thus only serializes @code{<ghil-bind>} as @code{bind}. -@end deftp -@deftp {Scheme Variable} <ghil-mv-bind> env loc vars rest producer . body +@deftp {Scheme Variable} <lambda> src names vars meta body +@deftpx {External Representation} (lambda @var{names} @var{vars} @var{meta} @var{body}) +A closure. @var{names} is original binding form, as given in the +source code, which may be an improper list. @var{vars} are gensyms +corresponding to the @var{names}. @var{meta} is an association list of +properties. The actual @var{body} is a single Tree-IL expression. +@end deftp +@deftp {Scheme Variable} <let> src names vars vals exp +@deftpx {External Representation} (let @var{names} @var{vars} @var{vals} @var{exp}) +Lexical binding, like Scheme's @code{let}. @var{names} are the +original binding names, @var{vars} 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> src names vars vals exp +@deftpx {External Representation} (letrec @var{names} @var{vars} @var{vals} @var{exp}) +A version of @code{<let>} that creates recursive bindings, like +Scheme's @code{letrec}. +@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 vars exp body +@deftpx {External Representation} (let-values @var{names} @var{vars} @var{exp} @var{body}) Like Scheme's @code{receive} -- binds the values returned by -applying @code{producer}, which should be a thunk, to the -@code{lambda}-like bindings described by @var{vars} and @var{rest}. -@end deftp -@deftp {Scheme Variable} <ghil-lambda> env loc vars rest meta . body -A closure. @var{vars} is the argument list, serialized as a list of -symbols. @var{rest} is a boolean, which is @code{#t} iff the last -argument is a rest argument. @var{meta} is an association list of -properties. The actual @var{body} should be a list of GHIL -expressions. -@end deftp -@deftp {Scheme Variable} <ghil-call> env loc proc . args -A procedure call. -@end deftp -@deftp {Scheme Variable} <ghil-mv-call> env loc producer consumer -Like Scheme's @code{call-with-values}. -@end deftp -@deftp {Scheme Variable} <ghil-inline> env loc op . args -An inlined VM instruction. @var{op} should be the instruction name as -a symbol, and @var{args} should be its arguments, as GHIL expressions. -@end deftp -@deftp {Scheme Variable} <ghil-values> env loc . values -Like Scheme's @code{values}. -@end deftp -@deftp {Scheme Variable} <ghil-values*> env loc . values -@var{values} are as in the Scheme expression, @code{(apply values . -@var{vals})}. +evaluating @code{exp} to the @code{lambda}-like bindings described by +@var{vars}. That is to say, @var{vars} may be an improper list. + +@code{<let-values>} is an optimization of @code{<application>} of the +primitive, @code{call-with-values}. @end deftp -@deftp {Scheme Variable} <ghil-reified-env> env loc -Produces, at run-time, a reification of the environment at compile -time. Used in the implementation of Scheme's -@code{compile-time-environment}. +@deftp {Scheme Variable} <fix> src names vars vals body +@deftpx {External Representation} (fix @var{names} @var{vars} @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 -GHIL implements a compiler to GLIL that recursively traverses GHIL -expressions, writing out GLIL expressions into a linear list. The -compiler also keeps some state as to whether the current expression is -in tail context, and whether its value will be used in future -computations. This state allows the compiler not to emit code for -constant expressions that will not be used (e.g. docstrings), and to -perform tail calls when in tail position. +Tree-IL implements a compiler to GLIL that recursively traverses +Tree-IL expressions, writing out GLIL expressions into a linear list. +The compiler also keeps some state as to whether the current +expression is in tail context, and whether its value will be used in +future computations. This state allows the compiler not to emit code +for constant expressions that will not be used (e.g. docstrings), and +to perform tail calls when in tail position. -Just as the Scheme to GHIL compiler introduced new hidden state---the -environment---the GHIL to GLIL compiler introduces more state, the -stack. While not represented explicitly, the stack is present in the -compilation of each GHIL expression: compiling a GHIL expression -should leave the run-time value stack in the same state. For example, -if the intermediate value stack has two elements before evaluating an -@code{if} expression, it should have two elements after that -expression. +Most optimization, such as it currently is, is performed on Tree-IL +expressions as source-to-source transformations. There will be more +optimizations added in the future. Interested readers are encouraged to read the implementation in -@code{(language ghil compile-glil)} for more details. +@code{(language tree-il compile-glil)} for more details. @node GLIL @subsection GLIL Guile Low Intermediate Language (GLIL) is a structured intermediate -language whose expressions closely mirror the functionality of Guile's -VM instruction set. - -Its expression types are defined in @code{(language glil)}, and as -with GHIL, some of its fields parse as rest arguments. +language whose expressions more closely approximate Guile's VM +instruction set. Its expression types are defined in @code{(language +glil)}. -@deftp {Scheme Variable} <glil-program> nargs nrest nlocs nexts meta . body +@deftp {Scheme Variable} <glil-program> nargs nrest nlocs meta . body A unit of code that at run-time will correspond to a compiled -procedure. @var{nargs} @var{nrest} @var{nlocs}, and @var{nexts} -collectively define the program's arity; see @ref{Compiled -Procedures}, for more information. @var{meta} should be an alist of -properties, as in @code{<ghil-lambda>}. @var{body} is a list of GLIL +procedure. @var{nargs} @var{nrest} and @var{nlocs} collectively define +the program's arity; see @ref{Compiled Procedures}, for more +information. @var{meta} should be an alist of properties, as in +Tree-IL's @code{<lambda>}. @var{body} is an ordered list of GLIL expressions. @end deftp @deftp {Scheme Variable} <glil-bind> . vars @@ -534,37 +478,34 @@ offset within a VM program. @end deftp @deftp {Scheme Variable} <glil-source> loc Records source information for the preceding expression. @var{loc} -should be a vector, @code{#(@var{line} @var{column} @var{filename})}. +should be an association list of containing @code{line} @code{column}, +and @code{filename} keys, e.g. as returned by +@code{source-properties}. @end deftp @deftp {Scheme Variable} <glil-void> -Pushes the unspecified value on the stack. +Pushes ``the unspecified value'' on the stack. @end deftp @deftp {Scheme Variable} <glil-const> obj Pushes a constant value onto the stack. @var{obj} must be a number, -string, symbol, keyword, boolean, character, or a pair or vector or -list thereof, or the empty list. -@end deftp -@deftp {Scheme Variable} <glil-argument> op index -Accesses an argument on the stack. If @var{op} is @code{ref}, the -argument is pushed onto the stack; if it is @code{set}, the argument -is set from the top value on the stack, which is popped off. -@end deftp -@deftp {Scheme Variable} <glil-local> op index -Like @code{<glil-argument>}, but for local variables. @xref{Stack -Layout}, for more information. -@end deftp -@deftp {Scheme Variable} <glil-external> op depth index -Accesses a heap-allocated variable, addressed by @var{depth}, the nth -enclosing environment, and @var{index}, the variable's position within -the environment. @var{op} is @code{ref} or @code{set}. +string, symbol, keyword, boolean, character, uniform array, the empty +list, or a pair or vector of constants. +@end deftp +@deftp {Scheme Variable} <glil-lexical> local? boxed? op index +Accesses a lexically bound variable. If the variable is not +@var{local?} it is free. All variables may have @code{ref} and +@code{set} as their @var{op}. Boxed variables may also have the +@var{op}s @code{box}, @code{empty-box}, and @code{fix}, which +correspond in semantics to the VM instructions @code{box}, +@code{empty-box}, and @code{fix-closure}. @xref{Stack Layout}, for +more information. @end deftp @deftp {Scheme Variable} <glil-toplevel> op name Accesses a toplevel variable. @var{op} may be @code{ref}, @code{set}, or @code{define}. @end deftp @deftp {Scheme Variable} <glil-module> op mod name public? -Accesses a variable within a specific module. See -@code{ghil-var-at-module!}, for more information. +Accesses a variable within a specific module. See Tree-IL's +@code{<module-ref>}, for more information. @end deftp @deftp {Scheme Variable} <glil-label> label Creates a new label. @var{label} can be any Scheme value, and should @@ -599,7 +540,7 @@ Guile Lowlevel Intermediate Language (GLIL) interpreter 0.3 on Guile 1.9.0 Copyright (C) 2001-2008 Free Software Foundation, Inc. Enter `,help' for help. -glil@@(guile-user)> (program 0 0 0 0 () (const 3) (call return 0)) +glil@@(guile-user)> (program 0 0 0 () (const 3) (call return 1)) @result{} 3 @end example @@ -607,23 +548,146 @@ Just as in all of Guile's compilers, an environment is passed to the GLIL-to-object code compiler, and one is returned as well, along with the object code. -@node Object Code -@subsection Object Code +@node Assembly +@subsection Assembly + +Assembly is an S-expression-based, human-readable representation of +the actual bytecodes that will be emitted for the VM. As such, it is a +useful intermediate language both for compilation and for +decompilation. + +Besides the fact that it is not a record-based language, assembly +differs from GLIL in four main ways: + +@itemize +@item Labels have been resolved to byte offsets in the program. +@item Constants inside procedures have either been expressed as inline +instructions or cached in object arrays. +@item Procedures with metadata (source location information, liveness +extents, procedure names, generic properties, etc) have had their +metadata serialized out to thunks. +@item All expressions correspond directly to VM instructions -- i.e., +there is no @code{<glil-lexical>} which can be a ref or a set. +@end itemize + +Assembly is isomorphic to the bytecode that it compiles to. You can +compile to bytecode, then decompile back to assembly, and you have the +same assembly code. + +The general form of assembly instructions is the following: -Object code is the serialization of the raw instruction stream of a -program, ready for interpretation by the VM. Procedures related to -object code are defined in the @code{(system vm objcode)} module. +@lisp +(@var{inst} @var{arg} ...) +@end lisp + +The @var{inst} names a VM instruction, and its @var{arg}s will be +embedded in the instruction stream. The easiest way to see assembly is +to play around with it at the REPL, as can be seen in this annotated +example: + +@example +scheme@@(guile-user)> (compile '(lambda (x) (+ x x)) #:to 'assembly) +(load-program 0 0 0 + () ; Labels + 70 ; Length + #f ; Metadata + (make-false) + (make-false) ; object table for the returned lambda + (nop) + (nop) ; Alignment. Since assembly has already resolved its labels + (nop) ; to offsets, and programs must be 8-byte aligned since their + (nop) ; object code is mmap'd directly to structures, assembly + (nop) ; has to have the alignment embedded in it. + (nop) + (load-program + 1 + 0 + () + 8 + (load-program 0 0 0 () 21 #f + (load-symbol "x") ; Name and liveness extent for @code{x}. + (make-false) + (make-int8:0) ; Some instruction+arg combinations + (make-int8:0) ; have abbreviations. + (make-int8 6) + (list 0 5) + (list 0 1) + (make-eol) + (list 0 2) + (return)) + ; And here, the actual code. + (local-ref 0) + (local-ref 0) + (add) + (return) + (nop) + (nop)) + ; Return our new procedure. + (return)) +@end example + +Of course you can switch the REPL to assembly and enter in assembly +S-expressions directly, like with other languages, though it is more +difficult, given that the length fields have to be correct. + +@node Bytecode and Objcode +@subsection Bytecode and Objcode + +Finally, the raw bytes. There are actually two different ``languages'' +here, corresponding to two different ways to represent the bytes. + +``Bytecode'' represents code as uniform byte vectors, useful for +structuring and destructuring code on the Scheme level. Bytecode is +the next step down from assembly: + +@example +scheme@@(guile-user)> (compile '(+ 32 10) #:to 'assembly) +@result{} (load-program 0 0 0 () 6 #f + (make-int8 32) (make-int8 10) (add) (return)) +scheme@@(guile-user)> (compile '(+ 32 10) #:to 'bytecode) +@result{} #u8(0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 10 32 10 10 120 52) +@end example + +``Objcode'' is bytecode, but mapped directly to a C structure, +@code{struct scm_objcode}: + +@example +struct scm_objcode @{ + scm_t_uint8 nargs; + scm_t_uint8 nrest; + scm_t_uint16 nlocs; + scm_t_uint32 len; + scm_t_uint32 metalen; + scm_t_uint8 base[0]; +@}; +@end example + +As one might imagine, objcode imposes a minimum length on the +bytecode. Also, the multibyte fields are in native endianness, which +makes objcode (and bytecode) system-dependent. Indeed, in the short +example above, all but the last 6 bytes were the program's header. + +Objcode also has a couple of important efficiency hacks. First, +objcode may be mapped directly from disk, allowing compiled code to be +loaded quickly, often from the system's disk cache, and shared among +multiple processes. Secondly, objcode may be embedded in other +objcode, allowing procedures to have the text of other procedures +inlined into their bodies, without the need for separate allocation of +the code. Of course, the objcode object itself does need to be +allocated. + +Procedures related to objcode are defined in the @code{(system vm +objcode)} module. @deffn {Scheme Procedure} objcode? obj @deffnx {C Function} scm_objcode_p (obj) Returns @code{#f} iff @var{obj} is object code, @code{#f} otherwise. @end deffn -@deffn {Scheme Procedure} bytecode->objcode bytecode nlocs nexts -@deffnx {C Function} scm_bytecode_to_objcode (bytecode, nlocs, nexts) +@deffn {Scheme Procedure} bytecode->objcode bytecode +@deffnx {C Function} scm_bytecode_to_objcode (bytecode,) Makes a bytecode object from @var{bytecode}, which should be a -@code{u8vector}. @var{nlocs} and @var{nexts} denote the number of -stack and heap variables to reserve when this objcode is executed. +@code{u8vector}. @end deffn @deffn {Scheme Variable} load-objcode file @@ -631,21 +695,28 @@ stack and heap variables to reserve when this objcode is executed. 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. -On disk, object code has an eight-byte cookie prepended to it, so that -we will not execute arbitrary garbage. In addition, two more bytes are -reserved for @var{nlocs} and @var{nexts}. +On disk, object code has an sixteen-byte cookie prepended to it, to +prevent accidental loading of arbitrary garbage. +@end deffn + +@deffn {Scheme Variable} write-objcode objcode file +@deffnx {C Function} scm_write_objcode (objcode) +Write object code out to a file, prepending the eight-byte cookie. @end deffn @deffn {Scheme Variable} objcode->u8vector objcode @deffnx {C Function} scm_objcode_to_u8vector (objcode) -Copy object code out to a @code{u8vector} for analysis by Scheme. The -ten-byte header is included. +Copy object code out to a @code{u8vector} for analysis by Scheme. @end deffn -@deffn {Scheme Variable} objcode->program objcode [external='()] -@deffnx {C Function} scm_objcode_to_program (objcode, external) +The following procedure is actually in @code{(system vm program)}, but +we'll mention it here: + +@deffn {Scheme Variable} make-program objcode objtable [free-vars=#f] +@deffnx {C Function} scm_make_program (objcode, objtable, free_vars) Load up object code into a Scheme program. The resulting program will -be a thunk that captures closure variables from @var{external}. +have @var{objtable} as its object table, which should be a vector or +@code{#f}, and will capture the free variables from @var{free-vars}. @end deffn Object code from a file may be disassembled at the REPL via the @@ -659,12 +730,25 @@ respect to the compilation environment. Normally the environment propagates through the compiler transparently, but users may specify the compilation environment manually as well: -@deffn {Scheme Procedure} make-objcode-env module externals +@deffn {Scheme Procedure} make-objcode-env module free-vars Make an object code environment. @var{module} should be a Scheme -module, and @var{externals} should be a list of external variables. +module, and @var{free-vars} should be a vector of free variables. @code{#f} is also a valid object code environment. @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 @@ -687,12 +771,14 @@ procedure is called a certain number of times. The name of the game is a profiling-based harvest of the low-hanging fruit, running programs of interest under a system-level profiler and determining which improvements would give the most bang for the buck. -There are many well-known efficiency hacks in the literature: Dybvig's -letrec optimization, individual boxing of heap-allocated values (and -then store the boxes on the stack directory), optimized case-lambda -expressions, stack underflow and overflow handlers, etc. Highly -recommended papers: Dybvig's HOCS, Ghuloum's compiler paper. +It's really getting to the point though that native compilation is the +next step. The compiler also needs help at the top end, enhancing the Scheme that -it knows to also understand R6RS, and adding new high-level compilers: -Emacs Lisp, Lua, JavaScript... +it knows to also understand R6RS, 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, butq 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/intro.texi b/doc/ref/intro.texi index a31fe30f8..b0c4c1263 100644 --- a/doc/ref/intro.texi +++ b/doc/ref/intro.texi @@ -470,12 +470,12 @@ You can get the version number by invoking the command @example $ guile --version -Guile 1.4.1 -Copyright (c) 1995, 1996, 1997, 2000, 2006 Free Software Foundation -Guile may be distributed under the terms of the GNU General Public License; -certain other uses are permitted as well. For details, see the file -`COPYING', which is included in the Guile distribution. -There is no warranty, to the extent permitted by law. +Guile 1.9.0 +Copyright (c) 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation +Guile may be distributed under the terms of the GNU Lesser General +Public Licence. For details, see the files `COPYING.LESSER' and +`COPYING', which are included in the Guile distribution. There is no +warranty, to the extent permitted by law. @end example @item diff --git a/doc/ref/libguile-concepts.texi b/doc/ref/libguile-concepts.texi index 8979f0cd6..15d54f531 100644 --- a/doc/ref/libguile-concepts.texi +++ b/doc/ref/libguile-concepts.texi @@ -182,7 +182,7 @@ 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 explicitely deallocate it +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 diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi index cb19a7af8..2d64919a5 100644 --- a/doc/ref/posix.texi +++ b/doc/ref/posix.texi @@ -1909,10 +1909,6 @@ for termination, not stopping. 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). - -Guile always enables this flag where available, no matter what -@var{flags} are specified. This avoids spurious error returns in low -level operations. @end defvar The return value is a pair with information about the old handler as diff --git a/doc/ref/preface.texi b/doc/ref/preface.texi index d6de77440..7fa85811b 100644 --- a/doc/ref/preface.texi +++ b/doc/ref/preface.texi @@ -159,12 +159,12 @@ 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 2.1. See -the file @file{COPYING.LIB}. +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 2. See the file @file{COPYING}. +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 diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi index 1fa50b209..7c107e710 100644 --- a/doc/ref/srfi-modules.texi +++ b/doc/ref/srfi-modules.texi @@ -47,6 +47,7 @@ get the relevant SRFI documents from the SRFI home page * SRFI-61:: A more general `cond' clause * SRFI-69:: Basic hash tables. * SRFI-88:: Keyword objects. +* SRFI-98:: Accessing environment variables. @end menu @@ -3608,6 +3609,25 @@ Return the keyword object whose name is @var{str}. @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 @c srfi-modules.texi ends here diff --git a/doc/ref/vm.texi b/doc/ref/vm.texi index 042645200..59798d881 100644 --- a/doc/ref/vm.texi +++ b/doc/ref/vm.texi @@ -13,8 +13,8 @@ procedures can call each other as they please. The difference is that the compiler creates and interprets bytecode for a custom virtual machine, instead of interpreting the -S-expressions directly. Running compiled code is faster than running -interpreted code. +S-expressions directly. Loading and running compiled code is faster +than loading and running source code. The virtual machine that does the bytecode interpretation is a part of Guile itself. This section describes the nature of Guile's virtual @@ -111,7 +111,7 @@ The registers that a VM has are as follows: In other architectures, the instruction pointer is sometimes called the ``program counter'' (pc). This set of registers is pretty typical for stack machines; their exact meanings in the context of Guile's VM -is described in the next section. +are described in the next section. A virtual machine executes by loading a compiled procedure, and executing the object code associated with that procedure. Of course, @@ -119,19 +119,22 @@ that procedure may call other procedures, tail-call others, ad infinitum---indeed, within a guile whose modules have all been compiled to object code, one might never leave the virtual machine. -@c wingo: I wish the following were true, but currently we just use -@c the one engine. This kind of thing is possible tho. +@c wingo: The following is true, but I don't know in what context to +@c describe it. A documentation FIXME. @c A VM may have one of three engines: reckless, regular, or debugging. @c Reckless engine is fastest but dangerous. Regular engine is normally @c fail-safe and reasonably fast. Debugging engine is safest and @c functional but very slow. +@c (Actually we have just a regular and a debugging engine; normally +@c we use the latter, it's almost as fast as the ``regular'' engine.) + @node Stack Layout @subsection Stack Layout While not strictly necessary to understand how to work with the VM, it -is instructive and sometimes entertaining to consider the struture of +is instructive and sometimes entertaining to consider the structure of the VM stack. Logically speaking, a VM stack is composed of ``frames''. Each frame @@ -156,12 +159,11 @@ The structure of the fixed part of an application frame is as follows: @example Stack - | | <- fp + bp->nargs + bp->nlocs + 4 + | | <- fp + bp->nargs + bp->nlocs + 3 +------------------+ = SCM_FRAME_UPPER_ADDRESS (fp) | Return address | | MV return address| - | Dynamic link | - | External link | <- fp + bp->nargs + bp->nlocs + | Dynamic link | <- fp + bp->nargs + bp->nlocs | Local variable 1 | = SCM_FRAME_DATA_ADDRESS (fp) | Local variable 0 | <- fp + bp->nargs | Argument 1 | @@ -174,7 +176,7 @@ The structure of the fixed part of an application frame is as follows: In the above drawing, the stack grows upward. The intermediate values stored in the application of this frame are stored above @code{SCM_FRAME_UPPER_ADDRESS (fp)}. @code{bp} refers to the -@code{struct scm_program*} data associated with the program at +@code{struct scm_objcode} data associated with the program at @code{fp - 1}. @code{nargs} and @code{nlocs} are properties of the compiled procedure, which will be discussed later. @@ -198,25 +200,17 @@ values being returned. @item Dynamic link This is the @code{fp} in effect before this program was applied. In effect, this and the return address are the registers that are always -``saved''. - -@item External link -This field is a reference to the list of heap-allocated variables -associated with this frame. For a discussion of heap versus stack -allocation, @xref{Variables and the VM}. +``saved''. The dynamic link links the current frame to the previous +frame; computing a stack trace involves traversing these frames. @item Local variable @var{n} -Lambda-local variables that are allocated on the stack are all -allocated as part of the frame. This makes access to non-captured, -non-mutated variables very cheap. +Lambda-local variables that are all allocated as part of the frame. +This makes access to variables very cheap. @item Argument @var{n} The calling convention of the VM requires arguments of a function -application to be pushed on the stack, and here they are. Normally -references to arguments dispatch to these locations on the stack. -However if an argument has to be stored on the heap, it will be copied -from its initial value here onto a location in the heap, and -thereafter only referenced on the heap. +application to be pushed on the stack, and here they are. References +to arguments dispatch to these locations on the stack. @item Program This is the program being applied. For more information on how @@ -226,40 +220,51 @@ programs are implemented, @xref{VM Programs}. @node Variables and the VM @subsection Variables and the VM -Let's think about the following Scheme code as an example: +Consider the following Scheme code as an example: @example (define (foo a) (lambda (b) (list foo a b))) @end example -Within the lambda expression, "foo" is a top-level variable, "a" is a -lexically captured variable, and "b" is a local variable. - -That is to say: @code{b} may safely be allocated on the stack, as -there is no enclosed procedure that references it, nor is it ever -mutated. - -@code{a}, on the other hand, is referenced by an enclosed procedure, -that of the lambda. Thus it must be allocated on the heap, as it may -(and will) outlive the dynamic extent of the invocation of @code{foo}. - -@code{foo} is a toplevel variable, as mandated by Scheme's semantics: - -@example - (define proc (foo 'bar)) ; assuming prev. definition of @code{foo} - (define foo 42) ; redefinition - (proc 'baz) - @result{} (42 bar baz) -@end example - -Note that variables that are mutated (via @code{set!}) must be -allocated on the heap, even if they are local variables. This is -because any called subprocedure might capture the continuation, which -would need to capture locations instead of values. Thus perhaps -counterintuitively, what would seem ``closer to the metal'', viz -@code{set!}, actually forces heap allocation instead of stack -allocation. +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 allows one to +prove statements about functions. 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 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. + +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 @@ -276,6 +281,7 @@ You can pick apart these pieces with the accessors in @code{(system vm program)}. @xref{Compiled Procedures}, for a full API reference. @cindex object table +@cindex object array The object array of a compiled procedure, also known as the @dfn{object table}, holds all Scheme objects whose values are known not to change across invocations of the procedure: constant strings, @@ -293,38 +299,33 @@ instruction, which uses the object vector, and are almost as fast as local variable references. We can see how these concepts tie together by disassembling the -@code{foo} function to see what is going on: +@code{foo} function we defined earlier to see what is going on: @smallexample scheme@@(guile-user)> (define (foo a) (lambda (b) (list foo a b))) scheme@@(guile-user)> ,x foo Disassembly of #<program foo (a)>: -Bytecode: - - 0 (local-ref 0) ;; `a' (arg) - 2 (external-set 0) ;; `a' (arg) - 4 (object-ref 0) ;; #<program #(0 28 #f) (b)> - 6 (make-closure) at (unknown file):0:16 - 7 (return) + 0 (object-ref 1) ;; #<program b7e478b0 at <unknown port>:0:16 (b)> + 2 (local-ref 0) ;; `a' (arg) + 4 (vector 0 1) ;; 1 element + 7 (make-closure) + 8 (return) ---------------------------------------- -Disassembly of #<program #(0 28 #f) (b)>: +Disassembly of #<program b7e478b0 at <unknown port>:0:16 (b)>: -Bytecode: - - 0 (toplevel-ref 0) ;; `list' - 2 (toplevel-ref 1) ;; `foo' - 4 (external-ref 0) ;; (closure variable) - 6 (local-ref 0) ;; `b' (arg) - 8 (goto/args 3) at (unknown file):0:28 + 0 (toplevel-ref 1) ;; `foo' + 2 (free-ref 0) ;; (closure variable) + 4 (local-ref 0) ;; `b' (arg) + 6 (list 0 3) ;; 3 elements at (unknown file):0:28 + 9 (return) @end smallexample -At @code{ip} 0 and 2, we do the copy from argument to heap for -@code{a}. @code{Ip} 4 loads up the compiled lambda, and then at -@code{ip} 6 we make a closure---binding code (from the compiled -lambda) with data (the heap-allocated variables). Finally we return -the closure. +At @code{ip} 0, we load up the compiled lambda. @code{Ip} 2 and 4 +create the free variables vector, and @code{ip} 7 makes the +closure---binding code (from the compiled lambda) with data (the +free-variable vector). Finally we return the closure. The second stanza disassembles the compiled lambda. Toplevel variables are resolved relative to the module that was current when the @@ -336,13 +337,14 @@ Control Instructions}, for more details. Then we see a reference to an external variable, corresponding to @code{a}. The disassembler doesn't have enough information to give a name to that variable, so it just marks it as being a ``closure -variable''. Finally we see the reference to @code{b}, then a tail call -(@code{goto/args}) with three arguments. +variable''. Finally we see the reference to @code{b}, then the +@code{list} opcode, an inline implementation of the @code{list} scheme +routine. @node Instruction Set @subsection Instruction Set -There are about 100 instructions in Guile's virtual machine. These +There are 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. @@ -365,7 +367,8 @@ their own test-and-branch instructions: @end example In addition, some Scheme primitives have their own inline -implementations, e.g. @code{cons}. +implementations, e.g. @code{cons}, and @code{list}, as we saw in the +previous section. So Guile's instruction set is a @emph{complete} instruction set, in that it provides the instructions that are suited to the problem, and @@ -381,16 +384,22 @@ instructions. More instructions may be added over time. * Miscellaneous Instructions:: * Inlined Scheme Instructions:: * Inlined Mathematical Instructions:: +* Inlined Bytevector Instructions:: @end menu @node Environment Control Instructions @subsubsection Environment Control Instructions These instructions access and mutate the environment of a compiled -procedure---the local bindings, the ``external'' bindings, and the +procedure---the local bindings, the free (captured) bindings, and the toplevel bindings. +Some of these instructions have @code{long-} variants, the difference +being that they take 16-bit arguments, encoded in big-endianness, +instead of the normal 8-bit range. + @deffn Instruction local-ref index +@deffnx Instruction long-local-ref index Push onto the stack the value of the local variable located at @var{index} within the current stack frame. @@ -400,34 +409,65 @@ arguments. @end deffn @deffn Instruction local-set index +@deffnx Instruction long-local-ref index Pop the Scheme object located on top of the stack and make it the new value of the local variable located at @var{index} within the current stack frame. @end deffn -@deffn Instruction external-ref index -Push the value of the closure variable located at position -@var{index} within the program's list of external variables. +@deffn Instruction free-ref index +Push the value of the captured variable located at position +@var{index} within the program's vector of captured variables. @end deffn -@deffn Instruction external-set index -Pop the Scheme object located on top of the stack and make it the new -value of the closure variable located at @var{index} within the -program's list of external variables. +@deffn Instruction free-boxed-ref index +@deffnx Instruction free-boxed-set index +Get or set a boxed free variable. Note that there is no free-set +instruction, as variables that are @code{set!} must be boxed. + +These instructions assume that the value at position @var{index} in +the free variables vector is a variable. @end deffn -The external variable lookup algorithm should probably be made more -efficient in the future via addressing by frame and index. Currently, -external variables are all consed onto a list, which results in O(N) -lookup time. +@deffn Instruction make-closure +Pop a vector and a program object off the stack, in that order, and +push a new program object with the given free variables vector. The +new program object shares state with the original program. -@deffn Instruction externals -Pushes the current list of external variables onto the stack. This -instruction is used in the implementation of -@code{compile-time-environment}. @xref{The Scheme Compiler}. +At the time of this writing, the space overhead of closures is 4 words +per closure. +@end deffn + +@deffn Instruction fix-closure index +Pop a vector off the stack, and set it as the @var{index}th local +variable's free variable vector. The @var{index}th local variable is +assumed to be a procedure. + +This instruction is part of a hack for allocating mutually recursive +procedures. The hack is to first perform a @code{local-set} for all of +the recursive procedures, then fix up the procedures' free variable +bindings in place. This allows most @code{letrec}-bound procedures to +be allocated unboxed on the stack. + +One could of course do a @code{local-ref}, then @code{make-closure}, +then @code{local-set}, but this macroinstruction helps to speed up the +common case. +@end deffn + +@deffn Instruction box index +Pop a value off the stack, and set the @var{index}nth local variable +to a box containing that value. A shortcut for @code{make-variable} +then @code{local-set}, used when binding boxed variables. +@end deffn + +@deffn Instruction empty-box index +Set the @var{indext}h local variable to a box containing a variable +whose value is unbound. Used when compiling some @code{letrec} +expressions. @end deffn @deffn Instruction toplevel-ref index +@deffnx Instruction long-toplevel-ref index Push the value of the toplevel binding whose location is stored in at position @var{index} in the object table. @@ -440,11 +480,11 @@ created. Alternately, the lookup may be performed relative to a particular module, determined at compile-time (e.g. via @code{@@} or @code{@@@@}). In that case, the cell in the object table holds a list: -@code{(@var{modname} @var{sym} @var{interface?})}. The symbol -@var{sym} will be looked up in the module named @var{modname} (a list -of symbols). The lookup will be performed against the module's public -interface, unless @var{interface?} is @code{#f}, which it is for -example when compiling @code{@@@@}. +@code{(@var{modname} @var{sym} @var{public?})}. The symbol @var{sym} +will be looked up in the module named @var{modname} (a list of +symbols). The lookup will be performed against the module's public +interface, unless @var{public?} is @code{#f}, which it is for example +when compiling @code{@@@@}. In any case, if the symbol is unbound, an error is signalled. Otherwise the initial form is replaced with the looked-up variable, an @@ -455,13 +495,20 @@ variable has been successfully resolved. This instruction pushes the value of the variable onto the stack. @end deffn -@deffn Instruction toplevel-ref index +@deffn Instruction toplevel-set index +@deffnx Instruction long-toplevel-set index Pop a value off the stack, and set it as the value of the toplevel variable stored at @var{index} in the object table. If the variable has not yet been looked up, we do the lookup as in @code{toplevel-ref}. @end deffn +@deffn Instruction define +Pop a symbol and a value from the stack, in that order. Look up its +binding in the current toplevel environment, creating the binding if +necessary. Set the variable to the value. +@end deffn + @deffn Instruction link-now Pop a value, @var{x}, from the stack. Look up the binding for @var{x}, according to the rules for @code{toplevel-ref}, and push that variable @@ -481,8 +528,15 @@ Pop off two objects from the stack, a variable and a value, and set the variable to the value. @end deffn +@deffn Instruction make-variable +Replace the top object on the stack with a variable containing it. +Used in some circumstances when compiling @code{letrec} expressions. +@end deffn + @deffn Instruction object-ref n -Push @var{n}th value from the current program's object vector. +@deffnx Instruction long-object-ref n +Push @var{n}th value from the current program's object vector. The +``long'' variant has a 16-bit index instead of an 8-bit index. @end deffn @node Branch Instructions @@ -502,7 +556,10 @@ the one to which the instruction pointer points). @end itemize Note that the offset passed to the instruction is encoded on two 8-bit -integers which are then combined by the VM as one 16-bit integer. +integers which are then combined by the VM as one 16-bit integer. Note +also that jump targets in Guile are aligned on 8-byte boundaries, and +that the offset refers to the @var{n}th 8-byte boundary, effectively +giving Guile a 19-bit relative address space. @deffn Instruction br offset Jump to @var{offset}. @@ -546,81 +603,47 @@ the instruction pointer to the next VM instruction. All of these loading instructions have a @code{length} parameter, indicating the size of the embedded data, in bytes. The length itself -may be encoded in 1, 2, or 4 bytes. +is encoded in 3 bytes. -@deffn Instruction load-integer length -@deffnx Instruction load-unsigned-integer length -Load a 32-bit integer (respectively unsigned integer) from the -instruction stream. -@end deffn @deffn Instruction load-number length Load an arbitrary number from the instruction stream. The number is embedded in the stream as a string. @end deffn @deffn Instruction load-string length -Load a string from the instruction stream. +Load a string from the instruction stream. The string is assumed to be +encoded in the ``latin1'' locale. @end deffn -@deffn Instruction load-symbol length -Load a symbol from the instruction stream. +@deffn Instruction load-wide-string length +Load a UTF-32 string from the instruction stream. @var{length} is the +length in bytes, not in codepoints @end deffn -@deffn Instruction load-keyword length -Load a keyword from the instruction stream. +@deffn Instruction load-symbol length +Load a symbol from the instruction stream. The symbol is assumed to be +encoded in the ``latin1'' locale. Symbols backed by wide strings may +be loaded via @code{load-wide-string} then @code{make-symbol}. @end deffn - -@deffn Instruction define length -Load a symbol from the instruction stream, and look up its binding in -the current toplevel environment, creating the binding if necessary. -Push the variable corresponding to the binding. +@deffn Instruction load-array length +Load a uniform array from the instruction stream. The shape and type +of the array are popped off the stack, in that order. @end deffn -@deffn Instruction load-program length +@deffn Instruction load-program Load bytecode from the instruction stream, and push a compiled -procedure. This instruction pops the following values from the stack: - -@itemize -@item Optionally, a thunk, which when called should return metadata -associated with this program---for example its name, the names of its -arguments, its documentation string, debugging information, etc. - -Normally, this thunk its itself a compiled procedure (with no -metadata). Metadata is represented this way so that the initial load -of a procedure is fast: the VM just mmap's the thunk and goes. The -symbols and pairs associated with the metadata are only created if the -user asks for them. - -For information on the format of the thunk's return value, -@xref{Compiled Procedures}. -@item Optionally, the program's object table, as a vector. - -A program that does not reference toplevel bindings and does not use -@code{object-ref} does not need an object table. -@item Finally, either one immediate integer or four immediate integers -representing the arity of the program. - -In the four-fixnum case, the values are respectively the number of -arguments taken by the function (@var{nargs}), the number of @dfn{rest -arguments} (@var{nrest}, 0 or 1), the number of local variables -(@var{nlocs}) and the number of external variables (@var{nexts}) -(@pxref{Environment Control Instructions}). - -The common single-fixnum case represents all of these values within a -16-bit bitmask. -@end itemize +procedure. -The resulting compiled procedure will not have any ``external'' -variables captured, so it will be loaded only once but may be used -many times to create closures. -@end deffn +This instruction pops one value from the stack: the program's object +table, as a vector, or @code{#f} in the case that the program has no +object table. A program that does not reference toplevel bindings and +does not use @code{object-ref} does not need an object table. -Finally, while this instruction is not strictly a ``loading'' -instruction, it's useful to wind up the @code{load-program} discussion -here: +This instruction is unlike the rest of the loading instructions, +because instead of parsing its data, it directly maps the instruction +stream onto a C structure, @code{struct scm_objcode}. @xref{Bytecode +and Objcode}, for more information. -@deffn Instruction make-closure -Pop the program object from the stack, capture the current set of -``external'' variables, and assign those external variables to a copy -of the program. Push the new program object, which shares state with -the original program. Also captures the current module. +The resulting compiled procedure will not have any free variables +captured, so it may be loaded only once but used many times to create +closures. @end deffn @node Procedural Instructions @@ -640,22 +663,24 @@ set to the returned value. @deffn Instruction call nargs Call the procedure located at @code{sp[-nargs]} with the @var{nargs} -arguments located from @code{sp[0]} to @code{sp[-nargs + 1]}. +arguments located from @code{sp[-nargs + 1]} to @code{sp[0]}. + +For compiled procedures, this instruction sets up a new stack frame, +as described in @ref{Stack Layout}, and then dispatches to the first +instruction in the called procedure, relying on the called procedure +to return one value to the newly-created continuation. Because the new +frame pointer will point to sp[-nargs + 1], the arguments don't have +to be shuffled around -- they are already in place. For non-compiled procedures (continuations, primitives, and interpreted procedures), @code{call} will pop the procedure and arguments off the stack, and push the result of calling @code{scm_apply}. - -For compiled procedures, this instruction sets up a new stack frame, -as described in @ref{Stack Layout}, and then dispatches to the first -instruction in the called procedure, relying on the called procedure -to return one value to the newly-created continuation. @end deffn @deffn Instruction goto/args nargs Like @code{call}, but reusing the current continuation. This -instruction implements tail calling as required by RnRS. +instruction implements tail calls as required by RnRS. For compiled procedures, that means that @code{goto/args} reuses the current frame instead of building a new one. The @code{goto/*} @@ -726,14 +751,14 @@ values. This is an optimization for the common @code{(apply values @deffn Instruction truncate-values nbinds nrest Used in multiple-value continuations, this instruction takes the -values that are on the stack (including the number-of-value marker) +values that are on the stack (including the number-of-values marker) and truncates them for a binding construct. For example, a call to @code{(receive (x y . z) (foo) ...)} would, logically speaking, pop off the values returned from @code{(foo)} and push them as three values, corresponding to @code{x}, @code{y}, and @code{z}. In that case, @var{nbinds} would be 3, and @var{nrest} would -be 1 (to indicate that one of the bindings was a rest arguments). +be 1 (to indicate that one of the bindings was a rest argument). Signals an error if there is an insufficient number of values. @end deffn @@ -760,6 +785,17 @@ Push the immediate value @code{1} onto the stack. Push @var{value}, a 16-bit integer, onto the stack. @end deffn +@deffn Instruction make-uint64 value +Push @var{value}, an unsigned 64-bit integer, onto the stack. The +value is encoded in 8 bytes, most significant byte first (big-endian). +@end deffn + +@deffn Instruction make-int64 value +Push @var{value}, a signed 64-bit integer, onto the stack. The value +is encoded in 8 bytes, most significant byte first (big-endian), in +twos-complement arithmetic. +@end deffn + @deffn Instruction make-false Push @code{#f} onto the stack. @end deffn @@ -776,15 +812,30 @@ Push @code{'()} onto the stack. Push @var{value}, an 8-bit character, onto the stack. @end deffn +@deffn Instruction make-char32 value +Push @var{value}, an 32-bit character, onto the stack. The value is +encoded in big-endian order. +@end deffn + +@deffn Instruction make-symbol +Pops a string off the stack, and pushes a symbol. +@end deffn + +@deffn Instruction make-keyword value +Pops a symbol off the stack, and pushes a keyword. +@end deffn + @deffn Instruction list n Pops off the top @var{n} values off of the stack, consing them up into a list, then pushes that list on the stack. What was the topmost value -will be the last element in the list. +will be the last element in the list. @var{n} is a two-byte value, +most significant byte first. @end deffn @deffn Instruction vector n Create and fill a vector with the top @var{n} values from the stack, -popping off those values and pushing on the resulting vector. +popping off those values and pushing on the resulting vector. @var{n} +is a two-byte value, like in @code{vector}. @end deffn @deffn Instruction mark @@ -817,7 +868,8 @@ pushes its elements on the stack. @subsubsection Miscellaneous Instructions @deffn Instruction nop -Does nothing! +Does nothing! Used for padding other instructions to certain +alignments. @end deffn @deffn Instruction halt @@ -850,9 +902,8 @@ Pushes ``the unspecified value'' onto the stack. @subsubsection Inlined Scheme Instructions The Scheme compiler can recognize the application of standard Scheme -procedures, or unbound variables that look like they are bound to -standard Scheme procedures. It tries to inline these small operations -to avoid the overhead of creating new stack frames. +procedures. It tries to inline these small operations to avoid the +overhead of creating new stack frames. Since most of these operations are historically implemented as C primitives, not inlining them would entail constantly calling out from @@ -876,14 +927,16 @@ stream. @deffnx Instruction eqv? x y @deffnx Instruction equal? x y @deffnx Instruction pair? x y -@deffnx Instruction list? x y +@deffnx Instruction list? x @deffnx Instruction set-car! pair x @deffnx Instruction set-cdr! pair x @deffnx Instruction slot-ref struct n @deffnx Instruction slot-set struct n x -@deffnx Instruction cons x +@deffnx Instruction cons x y @deffnx Instruction car x @deffnx Instruction cdr x +@deffnx Instruction vector-ref x y +@deffnx Instruction vector-set x n y Inlined implementations of their Scheme equivalents. @end deffn @@ -904,7 +957,9 @@ As in the previous section, the definitions below show stack parameters instead of instruction stream parameters. @deffn Instruction add x y +@deffnx Instruction add1 x @deffnx Instruction sub x y +@deffnx Instruction sub1 x @deffnx Instruction mul x y @deffnx Instruction div x y @deffnx Instruction quo x y @@ -917,3 +972,58 @@ parameters instead of instruction stream parameters. @deffnx Instruction ge? x y Inlined implementations of the corresponding mathematical operations. @end deffn + +@node Inlined Bytevector Instructions +@subsubsection Inlined Bytevector 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. + +As in the previous section, the definitions below show stack +parameters instead of instruction stream parameters. + +The multibyte formats (@code{u16}, @code{f64}, etc) take an extra +endianness argument. Only aligned native accesses are currently +fast-pathed in Guile's VM. + +@deffn Instruction bv-u8-ref bv n +@deffnx Instruction bv-s8-ref bv n +@deffnx Instruction bv-u16-native-ref bv n +@deffnx Instruction bv-s16-native-ref bv n +@deffnx Instruction bv-u32-native-ref bv n +@deffnx Instruction bv-s32-native-ref bv n +@deffnx Instruction bv-u64-native-ref bv n +@deffnx Instruction bv-s64-native-ref bv n +@deffnx Instruction bv-f32-native-ref bv n +@deffnx Instruction bv-f64-native-ref bv n +@deffnx Instruction bv-u16-ref bv n endianness +@deffnx Instruction bv-s16-ref bv n endianness +@deffnx Instruction bv-u32-ref bv n endianness +@deffnx Instruction bv-s32-ref bv n endianness +@deffnx Instruction bv-u64-ref bv n endianness +@deffnx Instruction bv-s64-ref bv n endianness +@deffnx Instruction bv-f32-ref bv n endianness +@deffnx Instruction bv-f64-ref bv n endianness +@deffnx Instruction bv-u8-set bv n val +@deffnx Instruction bv-s8-set bv n val +@deffnx Instruction bv-u16-native-set bv n val +@deffnx Instruction bv-s16-native-set bv n val +@deffnx Instruction bv-u32-native-set bv n val +@deffnx Instruction bv-s32-native-set bv n val +@deffnx Instruction bv-u64-native-set bv n val +@deffnx Instruction bv-s64-native-set bv n val +@deffnx Instruction bv-f32-native-set bv n val +@deffnx Instruction bv-f64-native-set bv n val +@deffnx Instruction bv-u16-set bv n val endianness +@deffnx Instruction bv-s16-set bv n val endianness +@deffnx Instruction bv-u32-set bv n val endianness +@deffnx Instruction bv-s32-set bv n val endianness +@deffnx Instruction bv-u64-set bv n val endianness +@deffnx Instruction bv-s64-set bv n val endianness +@deffnx Instruction bv-f32-set bv n val endianness +@deffnx Instruction bv-f64-set bv n val endianness +Inlined implementations of the corresponding bytevector operations. +@end deffn |