commit 6b41fabf449cad75d83e9c360e63c753445750a9
parent 8b7448513049c48bad659906b321f76376ab192c
Author: Andres Navarro <canavarro82@gmail.com>
Date: Sun, 5 Jun 2011 01:51:31 -0300
Merged split ground
Diffstat:
107 files changed, 10855 insertions(+), 1267 deletions(-)
diff --git a/.hgignore b/.hgignore
@@ -1,4 +1,5 @@
syntax: glob
*.o
+*.a
klisp
diff --git a/COPYRIGHT b/COPYRIGHT
@@ -12,6 +12,7 @@ under the MIT license.
klisp Parts: Copyright (C) 2011 Andres Navarro.
Lua Parts: Copyright (C) 1994-2010 Lua.org, PUC-Rio.
IMath Parts: Copyright (C) 2002-2007 Michael J. Fromberger.
+srfi-78: Copyright (C) 2005-2006 Sebastian Egner.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/manual/html/A-Sample-Applicative-Description.html b/manual/html/A-Sample-Applicative-Description.html
@@ -0,0 +1,81 @@
+<html lang="en">
+<head>
+<title>A Sample Applicative Description - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Format-of-Descriptions.html#Format-of-Descriptions" title="Format of Descriptions">
+<link rel="prev" href="Format-of-Descriptions.html#Format-of-Descriptions" title="Format of Descriptions">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="A-Sample-Applicative-Description"></a>
+<p>
+Previous: <a rel="previous" accesskey="p" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>,
+Up: <a rel="up" accesskey="u" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>
+<hr>
+</div>
+
+<h5 class="subsubsection">1.3.5.1 A Sample Applicative Description</h5>
+
+<p><a name="index-applicative-descriptions-8"></a><a name="index-operative-descriptions-9"></a><a name="index-object-descriptions-10"></a>
+ In an applicative description, the name of the applicative being
+described appears first. It is followed on the same line by an
+applicative combination that includes the name of the applicative and
+the arguments, as would appear in a program. The names used for the
+arguments are also used in the body of the description.
+
+ <p>Here is a description of an imaginary applicative <code>foo</code>:
+
+<div class="defun">
+— Applicative: <b>foo</b> (<var>foo integer1 integer2 . rest</var>)<var><a name="index-foo-11"></a></var><br>
+<blockquote><p> The applicative <code>foo</code> subtracts <var>integer1</var> from <var>integer2</var>,
+then adds all the rest of the arguments to the result.
+
+ <pre class="example"> (foo 1 5 3 9)
+ ⇒ 16
+</pre>
+ <p>More generally,
+
+ <pre class="example"> (foo <var>w</var> <var>x</var> <var>y</var>...)
+ ==
+ (+ (- <var>x</var> <var>w</var>) <var>y</var>...)
+</pre>
+ </blockquote></div>
+
+ <p>Any parameter whose name contains the name of a type (e.g.,
+<var>integer</var>, <var>integer1</var> or <var>continuation</var>) is expected to be of that
+type. A plural of a type (such as <var>numbers</var>) often means a list of
+objects of that type. Parameters named <var>object</var> may be of any
+type. Additionally parameters named <var>k</var>, or <var>kn</var> (for any
+value of <var>n</var>), should be exact, non-negative integers.
+<!-- TODO add xref types of objects -->
+(XXX Types of Lisp Object XXX, for a list of Kernel object types.)
+Parameters with other sorts of names are
+discussed specifically in the description of the combiner. In some
+sections, features common to parameters of several combiners are
+described at the beginning.
+
+<!-- TODO xref to ptree -->
+<!-- TODO clean this up a little -->
+ <p>Operative descriptions have the same format, but the word
+`Applicative' is replaced by `Operative', and `Argument' is replaced
+by `Operand'. Also Operatives always have an environment parameter
+(that can be #ignore or a symbol).
+
+ </body></html>
+
diff --git a/manual/html/Acknowledgements.html b/manual/html/Acknowledgements.html
@@ -0,0 +1,44 @@
+<html lang="en">
+<head>
+<title>Acknowledgements - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Introduction.html#Introduction" title="Introduction">
+<link rel="prev" href="Conventions.html#Conventions" title="Conventions">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Acknowledgements"></a>
+<p>
+Previous: <a rel="previous" accesskey="p" href="Conventions.html#Conventions">Conventions</a>,
+Up: <a rel="up" accesskey="u" href="Introduction.html#Introduction">Introduction</a>
+<hr>
+</div>
+
+<h3 class="section">1.4 Acknowledgements</h3>
+
+<p>This manual was written by Andres Navarro.
+
+ <p>The structure and some text for this introductory section were
+borrowed from the Elisp Manual by the Free Sofware Foundation. This
+manual also borrows freely from both the Kernel Report and the Scheme
+Reports.
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Booleans.html b/manual/html/Booleans.html
@@ -0,0 +1,102 @@
+<html lang="en">
+<head>
+<title>Booleans - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Introduction.html#Introduction" title="Introduction">
+<link rel="next" href="Equivalence.html#Equivalence" title="Equivalence">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Booleans"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Equivalence.html#Equivalence">Equivalence</a>,
+Previous: <a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">2 Booleans</h2>
+
+<p><a name="index-booleans-12"></a>
+ The boolean data type consists of two values, which are called true
+and false, and have respectively external representations <code>#t</code>
+and <code>#f</code>. There are no possible mutations of either of these two
+<!-- add encapsulated cross ref -->
+values, and the boolean type is encapsulated.
+
+<div class="defun">
+— Applicative: <b>boolean?</b> (<var>boolean? . objects</var>)<var><a name="index-boolean_003f-13"></a></var><br>
+<blockquote><p> The primitive type predicate for type boolean. <code>boolean?</code>
+returns true iff all the objects in <code>objects</code> are of type boolean.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>not?</b> (<var>not? boolean</var>)<var><a name="index-not_003f-14"></a></var><br>
+<blockquote><p> Applicative <code>not?</code> is a predicate that returns the logical
+negation of its argument.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>and?</b> (<var>and? . booleans</var>)<var><a name="index-and_003f-15"></a></var><br>
+<blockquote><p> Applicative <code>and?</code> is a predicate that returns true unless one
+or more of its arguments are false.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>or?</b> (<var>or? . booleans</var>)<var><a name="index-or_003f-16"></a></var><br>
+<blockquote><p> Applicative <code>or?</code> is a predicate that returns false unless one
+or more of its arguments are true.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$and?</b> (<var>$and? . <list></var>)<var><a name="index-g_t_0024and_003f-17"></a></var><br>
+<blockquote><p> The <code>$and?</code> operative performs a “short-circuit and” of its
+operands. It evaluates them from left to right, until either an
+operand evaluates to false, or the end of the list is reached. If the
+end of the list is reached (which is immediate if <code><list></code> is
+<code>nil</code>), the operative returns true. If an operand evaluates to
+false, no further operand evaluations are performed, and the operative
+returns false. If <code><list></code> is acyclic, and the last operand is
+<!-- TODO cross ref tail-contect -->
+evaluated, it is evaluated as a tail context. If <code><list></code> is
+cyclic, an unbounded number of operand evaluations may be
+performed. If any of the operands evaluates to a non-boolean value, an
+error is signaled (even if it's the last one).
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$or?</b> (<var>$or? . <list></var>)<var><a name="index-g_t_0024or_003f-18"></a></var><br>
+<blockquote><p> The <code>$or?</code> operative performs a “short-circuit or” of its
+operands. It evaluates them from left to right, until either an
+operand evaluates to true, or the end of the list is reached. If the
+end of the list is reached (which is immediate if <code><list></code> is
+<code>nil</code>), the operative returns false. If an operand evaluates to
+true, no further operand evaluations are performed, and the operative
+returns true. If <code><list></code> is acyclic, and the last operand is
+<!-- TODO cross ref tail-context -->
+evaluated, it is evaluated as a tail context. If <code><list></code> is
+cyclic, an unbounded number of operand evaluations may be
+performed. If any of the operands evaluates to a non-boolean value, an
+error is signaled (even if it's the last one).
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Caveats.html b/manual/html/Caveats.html
@@ -0,0 +1,57 @@
+<html lang="en">
+<head>
+<title>Caveats - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Introduction.html#Introduction" title="Introduction">
+<link rel="prev" href="Introduction.html#Introduction" title="Introduction">
+<link rel="next" href="Kernel-History.html#Kernel-History" title="Kernel History">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Caveats"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Kernel-History.html#Kernel-History">Kernel History</a>,
+Previous: <a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>,
+Up: <a rel="up" accesskey="u" href="Introduction.html#Introduction">Introduction</a>
+<hr>
+</div>
+
+<h3 class="section">1.1 Caveats</h3>
+
+<p>This is the first draft of this manual. It will be incomplete for
+some time. It will also evolve, together with klisp and the Kernel
+Programming Language, both of which, right now, are in a quite fluid
+state.
+
+<!-- this is below, in history -->
+ <p>The main reference on Kernel is the preliminary report:
+<cite>Revised(-1) Report on the Kernel Programming Language</cite>. Some
+sections of the report are still incomplete, so both klisp and this
+manual will use specifications from other languages in these sections,
+trying to follow the Kernel spirit. These instances will be documented
+throughout the manual.
+
+ <p>Please mail comments and corrections to
+<a href="mailto:canavarro82@gmail.com">canavarro82@gmail.com</a>.
+
+<p class="noindent">
+<pre class="display"> –Andres Navarro
+</pre>
+ </body></html>
+
diff --git a/manual/html/Characters.html b/manual/html/Characters.html
@@ -0,0 +1,41 @@
+<html lang="en">
+<head>
+<title>Characters - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Strings.html#Strings" title="Strings">
+<link rel="next" href="Ports.html#Ports" title="Ports">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Characters"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Ports.html#Ports">Ports</a>,
+Previous: <a rel="previous" accesskey="p" href="Strings.html#Strings">Strings</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">15 Characters</h2>
+
+<p><a name="index-characters-152"></a>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Combiners.html b/manual/html/Combiners.html
@@ -0,0 +1,188 @@
+<html lang="en">
+<head>
+<title>Combiners - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Environments.html#Environments" title="Environments">
+<link rel="next" href="Continuations.html#Continuations" title="Continuations">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Combiners"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Continuations.html#Continuations">Continuations</a>,
+Previous: <a rel="previous" accesskey="p" href="Environments.html#Environments">Environments</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">8 Combiners</h2>
+
+<p><a name="index-combiners-114"></a><a name="index-applicatives-115"></a><a name="index-operatives-116"></a>
+ There are two types of combiners in Kernel, operative and
+applicative. Both types are encapsulated. All combiners are immutable.
+Two applicatives are <code>eq?</code> iff their underlying combiners are
+<code>eq?</code>. However, <code>eq?</code>-ness of operatives is only
+constrained by the general rules for <code>eq?</code>, which leave
+considerable leeway for variation between implementations. klisp only
+considers <code>eq?</code> those operatives constructed by the same call to
+a constructor (e.g. <code>$vau</code>). Two combiners are <code>equal?</code>
+iff they are <code>eq?</code>.
+<!-- TODO add xref for eq? and equal? -->
+
+<div class="defun">
+— Applicative: <b>operative?</b> (<var>operative? . objects</var>)<var><a name="index-operative_003f-117"></a></var><br>
+<blockquote><p> The primitive type predicate for type operative. <code>operative?</code>
+returns true iff all the objects in <code>objects</code> are of type
+operative.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>applicative?</b> (<var>applicative? . objects</var>)<var><a name="index-applicative_003f-118"></a></var><br>
+<blockquote><p> The primitive type predicate for type applicative.
+<code>applicative?</code> returns true iff all the objects in
+<code>objects</code> are of type applicative.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$vau</b> (<var>$vau <formals> <eformal> . <objects></var>)<var><a name="index-g_t_0024vau-119"></a></var><br>
+<blockquote><!-- TODO add xref to formal parameter tree -->
+ <p><code><formals></code> should be a formal parameter tree; <code><eformal></code>
+should be either a symbol or <code>#ignore</code>. If <code><formals></code> does
+not have the correct form for a formal parameter tree, or if
+<code><eformal></code> is a symbol that also occurs in <code><formals></code>, an
+error is signaled.
+
+ <p>A <code>vau</code> expression evaluates to an operative; an operative
+created in this way is said to be compound. The environment in which
+the <code>vau</code> expression was evaluated is remembered as part of the compound
+operative, called the compound operative’s static environment.
+<code><formals></code> and <code><objects></code> are copied as by
+<code>copy-es-immutable</code> and the copies are stored as part of the
+operative being constructed. This avoids problem if these structures
+are later mutated.
+
+ <!-- TODO add xref to eval or apply as example -->
+ <p>When the compound operative created by <code>$vau</code> is later called
+with an object and an environment, here called respectively the
+operand tree and the dynamic environment, the following happens:
+
+ <ol type=1 start=1>
+<li>A new, initially empty environment is created, with the static
+environment as its parent. This will be called the local environment.
+
+ <li>A stored copy of the formal parameter tree formals is matched in the
+local environment to the operand tree, locally binding the symbols of
+<!-- TODO add xref to matching -->
+formals to the corresponding parts of the operand tree. eformal is
+matched to the dynamic environment; that is, if eformal is a symbol
+then that symbol is bound in the local environment to the dynamic
+environment.
+
+ <li><!-- TODO add xref to tail context. -->
+A stored copy of the expressions is evaluated sequentially from left
+to right, with the last (if any) evaluated as a tail context, or if
+the list of expressions is empty, the result is inert.
+ </ol>
+
+ <p>NOTE: Because compound operatives are not a distinct type in Kernel,
+they are covered by the encapsulation of type operative. In
+particular, an implementation of Kernel cannot provide a feature that
+supports extracting the static environment of any given compound
+operative, nor that supports determining whether or not a given
+operative is compound.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>wrap</b> (<var>wrap combiner</var>)<var><a name="index-wrap-120"></a></var><br>
+<blockquote><p> The <code>wrap</code> applicative returns an applicative whose underlying
+combiner is <code>combiner</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>unwrap</b> (<var>unwrap applicative</var>)<var><a name="index-unwrap-121"></a></var><br>
+<blockquote><p> The <code>unwrap</code> applicative returns the underlying combiner of
+<code>applicative</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$lambda</b> (<var>$lambda <formals> . <objects></var>)<var><a name="index-g_t_0024lambda-122"></a></var><br>
+<blockquote><p> <code><formals></code> should be a formal parameter tree.
+
+ <p>The <code>$lambda</code> operative is defined by the following equivalence:
+ <pre class="example"> ($lambda formals . objects) ==
+ (wrap ($vau formals #ignore . objects))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>apply</b> (<var>apply applicative object </var>[<var>environment</var>])<var><a name="index-apply-123"></a></var><br>
+<blockquote><p> Applicative <code>apply</code> combines the underlying combiner of
+<code>applicative</code> with <code>object</code> in a tail context with dynamic
+environment <code>environment</code> (if the long form is used) or in an
+empty environment (if the short form is used).
+
+ <p>The following equivalences hold:
+ <pre class="example"> (apply applicative object environment) ==
+ (eval (cons (unwrap applicative) object) environment)
+
+ (apply applicative object) ==
+ (apply applicative object (make-environment))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>map</b> (<var>map applicative . lists</var>)<var><a name="index-map-124"></a></var><br>
+<blockquote><p> <code>lists</code> must be a nonempty list of lists; if there are two or
+<!-- TODO add xref to length -->
+more, they must all have the same length. If <code>lists</code> is empty, or
+if all of its elements are not lists of the same length, an error is
+signaled.
+
+ <p>The <code>map</code> applicative applies <code>applicative</code> element-wise
+to the elements of the lists in <code>lists</code> (i.e., applies it to a
+list of the first elements of the <code>lists</code>, to a list of the
+second elements of the <code>lists</code>, etc.), using the dynamic
+environment from which <code>map</code> was called, and returns a list of
+the results, in order. The applications may be performed in any order,
+as long as their results occur in the resultant list in the order of
+their arguments in the original <code>lists</code>. If <code>lists</code> is a
+cyclic list, each argument list to which <code>applicative</code> is applied
+is structurally isomorphic to <code>lists</code>. If any of the elements of
+<code>lists</code> is a cyclic list, they all must be, or they wouldn’t all
+have the same length. Let <code>a1...an</code> be their acyclic prefix
+lengths, and <code>c1...cn</code> be their cycle lengths. The acyclic
+prefix length <code>a</code> of the resultant list will be the maximum of
+the <code>ak</code>, while the cycle length <code>c</code> of the resultant list
+will be the least common multiple of the <code>ck</code>. In the
+construction of the result, applicative is called exactly <code>a + c</code>
+times.
+<!-- TODO comp/xref for-each -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>combiner?</b> (<var>combiner? . objects</var>)<var><a name="index-combiner_003f-125"></a></var><br>
+<blockquote><p> The primitive type predicate for type combiner. <code>combiner?</code>
+returns true iff all the objects in <code>objects</code> are of type
+combiner (i.e. applicative or operative).
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Continuations.html b/manual/html/Continuations.html
@@ -0,0 +1,233 @@
+<html lang="en">
+<head>
+<title>Continuations - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Combiners.html#Combiners" title="Combiners">
+<link rel="next" href="Encapsulations.html#Encapsulations" title="Encapsulations">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Continuations"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Encapsulations.html#Encapsulations">Encapsulations</a>,
+Previous: <a rel="previous" accesskey="p" href="Combiners.html#Combiners">Combiners</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">9 Continuations</h2>
+
+<p><a name="index-continuations-126"></a>
+ A continuation is a plan for all future computation, parameterized
+by a value to be provided, and contingent on the states of all mutable
+data structures (which notably may include environments). When the
+Kernel evaluator is invoked, the invoker provides a continuation to
+which the result of the evaluation will normally be returned.
+
+ <p>For example, when <code>$if</code> evaluates its test operand, the
+continuation provided for the result expects to be given a boolean
+value; and, depending on which boolean it gets, it will evaluate
+either the consequent or the alternative operand as a tail context —
+that is, the continuation provided for the result of evaluating the
+selected operand is the same continuation that was provided for the
+result of the call to <code>$if</code>.
+
+ <p>A Kernel program may sometimes capture a continuation; that is,
+acquire a reference to it as a first-class object. The basic means of
+continuation capture is applicative <code>call/cc</code>. Given a
+first-class continuation <code>c</code>, a combiner can be constructed that
+will abnormally pass its operand tree to <code>c</code> (as opposed to the
+<!-- TODO add xref to abnormal pass -->
+normal return of values to continuations). In the simplest case, the
+abnormally passed value arrives at <code>c</code> as if it had been normally
+returned to <code>c</code>. In general, continuations bypassed by the
+abnormal pass may have entry/exit guards attached to them, and these
+guards can intercept the abnormal pass before it reaches <code>c</code>.
+Each entry/exit guard consists of a selector continuation, which
+designates which abnormal passes the guard will intercept, and an
+interceptor applicative that performs the interception when selected.
+<!-- TODO add xref to guard-continuation, continuation->applicative -->
+<!-- and abnormal pass -->
+
+ <p>Continuations are immutable, and are <code>equal?</code> iff <code>eq?</code>.
+The continuation type is encapsulated.
+
+<!-- TODO add dynamic extent & guard selection/interception to the intro -->
+<div class="defun">
+— Applicative: <b>continuation?</b> (<var>continuation? . objects</var>)<var><a name="index-continuation_003f-127"></a></var><br>
+<blockquote><p> The primitive type predicate for type continuation.
+<code>continuation?</code> returns true iff all the objects in
+<code>objects</code> are of type continuation.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>call/cc</b> (<var>call/cc combiner</var>)<var><a name="index-call_002fcc-128"></a></var><br>
+<blockquote><p> Calls <code>combiner</code> in the dynamic environment as a tail context,
+passing as sole operand to it the continuation to which <code>call/cc</code>
+would normally return its result. (That is, constructs such a
+combination and evaluates it in the dynamic environment.)
+<!-- TODO add xref Cf. operative $let/cc , §7.3.2. -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>extend-continuation</b> (<var>extend-continuation continuation applicative </var>[<var>environment</var>])<var><a name="index-extend_002dcontinuation-129"></a></var><br>
+<blockquote><p> The <code>extend-continuation</code> applicative constructs and returns a
+new child of <code>continuation</code> that, when it normally receives a
+value v, calls the underlying combiner of <code>applicative</code> with
+dynamic environment <code>environment</code> (or an empty environment if
+none was specified) and operand tree <code>v</code>, the result of the call
+normally to be returned to <code>continuation</code>.
+
+ <p>The following equivalnece defines the short version:
+ <pre class="example"> (extend-continuation c a) ==
+ (extend-continuation c a (make-environment))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>guard-continuation</b> (<var>guard-continuation entry-guards continuation exit-guards</var>)<var><a name="index-guard_002dcontinuation-130"></a></var><br>
+<blockquote><p> <code>entry-guards</code> and <code>exit-guards</code> should each be a list of
+clauses; each clause should be a list of length two, whose first
+element is a continuation, and whose second element is an applicative
+whose underlying combiner is operative.
+
+ <p>Applicative <code>guard-continuation</code> constructs two continuations:
+a child of continuation, called the <code>outer continuation</code>; and a
+child of the <code>outer continuation</code>, called the <code>inner
+continuation</code>. The <code>inner continuation</code> is returned as the
+result of the call to <code>guard-continuation</code>.
+
+ <p>When the <code>inner continuation</code> normally receives a value, it
+passes the value normally to the <code>outer continuation</code>; and when
+the <code>outer continuation</code> normally receives a value, it passes the
+value normally to <code>continuation</code>. Thus, in the absence of
+abnormal passing, the inner and outer continuations each have the same
+behavior as <code>continuation</code>.
+
+ <p>The two elements of each guard clause are called, respectively, the
+<code>selector</code> and the <code>interceptor</code>. The <code>selector</code>
+continuation is used in deciding whether to intercept a given abnormal
+pass, and the <code>interceptor</code> applicative is called to perform
+<!-- TODO add xref to selection and interception -->
+customized action when interception occurs.
+
+ <!-- TODO add xref to evaluation structure -->
+ <p>At the beginning of the call to <code>guard-continuation</code>, internal
+copies are made of the evaluation structures of <code>entry-guards</code>
+and <code>exit-guards</code>, so that the selectors and interceptors
+contained in the arguments at that time remain fixed thereafter,
+independent of any subsequent mutations to the arguments.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>continuation->applicative</b> (<var>continuation->applicative continuation</var>)<var><a name="index-continuation_002d_003eapplicative-131"></a></var><br>
+<blockquote><p> Returns an applicative whose underlying operative abnormally passes
+its operand tree to <code>continuation</code>, thus: A series of
+interceptors are selected to handle the abnormal pass, and a
+continuation is derived that will normally perform all the
+interceptions in sequence and pass some value to the destination of
+the originally abnormal pass. The operand tree is then normally
+passed to the derived continuation.
+<!-- TODO add xref to selection and interception -->
+</p></blockquote></div>
+
+<div class="defun">
+— Variable: <b>root-continuation</b><var><a name="index-root_002dcontinuation-132"></a></var><br>
+<blockquote><p> This continuation is the ancestor of all other continuations. When
+it normally receives a value, it terminates the Kernel session. (For
+example, if the system is running a read-eval-print loop, it exits the
+loop.)
+<!-- TODO add xref Cf. applicative exit, §7.3.4. -->
+</p></blockquote></div>
+
+<div class="defun">
+— Variable: <b>error-continuation</b><var><a name="index-error_002dcontinuation-133"></a></var><br>
+<blockquote><p> The dynamic extent of this continuation is mutually disjoint from
+the dynamic extent in which Kernel computation usually occurs (such as
+the dynamic extent in which the Kernel system would run a
+read-eval-print loop).
+
+ <p>When this continuation normally receives a value, it provides a
+diagnostic message to the user of the Kernel system, on the assumption
+that the received value is an attempt to describe some error that
+aborted a computation; and then resumes operation of the Kernel system
+at some point that is outside of all user-defined computation. (For
+example, if the system is running a read-eval-print loop, operation
+may resume by continuing from the top of the loop.)
+
+ <p>The diagnostic message is not made available to any Kernel
+computation, and is therefore permitted to contain information that
+violates abstractions within the system.
+
+ <!-- TODO add details about klisp error messages -->
+ <p>When an error is signaled during a Kernel computation, the signaling
+action consists of an abnormal pass to some continuation in the
+dynamic extent of <code>error-continuation</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>apply-continuation</b> (<var>apply-continuation continuation object</var>)<var><a name="index-apply_002dcontinuation-134"></a></var><br>
+<blockquote><p> Applicative <code>apply-continuation</code> converts its first argument to
+an applicative as if by <code>continuation->applicative</code>, and then
+applies it as usual.
+
+ <p>That is:
+ <pre class="example"> (apply-continuation continuation object) ==
+ (apply (continuation->applicative continuation) object)
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>(</b><var>$let/cc <symbol> . <objects></var>)<var><a name="index-g_t_0028-135"></a></var><br>
+<blockquote><p> A child environment <code>e</code> of the dynamic environment is created,
+containing a binding of <code><symbol></code> to the continuation to which
+the result of the call to <code>$let/cc</code> should normally return; then,
+the subexpressions of <code><objects></code> are evaluated in <code>e</code> from
+left to right, with the last (if any) evaluated as a tail context, or
+if <code><objects></code> is empty the result is inert.
+
+ <p>That is:
+ <pre class="example"> ($let/cc symbol . objects) ==
+ (call/cc ($lambda (symbol) . objects))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>guard-dynamic-extent</b> (<var>guard-dynamic-extent entry-guards combiner exit-guards</var>)<var><a name="index-guard_002ddynamic_002dextent-136"></a></var><br>
+<blockquote><p> This applicative extends the current continuation with the specified
+guards, and calls <code>combiner</code> in the dynamic extent of the new
+continuation, with no operands and the dynamic environment of the call
+to <code>guard-dynamic-extent</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>exit</b> (<var>exit</var>)<var><a name="index-exit-137"></a></var><br>
+<blockquote><!-- TODO add xref -->
+ <p>Applicative <code>exit</code> initiates an abnormal transfer of
+<code>#inert</code> to <code>root-continuation</code>.
+
+ <p>That is:
+ <pre class="example"> (exit ) == (apply-continuation root-continuation #inert)
+</pre>
+ </blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Control.html b/manual/html/Control.html
@@ -0,0 +1,99 @@
+<html lang="en">
+<head>
+<title>Control - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Symbols.html#Symbols" title="Symbols">
+<link rel="next" href="Pairs-and-lists.html#Pairs-and-lists" title="Pairs and lists">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Control"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a>,
+Previous: <a rel="previous" accesskey="p" href="Symbols.html#Symbols">Symbols</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">5 Control</h2>
+
+<p><a name="index-control-26"></a><a name="index-inert-27"></a> The inert data type is provided for use with control combiners. It
+consists of a single immutable value, having external representation
+<code>#inert</code>. The inert type is encapsulated.
+
+<div class="defun">
+— Applicative: <b>inert?</b> (<var>inert? . objects</var>)<var><a name="index-inert_003f-28"></a></var><br>
+<blockquote><p> The primitive type predicate for type inert. <code>inert?</code>
+returns true iff all the objects in <code>objects</code> are of type inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$if</b> (<var>$if <test> <consequent> <alternative></var>)<var><a name="index-g_t_0024if-29"></a></var><br>
+<blockquote><p> The <code>$if</code> operative first evaluates <code><test></code> in the
+dynamic environment. If the result is not of type boolean, an error
+is signaled. If the result is true, <code><consequent></code> is then
+<!-- TODO add xref to tail context -->
+evaluated in the dynamic environment as a tail context. Otherwise,
+<code><alternative></code> is evaluated in the dynamic environment as a tail
+context.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$sequence</b> (<var>$sequence . <objects></var>)<var><a name="index-g_t_0024sequence-30"></a></var><br>
+<blockquote><p>The <code>$sequence</code> operative evaluates the elements of the list
+<code><objects></code> in the dynamic environment, one at a time from left
+to right. If <code><objects></code> is a cyclic list, element evaluation
+continues indefinitely, with elements in the cycle being evaluated
+repeatedly. If <code><objects></code> is a nonempty finite list, its last
+<!-- TODO add xref for tail context. -->
+element is evaluated as a tail context. If <code><objects></code> is the
+empty list, the result is inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$cond</b> (<var>$cond . <clauses></var>)<var><a name="index-g_t_0024cond-31"></a></var><br>
+<blockquote><p><code><clauses></code> should be a list of clause expressions, each of the
+form <code>(<test> . <body>)</code>, where body is a list of expressions.
+
+ <p>The following equivalences define
+the behaviour of the <code>$cond</code> operative:
+ <pre class="example"> ($cond) == #inert
+ ($cond (<test> . <body>) . <clauses>) ==
+ ($if <test> ($sequence . <body>) ($cond . <clauses>))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>for-each</b> (<var>for-each . lists</var>)<var><a name="index-for_002deach-32"></a></var><br>
+<blockquote><p><code>lists</code> must be a nonempty list of lists; if there are two or
+more, they should all be the same length. If lists is empty, or if all
+of its elements are not lists of the same length, an error is
+signaled.
+
+ <!-- TODO add xref to map -->
+ <p><code>for-each</code> behaves identically to <code>map</code>, except that instead
+of accumulating and returning a list of the results of the
+element-wise applications, the results of the applications are
+discarded and the result returned by <code>for-each</code> is inert.
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Conventions.html b/manual/html/Conventions.html
@@ -0,0 +1,51 @@
+<html lang="en">
+<head>
+<title>Conventions - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Introduction.html#Introduction" title="Introduction">
+<link rel="prev" href="Kernel-History.html#Kernel-History" title="Kernel History">
+<link rel="next" href="Acknowledgements.html#Acknowledgements" title="Acknowledgements">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Conventions"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Acknowledgements.html#Acknowledgements">Acknowledgements</a>,
+Previous: <a rel="previous" accesskey="p" href="Kernel-History.html#Kernel-History">Kernel History</a>,
+Up: <a rel="up" accesskey="u" href="Introduction.html#Introduction">Introduction</a>
+<hr>
+</div>
+
+<h3 class="section">1.3 Conventions</h3>
+
+<p>This section explains the notational conventions that are used in this
+manual. You may want to skip this section and refer back to it later.
+
+<ul class="menu">
+<li><a accesskey="1" href="Some-Terms.html#Some-Terms">Some Terms</a>: Explanation of terms we use in this manual.
+<!-- TODO add sections for booleans, parameter trees, list structures, -->
+<!-- naming conventions, etc. -->
+<li><a accesskey="2" href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a>: The format we use for examples of evaluation.
+<li><a accesskey="3" href="Printing-Notation.html#Printing-Notation">Printing Notation</a>: The format we use for examples that print output.
+<li><a accesskey="4" href="Error-Messages.html#Error-Messages">Error Messages</a>: The format we use for examples of errors.
+<li><a accesskey="5" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>: Notation for describing functions, variables, etc.
+</ul>
+
+ </body></html>
+
diff --git a/manual/html/Encapsulations.html b/manual/html/Encapsulations.html
@@ -0,0 +1,73 @@
+<html lang="en">
+<head>
+<title>Encapsulations - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Continuations.html#Continuations" title="Continuations">
+<link rel="next" href="Promises.html#Promises" title="Promises">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Encapsulations"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Promises.html#Promises">Promises</a>,
+Previous: <a rel="previous" accesskey="p" href="Continuations.html#Continuations">Continuations</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">10 Encapsulations</h2>
+
+<p><a name="index-encapsulations-138"></a>
+An encapsulation is an object that refers to another object, called
+its content. The Kernel data type encapsulation is encapsulated. Two
+encapsulations are <code>equal?</code> iff they are <code>eq?</code>.
+Encapsulations are immutable.
+
+<!-- TODO this is a little spartan... maybe add some more content -->
+<div class="defun">
+— Applicative: <b>make-encapsulation-type</b> (<var>make-encapsulation-type</var>)<var><a name="index-make_002dencapsulation_002dtype-139"></a></var><br>
+<blockquote><p> Returns a list of the form <code>(e p? d)</code>, where <code>e</code>,
+<code>p</code>?, and <code>d</code> are applicatives, as follows. Each call to
+<code>make-encapsulation-type</code> returns different applicatives
+<code>e</code>, <code>p?</code>, and <code>d</code>.
+
+ <ul>
+<li><code>e</code> is an applicative that takes one argument, and returns a
+fresh encapsulation with the argument as content. Encapsulations
+returned on different occasions are not <code>eq?</code>.
+
+ <li><code>p?</code> is a primitive type predicate, that takes zero or more
+arguments and returns true iff all of them are encapsulations
+generated by <code>e</code>.
+
+ <li><code>d</code> is an applicative that takes one argument; if the argument is
+not an encapsulation generated by <code>e</code>, an error is signaled,
+otherwise the content of the encapsulation is returned.
+</ul>
+
+ <p>That is, the predicate <code>p?</code> only recognizes, and the decapsulator
+<code>d</code> only extracts the content of, encapsulations created by the
+encapsulator <code>e</code> that was returned by the same call to
+<code>make-encapsulation-type</code>.
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Environments.html b/manual/html/Environments.html
@@ -0,0 +1,330 @@
+<html lang="en">
+<head>
+<title>Environments - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Pairs-and-lists.html#Pairs-and-lists" title="Pairs and lists">
+<link rel="next" href="Combiners.html#Combiners" title="Combiners">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Environments"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Combiners.html#Combiners">Combiners</a>,
+Previous: <a rel="previous" accesskey="p" href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">7 Environments</h2>
+
+<p><a name="index-environments-93"></a><a name="index-ignore-94"></a>
+ An environment consists of a set of bindings, and a list of zero or
+more references to other environments called its parents.
+<!-- TODO add xref to lookup algo & ground env -->
+Changing the set of bindings of an environment, or setting the
+referent of the reference in a binding, is a mutation of the
+environment. (Changing the parent list, or a referent in the list,
+would be a mutation of the environment too, but there is no facility
+provided to do it.) The Kernel data type environment is encapsulated.
+Among other things, there is no facility provided for enumerating all
+the variables exhibited by an environment (which is not required,
+after all, to be a finite set), and no facility for identifying the
+parents of an environment. Two environments are <code>equal?</code> iff
+they are <code>eq?</code>.
+
+ <p>An auxiliary data type used by combiners that perform binding is
+ignore. The ignore type consists of a single immutable value, having
+external representation <code>#ignore</code>. The ignore type is
+encapsulated.
+
+<div class="defun">
+— Applicative: <b>environment?</b> (<var>environment? . objects</var>)<var><a name="index-environment_003f-95"></a></var><br>
+<blockquote><p> The primitive type predicate for type environment.
+<code>environment?</code> returns true iff all the objects in <code>objects</code>
+are of type environment.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>ignore?</b> (<var>ignore? . objects</var>)<var><a name="index-ignore_003f-96"></a></var><br>
+<blockquote><p> The primitive type predicate for type ignore. <code>ignore?</code>
+returns true iff all the objects in <code>objects</code> are of type ignore.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>eval</b> (<var>eval expression environment</var>)<var><a name="index-eval-97"></a></var><br>
+<blockquote><!-- TODO add xref to tail context -->
+ <!-- TODO add xref to evaluation description -->
+ <p>The <code>eval</code> applicative evaluates <code>expression</code> as a tail
+context in <code>environment</code>, and returns the resulting value.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>make-environment</b> (<var>make-environment . environments</var>)<var><a name="index-make_002denvironment-98"></a></var><br>
+<blockquote><p> The applicative constructs and returns a new environment, with
+initially no local bindings, and parent environments the environments
+listed in <code>environments</code>. The constructed environment internally
+stores its list of parents independent of the first-class list
+<code>environments</code>, so that subsequent mutation of
+<code>environments</code> will not change the parentage of the constructed
+environment. If the provided list <code>environments</code> is cyclic, the
+constructed environment will still check each of its parents at most
+once, and signal an error if no binding is found locally or in any of
+<!-- TODO add xref to cons, mutation, eq? and equal? -->
+the parents. No two objects returned by different calls to
+<code>make-environment</code> are <code>eq?</code> to each other.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$define!</b> (<var>$define! <definiend> <expression></var>)<var><a name="index-g_t_0024define_0021-99"></a></var><br>
+<blockquote><!-- TODO move formal parameter tree definition to the intro -->
+ <!-- TODO move matching definition to the intro -->
+ <p><code><definiend></code> should be a formal parameter tree, as described
+below; otherwise, an error is signaled.
+
+ <p>The <code>$define!</code> operative evaluates <code><expression></code> in the
+dynamic environment and matches <code><definiend></code> to the result in
+the dynamic environment, binding each symbol in definiend in the
+dynamic environment to the corresponding part of the result; the
+matching process will be further described below. The ancestors of the
+dynamic environment, if any, are unaffected by the matching process,
+as are all bindings, local to the dynamic environment, of symbols not
+in <code><definiend></code>. The result returned by <code>$define!</code> is
+inert.
+
+ <p>A formal parameter tree has the following context-free structure:
+ <pre class="example"> ptree:: symbol | #ignore | () | (ptree . ptree)
+</pre>
+ <p>That is, a formal parameter tree is either a symbol, or ignore, or
+nil, or a pair whose car and cdr referents are formal parameter trees.
+A formal parameter tree must also be acyclic, and no one symbol can
+occur more than once in it. It is not an error for a pair in the tree
+to be reachable from the root by more than one path, as long as there
+is no cycle; but if any particular symbol were reachable from the root
+by more than one path, that would count as occurring more than once.
+Thus, if a pair is reachable by more than one path, there must be no
+symbols reachable from it.
+
+ <p>Matching of a formal parameter tree <code>t</code> to an object <code>o</code>
+in an environment <code>e</code> proceeds recursively as follows. If the
+matching process fails, an error is signaled.
+ <ul>
+<li>If <code>t</code> is a symbol, then <code>t</code> is bound to <code>o</code> in
+<code>e</code>.
+
+ <li>If <code>t</code> is <code>#ignore</code>, no action is taken.
+
+ <li>If <code>t</code> is nil, then <code>o</code> must be nil (else matching fails).
+
+ <li>If <code>t</code> is a pair, then <code>o</code> must be a pair (else matching
+fails). The car of <code>t</code> is matched to the car of <code>o</code> in
+<code>e</code>, and the cdr of <code>t</code> is matched to the cdr of <code>o</code> in
+<code>e</code>.
+</ul>
+ </p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$let</b> (<var>$let <bindings> . <objects></var>)<var><a name="index-g_t_0024let-100"></a></var><br>
+<blockquote><!-- TODO add xref to formal parameter tree -->
+ <p><code><bindings></code> should be a finite list of
+formal-parameter-tree/expression pairings, each of the form
+<code>(formals expression)</code>, where each <code>formals</code> is a formal
+parameter, and no symbol occurs in more than one of the
+<code>formals</code>.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($let ((form1 exp1) ... (formn expn)) . objects) ==
+ (($lambda (form1 ... formn) . objects) exp1 ... expn)
+</pre>
+ <!-- TODO add xref to tail context -->
+ <p>Thus, the <code>expk</code> are first evaluated in the dynamic environment,
+in any order; then a child environment <code>e</code> of the dynamic
+environment is created, with the <code>formk</code> matched in <code>e</code> to
+the results of the evaluations of the <code>expk</code>; and finally the
+subexpressions of <code>objects</code> are evaluated in <code>e</code> from left
+to right, with the last (if any) evaluated as a tail context, or if
+<code>objects</code> is empty the result is inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$binds?</b> (<var>$binds? <exp> . <symbols></var>)<var><a name="index-g_t_0024binds_003f-101"></a></var><br>
+<blockquote><p> Operative <code>$binds</code> evaluates <code><exp></code> in the dynamic
+environment; call the result <code>env</code>. <code>env</code> must be an
+environment. The operative is a predicate that returns true iff all
+its later operands, <code><symbols></code>, are visibly bound in <code>env</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>get-current-environment</b> (<var>get-current-environment</var>)<var><a name="index-get_002dcurrent_002denvironment-102"></a></var><br>
+<blockquote><p> The <code>get-current-environment</code> applicative returns the dynamic
+environment in which it is called.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>make-kernel-standard-environment</b> (<var>make-kernel-standard-environment</var>)<var><a name="index-make_002dkernel_002dstandard_002denvironment-103"></a></var><br>
+<blockquote><!-- TODO add xref to ground environment/standard environment -->
+ <p>The <code>make-kernel-standard-environment</code> applicative returns a
+standard environment; that is, a child of the ground environment with
+no local bindings.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$let*</b> (<var>$let* <bindings> . <body></var>)<var><a name="index-g_t_0024let_002a-104"></a></var><br>
+<blockquote><!-- TODO add xref to formal ptree -->
+ <p><code><bindings></code> should be a finite list of
+formal-parameter-tree/expression pairings, each of the form
+<code>(formals expression)</code>, where each <code>formals</code> is a formal
+parameter tree; <code><body></code> should be a list of expressions.
+
+ <p>The following equivalences hold:
+
+ <pre class="example"> ($let* () . body) == ($let () . body)
+
+ ($let* ((form exp) . bindings) . body) ==
+ ($let ((form exp)) ($let* bindings . body))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$letrec</b> (<var>$letrec <bindings> . <body></var>)<var><a name="index-g_t_0024letrec-105"></a></var><br>
+<blockquote><!-- add xref for $let -->
+ <p><code><bindings></code> and <code><body></code> should be as described for
+<code>$let</code>.
+
+ <p>The following equivalence holds:
+ <pre class="example"> ($letrec ((form1 exp1) ... (formn expn)) . body) ==
+ ($let () ($define! (form1 ... formn) (list exp1 ... expn)) . body)
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$letrec*</b> (<var>$letrec* <bindings> . <body></var>)<var><a name="index-g_t_0024letrec_002a-106"></a></var><br>
+<blockquote><!-- TODO add xref to $let* -->
+ <p><code><bindings></code> and <code><body></code> should be as described for
+<code>$let*</code>.
+
+ <p>The following equivalences hold:
+ <pre class="example"> ($letrec* () . body) == ($letrec () . body)
+
+ ($letrec* ((form exp) . bindings) . body) ==
+ ($letrec ((form exp)) ($letrec* bindings . body))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$let-redirect</b> (<var>$let-redirect <exp> <bindings> . <body></var>)<var><a name="index-g_t_0024let_002dredirect-107"></a></var><br>
+<blockquote><!-- TODO add xref to $let -->
+ <p><code><bindings></code> and <code><body></code> should be as described for
+<code>$let</code>.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($let-redirect exp ((form1 exp1) ... (formn . body) expn)) ==
+ ((eval (list $lambda (form1 ... formn) body) exp) expn ... expn)
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$let-safe</b> (<var>$let-safe <bindings> . <body></var>)<var><a name="index-g_t_0024let_002dsafe-108"></a></var><br>
+<blockquote><!-- TODO add xref to $let -->
+ <p><code><bindings></code> and <code><body></code> should be as described for
+<code>$let</code>.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($let-safe bindings . body) ==
+ ($let-redirect (make-kernel-standard-environment) bindings . body)
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$remote-eval</b> (<var>$remote-eval <exp1> <exp2></var>)<var><a name="index-g_t_0024remote_002deval-109"></a></var><br>
+<blockquote><!-- TODO add xref to tail context -->
+ <p>Operative <code>$remote-eval</code> evaluates <code><exp2></code> in the dynamic
+environment, then evaluates <code><exp1></code> as a tail context in the
+environment that must result from the first evaluation.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>(</b><var>$bindings-environment . <bindings></var>)<var><a name="index-g_t_0028-110"></a></var><br>
+<blockquote><!-- TODO add xref to $let -->
+ <p><code><bindings></code> should be as described for <code>$let</code>.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($bindings->environment . bindings) ==
+ ($let-redirect (make-environment) bindings (get-current-environment))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$set!</b> (<var>$set! <exp1> <formals> <exp2></var>)<var><a name="index-g_t_0024set_0021-111"></a></var><br>
+<blockquote><!-- TODO add xref to $define! -->
+ <!-- TODO add xref to matching algo -->
+ <p><code><formals></code> should be as described for the <code>$define!</code>
+operative. The <code>$set!</code> operative evaluates <code><exp1></code> and
+<code><exp2></code> in the dynamic environment; call the results <code>env</code>
+and <code>obj</code>. If <code>env</code> is not an environment, an error is
+signaled. Then the operative matches <code><formals></code> to <code>obj</code>
+in environment <code>env</code>. Thus, the symbols of <code><formals></code> are
+bound in <code>env</code> to the corresponding parts of <code>obj</code>.
+The result returned by <code>$set!</code> is inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$provide!</b> (<var>$provide! <symbols> . <body></var>)<var><a name="index-g_t_0024provide_0021-112"></a></var><br>
+<blockquote><p> <code><symbols></code> must be a finite list of symbols, containing no
+duplicates. <code><body></code> must be a finite list.
+
+ <p>The <code>$provide!</code> operative constructs a child <code>e</code> of the
+dynamic environment <code>d</code>; evaluates the elements of <code><body></code>
+in <code>e</code>, from left to right, discarding all of the results; and
+exports all of the bindings of symbols in <code><symbols></code> from
+<code>e</code> to <code>d</code>, i.e., binds each symbol in <code>d</code> to the
+result of looking it up in <code>e</code>. The result returned by
+<code>$provide!</code> is inert.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($provide! symbols . body) ==
+ ($define! symbols ($let () ($sequence . body) (list . symbols)))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Operative: <b>$import!</b> (<var>$import! <exp> . <symbols></var>)<var><a name="index-g_t_0024import_0021-113"></a></var><br>
+<blockquote><p> <code><symbols></code> must be a list of symbols.
+
+ <p>The <code>$import!</code> operative evaluates <code><exp></code> in the dynamic
+environment; call the result <code>env</code>. <code>env</code> must be an
+environment. Each distinct symbol <code>s</code> in <code><symbols></code> is
+evaluated in <code>env</code>, and <code>s</code> is bound in the dynamic
+environment to the result of this evaluation.
+
+ <p>The following equivalence holds:
+
+ <pre class="example"> ($import! exp . symbols) ==
+ ($define! symbols ($remote-eval (list symbols) exp))
+</pre>
+ </blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Equivalence.html b/manual/html/Equivalence.html
@@ -0,0 +1,61 @@
+<html lang="en">
+<head>
+<title>Equivalence - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Booleans.html#Booleans" title="Booleans">
+<link rel="next" href="Symbols.html#Symbols" title="Symbols">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Equivalence"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Symbols.html#Symbols">Symbols</a>,
+Previous: <a rel="previous" accesskey="p" href="Booleans.html#Booleans">Booleans</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">3 Equivalence</h2>
+
+<p><a name="index-equivalence-19"></a>
+ Kernel has two general-purpose equivalence predicates (whereas R5RS
+Scheme has three). The two Kernel predicates correspond to the
+abstract notions of equivalence up to mutation (<code>equal</code>) and
+equivalence in the presence of mutation (<code>eq?</code>).
+
+<div class="defun">
+— Applicative: <b>eq?</b> (<var>eq? . objects</var>)<var><a name="index-eq_003f-20"></a></var><br>
+<blockquote><p> Predicate <code>eq?</code> returns true iff all of <code>objects</code> are
+effectively the same object, even in the presence of mutation.
+<!-- todo maybe add more content here, specifical to klisp -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>equal?</b> (<var>equal? . objects</var>)<var><a name="index-equal_003f-21"></a></var><br>
+<blockquote><p> Predicate <code>equal?</code> returns true iff all of <code>objects</code>
+“look” the same as long as nothing is mutated. This is a weaker
+predicate than <code>eq?</code>; that is, <code>equal?</code> must return true
+whenever <code>eq?</code> would return true.
+<!-- todo maybe add more content here, specifical to klisp -->
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Error-Messages.html b/manual/html/Error-Messages.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>Error Messages - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Conventions.html#Conventions" title="Conventions">
+<link rel="prev" href="Printing-Notation.html#Printing-Notation" title="Printing Notation">
+<link rel="next" href="Format-of-Descriptions.html#Format-of-Descriptions" title="Format of Descriptions">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Error-Messages"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>,
+Previous: <a rel="previous" accesskey="p" href="Printing-Notation.html#Printing-Notation">Printing Notation</a>,
+Up: <a rel="up" accesskey="u" href="Conventions.html#Conventions">Conventions</a>
+<hr>
+</div>
+
+<h4 class="subsection">1.3.4 Error Messages</h4>
+
+<p><a name="index-error-message-notation-6"></a>
+ Some examples cause errors to be signaled. The report doesn't
+specify what objects are passed to the error continuation, but in
+klisp, objects passed to the error continuation are encapsulated error
+objects that have at least a message and possibly some additional
+objects and context informations (such as source code location). In
+the examples, the error message is shown on a line starting with
+‘<samp><span class="samp">error--></span></samp>’.
+
+<pre class="example"> (+ 23 #t)
+ error--> Wrong type argument: (expected number) (#t)
+</pre>
+ </body></html>
+
diff --git a/manual/html/Evaluation-Notation.html b/manual/html/Evaluation-Notation.html
@@ -0,0 +1,61 @@
+<html lang="en">
+<head>
+<title>Evaluation Notation - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Conventions.html#Conventions" title="Conventions">
+<link rel="prev" href="Some-Terms.html#Some-Terms" title="Some Terms">
+<link rel="next" href="Printing-Notation.html#Printing-Notation" title="Printing Notation">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Evaluation-Notation"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Printing-Notation.html#Printing-Notation">Printing Notation</a>,
+Previous: <a rel="previous" accesskey="p" href="Some-Terms.html#Some-Terms">Some Terms</a>,
+Up: <a rel="up" accesskey="u" href="Conventions.html#Conventions">Conventions</a>
+<hr>
+</div>
+
+<h4 class="subsection">1.3.2 Evaluation Notation</h4>
+
+<p><a name="index-evaluation-notation-3"></a><a name="index-documentation-notation-4"></a>
+ When you evaluate a piece of Kernel code, it produces a result. In the
+examples in this manual, this is indicated with ‘<samp><span class="samp">⇒</span></samp>’:
+
+<pre class="example"> (car (cons 1 2))
+ ⇒ 1
+</pre>
+ <p class="noindent">You can read this as “<code>(car (cons 1 2))</code> evaluates to 1”.
+
+ <p>The semantics of a language feature are sometimes clarified, or even
+defined, in its entry by specifying that two expressions are
+equivalent. This is notated with ‘<samp><span class="samp">==</span></samp>’. For example, the
+semantics of applicative list* can be defined by following
+equivalences:
+<pre class="example"> (list* arg1) == arg1
+ (list* arg1 . more-args) == (cons arg1 (list* . more-args))
+</pre>
+ <p>Notice that in these kind of examples the applicatives or operatives
+referred to are the first class values and not the symbols bound to
+them in the ground environment. This definition would hold even if
+<code>cons</code> or <code>list*</code> were redefined in the current dynamic
+environment.
+
+ </body></html>
+
diff --git a/manual/html/Format-of-Descriptions.html b/manual/html/Format-of-Descriptions.html
@@ -0,0 +1,47 @@
+<html lang="en">
+<head>
+<title>Format of Descriptions - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Conventions.html#Conventions" title="Conventions">
+<link rel="prev" href="Error-Messages.html#Error-Messages" title="Error Messages">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Format-of-Descriptions"></a>
+<p>
+Previous: <a rel="previous" accesskey="p" href="Error-Messages.html#Error-Messages">Error Messages</a>,
+Up: <a rel="up" accesskey="u" href="Conventions.html#Conventions">Conventions</a>
+<hr>
+</div>
+
+<h4 class="subsection">1.3.5 Format of Descriptions</h4>
+
+<p><a name="index-description-format-7"></a>
+ Applicatives, operatives, and other objects are described in this manual
+in a uniform format. The first line of a description contains the
+name of the item followed by its operands or arguments, if any.
+The description follows on succeeding lines, sometimes with examples.
+
+<ul class="menu">
+<li><a accesskey="1" href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">A Sample Applicative Description</a>
+<!-- TODO add operative and/or variable like root-continuation -->
+</ul>
+
+ </body></html>
+
diff --git a/manual/html/Index.html b/manual/html/Index.html
@@ -0,0 +1,275 @@
+<html lang="en">
+<head>
+<title>Index - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Ports.html#Ports" title="Ports">
+<link rel="next" href="../index.html#dir" title="(dir)">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Index"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="../index.html#dir">(dir)</a>,
+Previous: <a rel="previous" accesskey="p" href="Ports.html#Ports">Ports</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- this is from the elisp manual... Should read a little about this. -->
+<h2 class="unnumbered">Index</h2>
+
+<ul class="index-fn" compact>
+<li><a href="Booleans.html#index-g_t_0024and_003f-17"><code>$and?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Environments.html#index-g_t_0024binds_003f-101"><code>$binds?</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Control.html#index-g_t_0024cond-31"><code>$cond</code></a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Environments.html#index-g_t_0024define_0021-99"><code>$define!</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Control.html#index-g_t_0024if-29"><code>$if</code></a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Environments.html#index-g_t_0024import_0021-113"><code>$import!</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Combiners.html#index-g_t_0024lambda-122"><code>$lambda</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Promises.html#index-g_t_0024lazy-143"><code>$lazy</code></a>: <a href="Promises.html#Promises">Promises</a></li>
+<li><a href="Environments.html#index-g_t_0024let-100"><code>$let</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024let_002a-104"><code>$let*</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024let_002dredirect-107"><code>$let-redirect</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024let_002dsafe-108"><code>$let-safe</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024letrec-105"><code>$letrec</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024letrec_002a-106"><code>$letrec*</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Booleans.html#index-g_t_0024or_003f-18"><code>$or?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Environments.html#index-g_t_0024provide_0021-112"><code>$provide!</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-g_t_0024remote_002deval-109"><code>$remote-eval</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Control.html#index-g_t_0024sequence-30"><code>$sequence</code></a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Environments.html#index-g_t_0024set_0021-111"><code>$set!</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Combiners.html#index-g_t_0024vau-119"><code>$vau</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Ports.html#index-g_t_0028-157"><code>(</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Continuations.html#index-g_t_0028-135"><code>(</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Environments.html#index-g_t_0028-110"><code>(</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Booleans.html#index-and_003f-15"><code>and?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Pairs-and-lists.html#index-append-81"><code>append</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-append_0021-89"><code>append!</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="A-Sample-Applicative-Description.html#index-applicative-descriptions-8">applicative descriptions</a>: <a href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">A Sample Applicative Description</a></li>
+<li><a href="Combiners.html#index-applicative_003f-118"><code>applicative?</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Combiners.html#index-applicatives-115">applicatives</a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Combiners.html#index-apply-123"><code>apply</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Continuations.html#index-apply_002dcontinuation-134"><code>apply-continuation</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Pairs-and-lists.html#index-assoc-84"><code>assoc</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-assq-91"><code>assq</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Booleans.html#index-boolean_003f-13"><code>boolean?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Booleans.html#index-booleans-12">booleans</a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Pairs-and-lists.html#index-caaaar-59"><code>caaaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caaadr-60"><code>caaadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caaar-51"><code>caaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caadar-61"><code>caadar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caaddr-62"><code>caaddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caadr-52"><code>caadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caar-47"><code>caar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cadaar-63"><code>cadaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cadadr-64"><code>cadadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cadar-53"><code>cadar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caddar-65"><code>caddar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cadddr-66"><code>cadddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-caddr-54"><code>caddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cadr-48"><code>cadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Ports.html#index-call_002dwith_002dinput_002dfile-167"><code>call-with-input-file</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Ports.html#index-call_002dwith_002doutput_002dfile-168"><code>call-with-output-file</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Continuations.html#index-call_002fcc-128"><code>call/cc</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Pairs-and-lists.html#index-car-45"><code>car</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdaaar-67"><code>cdaaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdaadr-68"><code>cdaadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdaar-55"><code>cdaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdadar-69"><code>cdadar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdaddr-70"><code>cdaddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdadr-56"><code>cdadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdar-49"><code>cdar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cddaar-71"><code>cddaar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cddadr-72"><code>cddadr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cddar-57"><code>cddar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdddar-73"><code>cdddar</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cddddr-74"><code>cddddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdddr-58"><code>cdddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cddr-50"><code>cddr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-cdr-46"><code>cdr</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Characters.html#index-characters-152">characters</a>: <a href="Characters.html#Characters">Characters</a></li>
+<li><a href="Combiners.html#index-combiner_003f-125"><code>combiner?</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Combiners.html#index-combiners-114">combiners</a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Pairs-and-lists.html#index-cons-39"><code>cons</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Continuations.html#index-continuation_002d_003eapplicative-131"><code>continuation->applicative</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Continuations.html#index-continuation_003f-127"><code>continuation?</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Continuations.html#index-continuations-126">continuations</a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Control.html#index-control-26">control</a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Pairs-and-lists.html#index-copy_002des-90"><code>copy-es</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-copy_002des_002dimmutable_0021-42"><code>copy-es-immutable!</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-countable_002dlist_003f-87"><code>countable-list?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Format-of-Descriptions.html#index-description-format-7">description format</a>: <a href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a></li>
+<li><a href="Evaluation-Notation.html#index-documentation-notation-4">documentation notation</a>: <a href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a></li>
+<li><a href="Pairs-and-lists.html#index-empty-list-35">empty list</a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Encapsulations.html#index-encapsulations-138">encapsulations</a>: <a href="Encapsulations.html#Encapsulations">Encapsulations</a></li>
+<li><a href="Pairs-and-lists.html#index-encycle_0021-77"><code>encycle!</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Environments.html#index-environment_003f-95"><code>environment?</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-environments-93">environments</a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Ports.html#index-eof_002dobject_003f-171"><code>eof-object?</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Equivalence.html#index-eq_003f-20"><code>eq?</code></a>: <a href="Equivalence.html#Equivalence">Equivalence</a></li>
+<li><a href="Equivalence.html#index-equal_003f-21"><code>equal?</code></a>: <a href="Equivalence.html#Equivalence">Equivalence</a></li>
+<li><a href="Equivalence.html#index-equivalence-19">equivalence</a>: <a href="Equivalence.html#Equivalence">Equivalence</a></li>
+<li><a href="Error-Messages.html#index-error-message-notation-6">error message notation</a>: <a href="Error-Messages.html#Error-Messages">Error Messages</a></li>
+<li><a href="Continuations.html#index-error_002dcontinuation-133"><code>error-continuation</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Environments.html#index-eval-97"><code>eval</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Evaluation-Notation.html#index-evaluation-notation-3">evaluation notation</a>: <a href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a></li>
+<li><a href="Continuations.html#index-exit-137"><code>exit</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Continuations.html#index-extend_002dcontinuation-129"><code>extend-continuation</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Pairs-and-lists.html#index-filter-83"><code>filter</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-finite_002dlist_003f-86"><code>finite-list?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Some-Terms.html#index-fonts-2">fonts</a>: <a href="Some-Terms.html#Some-Terms">Some Terms</a></li>
+<li><a href="A-Sample-Applicative-Description.html#index-foo-11"><code>foo</code></a>: <a href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">A Sample Applicative Description</a></li>
+<li><a href="Control.html#index-for_002deach-32"><code>for-each</code></a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Promises.html#index-force-142"><code>force</code></a>: <a href="Promises.html#Promises">Promises</a></li>
+<li><a href="Environments.html#index-get_002dcurrent_002denvironment-102"><code>get-current-environment</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Pairs-and-lists.html#index-get_002dlist_002dmetrics-75"><code>get-list-metrics</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Ports.html#index-get_002dmodule-170"><code>get-module</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Continuations.html#index-guard_002dcontinuation-130"><code>guard-continuation</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Continuations.html#index-guard_002ddynamic_002dextent-136"><code>guard-dynamic-extent</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Environments.html#index-ignore-94">ignore</a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-ignore_003f-96"><code>ignore?</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Control.html#index-inert-27">inert</a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Control.html#index-inert_003f-28"><code>inert?</code></a>: <a href="Control.html#Control">Control</a></li>
+<li><a href="Ports.html#index-input_002dport_003f-155"><code>input-port?</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Kernel-History.html#index-Kernel-history-1">Kernel history</a>: <a href="Kernel-History.html#Kernel-History">Kernel History</a></li>
+<li><a href="Keyed-Variables.html#index-keyed-dynamic-variables-146">keyed dynamic variables</a>: <a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a></li>
+<li><a href="Keyed-Variables.html#index-keyed-static-variables-148">keyed static variables</a>: <a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a></li>
+<li><a href="Keyed-Variables.html#index-keyed-variables-145">keyed variables</a>: <a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a></li>
+<li><a href="Pairs-and-lists.html#index-length-79"><code>length</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-list-43"><code>list</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-list_002a-44"><code>list*</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-list_002dneighbors-82"><code>list-neighbors</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-list_002dref-80"><code>list-ref</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-list_002dtail-76"><code>list-tail</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-lists-36">lists</a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Ports.html#index-load-169"><code>load</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Encapsulations.html#index-make_002dencapsulation_002dtype-139"><code>make-encapsulation-type</code></a>: <a href="Encapsulations.html#Encapsulations">Encapsulations</a></li>
+<li><a href="Environments.html#index-make_002denvironment-98"><code>make-environment</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Environments.html#index-make_002dkernel_002dstandard_002denvironment-103"><code>make-kernel-standard-environment</code></a>: <a href="Environments.html#Environments">Environments</a></li>
+<li><a href="Keyed-Variables.html#index-make_002dkeyed_002ddynamic_002dvariable-147"><code>make-keyed-dynamic-variable</code></a>: <a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a></li>
+<li><a href="Keyed-Variables.html#index-make_002dkeyed_002dstatic_002dvariable-149"><code>make-keyed-static-variable</code></a>: <a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a></li>
+<li><a href="Combiners.html#index-map-124"><code>map</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Pairs-and-lists.html#index-map-78"><code>map</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-member_003f-85"><code>member?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Promises.html#index-memoize-144"><code>memoize</code></a>: <a href="Promises.html#Promises">Promises</a></li>
+<li><a href="Pairs-and-lists.html#index-memq_003f-92"><code>memq?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-nil-34">nil</a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Booleans.html#index-not_003f-14"><code>not?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Pairs-and-lists.html#index-null_003f-38"><code>null?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Numbers.html#index-numbers-150">numbers</a>: <a href="Numbers.html#Numbers">Numbers</a></li>
+<li><a href="A-Sample-Applicative-Description.html#index-object-descriptions-10">object descriptions</a>: <a href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">A Sample Applicative Description</a></li>
+<li><a href="Ports.html#index-open_002dinput_002dfile-161"><code>open-input-file</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Ports.html#index-open_002doutput_002dfile-162"><code>open-output-file</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="A-Sample-Applicative-Description.html#index-operative-descriptions-9">operative descriptions</a>: <a href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">A Sample Applicative Description</a></li>
+<li><a href="Combiners.html#index-operative_003f-117"><code>operative?</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Combiners.html#index-operatives-116">operatives</a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Booleans.html#index-or_003f-16"><code>or?</code></a>: <a href="Booleans.html#Booleans">Booleans</a></li>
+<li><a href="Ports.html#index-output_002dport_003f-156"><code>output-port?</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Pairs-and-lists.html#index-pair_003f-37"><code>pair?</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-pairs-33">pairs</a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Ports.html#index-port_003f-154"><code>port?</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Ports.html#index-ports-153">ports</a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Printing-Notation.html#index-printing-notation-5">printing notation</a>: <a href="Printing-Notation.html#Printing-Notation">Printing Notation</a></li>
+<li><a href="Promises.html#index-promise_003f-141"><code>promise?</code></a>: <a href="Promises.html#Promises">Promises</a></li>
+<li><a href="Promises.html#index-promises-140">promises</a>: <a href="Promises.html#Promises">Promises</a></li>
+<li><a href="Ports.html#index-read-165"><code>read</code></a>: <a href="Ports.html#Ports">Ports</a></li>
+<li><a href="Pairs-and-lists.html#index-reduce-88"><code>reduce</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Continuations.html#index-root_002dcontinuation-132"><code>root-continuation</code></a>: <a href="Continuations.html#Continuations">Continuations</a></li>
+<li><a href="Pairs-and-lists.html#index-set_002dcar_0021-40"><code>set-car!</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Pairs-and-lists.html#index-set_002dcdr_0021-41"><code>set-cdr!</code></a>: <a href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a></li>
+<li><a href="Symbols.html#index-string_002d_003esymbol-25"><code>string->symbol</code></a>: <a href="Symbols.html#Symbols">Symbols</a></li>
+<li><a href="Strings.html#index-strings-151">strings</a>: <a href="Strings.html#Strings">Strings</a></li>
+<li><a href="Symbols.html#index-symbol_002d_003estring-24"><code>symbol->string</code></a>: <a href="Symbols.html#Symbols">Symbols</a></li>
+<li><a href="Symbols.html#index-symbol_003f-23"><code>symbol?</code></a>: <a href="Symbols.html#Symbols">Symbols</a></li>
+<li><a href="Symbols.html#index-symbols-22">symbols</a>: <a href="Symbols.html#Symbols">Symbols</a></li>
+<li><a href="Combiners.html#index-unwrap-121"><code>unwrap</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+<li><a href="Combiners.html#index-wrap-120"><code>wrap</code></a>: <a href="Combiners.html#Combiners">Combiners</a></li>
+</ul><!-- Print the tables of contents -->
+
+<div class="shortcontents">
+<h2>Short Contents</h2>
+<ul>
+<li><a href="Index.html#toc_License">MIT/X11 License</a></li>
+<li><a href="Index.html#toc_Introduction">1 Introduction</a></li>
+<li><a href="Index.html#toc_Booleans">2 Booleans</a></li>
+<li><a href="Index.html#toc_Equivalence">3 Equivalence</a></li>
+<li><a href="Index.html#toc_Symbols">4 Symbols</a></li>
+<li><a href="Index.html#toc_Control">5 Control</a></li>
+<li><a href="Index.html#toc_Pairs-and-lists">6 Pairs and lists</a></li>
+<li><a href="Index.html#toc_Environments">7 Environments</a></li>
+<li><a href="Index.html#toc_Combiners">8 Combiners</a></li>
+<li><a href="Index.html#toc_Continuations">9 Continuations</a></li>
+<li><a href="Index.html#toc_Encapsulations">10 Encapsulations</a></li>
+<li><a href="Index.html#toc_Promises">11 Promises</a></li>
+<li><a href="Index.html#toc_Keyed-Variables">12 Keyed Variables</a></li>
+<li><a href="Index.html#toc_Numbers">13 Numbers</a></li>
+<li><a href="Index.html#toc_Strings">14 Strings</a></li>
+<li><a href="Index.html#toc_Characters">15 Characters</a></li>
+<li><a href="Index.html#toc_Ports">16 Ports</a></li>
+<li><a href="Index.html#toc_Index">Index</a></li>
+</ul>
+</div>
+
+ <div class="contents">
+<h2>Table of Contents</h2>
+<ul>
+<li><a name="toc_License" href="License.html#License">MIT/X11 License</a>
+<li><a name="toc_Introduction" href="Introduction.html#Introduction">1 Introduction</a>
+<ul>
+<li><a href="Caveats.html#Caveats">1.1 Caveats</a>
+<li><a href="Kernel-History.html#Kernel-History">1.2 Kernel History</a>
+<li><a href="Conventions.html#Conventions">1.3 Conventions</a>
+<ul>
+<li><a href="Some-Terms.html#Some-Terms">1.3.1 Some Terms</a>
+<li><a href="Evaluation-Notation.html#Evaluation-Notation">1.3.2 Evaluation Notation</a>
+<li><a href="Printing-Notation.html#Printing-Notation">1.3.3 Printing Notation</a>
+<li><a href="Error-Messages.html#Error-Messages">1.3.4 Error Messages</a>
+<li><a href="Format-of-Descriptions.html#Format-of-Descriptions">1.3.5 Format of Descriptions</a>
+<ul>
+<li><a href="A-Sample-Applicative-Description.html#A-Sample-Applicative-Description">1.3.5.1 A Sample Applicative Description</a>
+</li></ul>
+</li></ul>
+<li><a href="Acknowledgements.html#Acknowledgements">1.4 Acknowledgements</a>
+</li></ul>
+<li><a name="toc_Booleans" href="Booleans.html#Booleans">2 Booleans</a>
+<li><a name="toc_Equivalence" href="Equivalence.html#Equivalence">3 Equivalence</a>
+<li><a name="toc_Symbols" href="Symbols.html#Symbols">4 Symbols</a>
+<li><a name="toc_Control" href="Control.html#Control">5 Control</a>
+<li><a name="toc_Pairs-and-lists" href="Pairs-and-lists.html#Pairs-and-lists">6 Pairs and lists</a>
+<li><a name="toc_Environments" href="Environments.html#Environments">7 Environments</a>
+<li><a name="toc_Combiners" href="Combiners.html#Combiners">8 Combiners</a>
+<li><a name="toc_Continuations" href="Continuations.html#Continuations">9 Continuations</a>
+<li><a name="toc_Encapsulations" href="Encapsulations.html#Encapsulations">10 Encapsulations</a>
+<li><a name="toc_Promises" href="Promises.html#Promises">11 Promises</a>
+<li><a name="toc_Keyed-Variables" href="Keyed-Variables.html#Keyed-Variables">12 Keyed Variables</a>
+<ul>
+<li><a href="Keyed-Variables.html#Keyed-Variables">12.1 Keyed Dynamic Variables</a>
+<li><a href="Keyed-Variables.html#Keyed-Variables">12.2 Keyed Static Variables</a>
+</li></ul>
+<li><a name="toc_Numbers" href="Numbers.html#Numbers">13 Numbers</a>
+<li><a name="toc_Strings" href="Strings.html#Strings">14 Strings</a>
+<li><a name="toc_Characters" href="Characters.html#Characters">15 Characters</a>
+<li><a name="toc_Ports" href="Ports.html#Ports">16 Ports</a>
+<li><a name="toc_Index" href="Index.html#Index">Index</a>
+</li></ul>
+</div>
+
+<!-- That's all -->
+</body></html>
+
diff --git a/manual/html/Introduction.html b/manual/html/Introduction.html
@@ -0,0 +1,92 @@
+<html lang="en">
+<head>
+<title>Introduction - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="License.html#License" title="License">
+<link rel="next" href="Booleans.html#Booleans" title="Booleans">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Introduction"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Booleans.html#Booleans">Booleans</a>,
+Previous: <a rel="previous" accesskey="p" href="License.html#License">License</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<h2 class="chapter">1 Introduction</h2>
+
+<p>klisp is an open source interpreter for the Kernel Programming
+Language. It aims at being comprehensive and robust as specified in
+the <cite>Revised(-1) Report on the Kernel Programming Language</cite>, but
+that probably won't happen for some time. It is written in C99 under
+the MIT license. It draws heavily from the Lua interpreter source
+code & file structure. It uses the IMath library for arbitrary sized
+integers and rationals.
+
+ <p>The Kernel programming language is a statically scoped and properly
+tail-recursive dialect of Lisp, descended from Scheme. It is designed
+to be simpler and more general than Scheme, with an exceptionally
+clear, simple, and versatile semantics, only one way to form compound
+expressions, and no inessential restrictions on the power of that one
+compound form. Imperative, functional, and message-passing programming
+styles (to name a few) may be conveniently expressed in Kernel.
+
+ <p>An important property of Kernel is that all manipulable entities in
+Kernel are first-class objects. In particular, Kernel has no
+second-class combiners; instead, the roles of special forms and macros
+are subsumed by operatives, which are first-class, statically scoped
+combiners that act directly on their unevaluated operands. Kernel
+also has a second type of combiners, applicatives, which act on their
+evalu- ated arguments. Applicatives are roughly equivalent to Scheme
+procedures. However, an applicative is nothing more than a wrapper to
+induce operand evaluation, around an underlying operative (or, in
+principle, around another applicative, though that isn’t usually
+done); applicatives themselves are mere facilitators to computation.
+
+ <p>You can read more about Kernel at
+<a href="http://web.cs.wpi.edu/~jshutt/kernel.html">http://web.cs.wpi.edu/~jshutt/kernel.html</a>.
+
+ <p>klisp is freely available for both academic and commercial purposes.
+See LICENSE for details. it can be downloaded at
+<a href="http://www.bitbucket.org/AndresNavarro/klisp">http://www.bitbucket.org/AndresNavarro/klisp</a>
+
+ <p>klisp is developed by Andres Navarro, a Computer Science
+undergraduate at Buenos Aires University (UBA). You can reach him at
+<a href="mailto:canavarro82@gmail.com">canavarro82@gmail.com</a>.
+
+ <p>This manual describes klisp version 0.1, presuming some familiarity
+with the Lisp family of languages in general, and with the Kernel
+Programming Language in particular. There are frequent references to
+the Kernel Programming Language Report. Unlike in the report, no
+rationale is provided for any feature, only a description of the
+implemented functionality.
+
+ <p>This is edition 0.1.
+
+<ul class="menu">
+<li><a accesskey="1" href="Caveats.html#Caveats">Caveats</a>: Flaws and a request for help.
+<li><a accesskey="2" href="Kernel-History.html#Kernel-History">Kernel History</a>: Kernel is descended from Scheme.
+<li><a accesskey="3" href="Conventions.html#Conventions">Conventions</a>: How the manual is formatted.
+<li><a accesskey="4" href="Acknowledgements.html#Acknowledgements">Acknowledgements</a>: Contributions to this manual.
+</ul>
+
+ </body></html>
+
diff --git a/manual/html/Kernel-History.html b/manual/html/Kernel-History.html
@@ -0,0 +1,64 @@
+<html lang="en">
+<head>
+<title>Kernel History - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Introduction.html#Introduction" title="Introduction">
+<link rel="prev" href="Caveats.html#Caveats" title="Caveats">
+<link rel="next" href="Conventions.html#Conventions" title="Conventions">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Kernel-History"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Conventions.html#Conventions">Conventions</a>,
+Previous: <a rel="previous" accesskey="p" href="Caveats.html#Caveats">Caveats</a>,
+Up: <a rel="up" accesskey="u" href="Introduction.html#Introduction">Introduction</a>
+<hr>
+</div>
+
+<h3 class="section">1.2 Kernel History</h3>
+
+<p><a name="index-Kernel-history-1"></a>
+ The Kernel Programming Language is a work in progress. It is being
+developed by John N. Shutt, Ph.D, who created it while studying at the
+Worcester Polytechnic Institute (I think about 2002, or so... ASK). It
+is descended from scheme, with the idea that all objects should be
+first class values. In particular, Kernel replaces macros with
+operatives (kinda like statically scoped fexprs and fsubrs) and has
+first class environments. Kernel also has the notion of encapsulated
+objects which limits the ammount of information an implementation can
+share with a Kernel program (e.g. There is no way in Kernel to get the
+parents or a complete list of bindings of an environment object).
+
+<!-- this is repeated above, in caveats -->
+ <p>The main reference on Kernel is the preliminary report:
+<cite>Revised(-1) Report on the Kernel Programming Language</cite>. Some
+sections of the report are still incomplete, so both klisp and this
+manual will use specifications from other languages in these sections,
+trying to follow the Kernel spirit. These instances will be documented
+throughout the manual.
+
+ <p>You can read all about Kernel at John's homepage at WPI
+<a href="http://www.cs.wpi.edu/~jshutt/">http://www.cs.wpi.edu/~jshutt/</a>, including the preliminary report
+on the language and his doctoral dissertation which gives a
+theorethical frame for fexprs. You can contact him at
+<a href="mailto:jshutt@cs.wpi.edu">jshutt@cs.wpi.edu</a>.
+
+ </body></html>
+
diff --git a/manual/html/Keyed-Variables.html b/manual/html/Keyed-Variables.html
@@ -0,0 +1,106 @@
+<html lang="en">
+<head>
+<title>Keyed Variables - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Promises.html#Promises" title="Promises">
+<link rel="next" href="Numbers.html#Numbers" title="Numbers">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Keyed-Variables"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Numbers.html#Numbers">Numbers</a>,
+Previous: <a rel="previous" accesskey="p" href="Promises.html#Promises">Promises</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">12 Keyed Variables</h2>
+
+<p><a name="index-keyed-variables-145"></a>
+ A keyed variable is a device that associates a non-symbolic key (in
+the form of an accessor applicative) with a value depending on the
+context in which lookup occurs. Kernel provides two types of keyed
+variables: dynamic & static. Keyed Dynamic Variables use the dynamic
+extent as context and Keyed Static Variables use the dynamic
+environment.
+
+<h3 class="section">12.1 Keyed Dynamic Variables</h3>
+
+<p><a name="index-keyed-dynamic-variables-146"></a><!-- add cf xref static -->
+<!-- TODO add xref to dynamic extent -->
+ A keyed dynamic variable is a device that associates a non-symbolic
+key (in the form of an accessor applicative) with a value depending on
+the dynamic extent in which lookup occurs.
+
+<div class="defun">
+— Applicative: <b>make-keyed-dynamic-variable</b> (<var>make-keyed-dynamic-variable</var>)<var><a name="index-make_002dkeyed_002ddynamic_002dvariable-147"></a></var><br>
+<blockquote><p> Returns a list of the form <code>(b a)</code>, where <code>b</code> and <code>a</code>
+are applicatives, as follows. Each call to
+<code>make-keyed-dynamic-variable</code> returns different <code>b</code> and
+<code>a</code>.
+
+ <ul>
+<li><code>b</code> is an applicative that takes two arguments, the second of
+which must be a combiner. It calls its second argument with no
+operands (nil operand tree) in a fresh empty environment, and returns
+the result.
+
+ <li><code>a</code> is an applicative that takes zero arguments. If the call to
+<code>a</code> occurs within the dynamic extent of a call to <code>b</code>, then
+<code>a</code> returns the value of the first argument passed to <code>b</code> in
+the smallest enclosing dynamic extent of a call to <code>b</code>. If the
+call to <code>a</code> is not within the dynamic extent of any call to
+<code>b</code>, an error is signaled.
+</ul>
+ </p></blockquote></div>
+
+<h3 class="section">12.2 Keyed Static Variables</h3>
+
+<p><a name="index-keyed-static-variables-148"></a> A keyed static variable is a device that binds data in an
+environment by a non-symbolic key, where the key is an accessor
+applicative.
+<!-- add cf xref dynamic -->
+
+<div class="defun">
+— Applicative: <b>make-keyed-static-variable</b> (<var>make-keyed-static-variable</var>)<var><a name="index-make_002dkeyed_002dstatic_002dvariable-149"></a></var><br>
+<blockquote><p> Returns a list of the form <code>(b a)</code>, where <code>b</code> and <code>a</code>
+are applicatives, as follows. Each call to <code>make-keyed-static-variable</code>
+returns different <code>b</code> and <code>a</code>.
+
+ <ul>
+<li><code>b</code> is an applicative that takes two arguments, the second of
+which must be an environment. It constructs and returns a
+child-environment of its second argument, with initially no local
+bindings.
+
+ <li><code>a</code> is an applicative that takes zero arguments. If the dynamic
+environment <code>e</code> of the call to a has an improper ancestor that
+was constructed by a call to <code>b</code>, then a returns the value of the
+first argument passed to <code>b</code> in the first such environment
+encountered by a depth-first traversal of the improper ancestors of
+<code>e</code>. If <code>e</code> has no improper ancestors constructed via
+<code>b</code>, an error is signaled.
+</ul>
+ </p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/License.html b/manual/html/License.html
@@ -0,0 +1,70 @@
+<html lang="en">
+<head>
+<title>License - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="index.html#Top" title="Top">
+<link rel="next" href="Introduction.html#Introduction" title="Introduction">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="License"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Introduction.html#Introduction">Introduction</a>,
+Previous: <a rel="previous" accesskey="p" href="index.html#Top">Top</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+ <p>klisp is licensed under the terms of the MIT license reproduced below.
+This means that klisp is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+The two projects whose code klisp uses, Lua & IMath, are also distributed
+under the MIT license.
+
+ <ul>
+<li>klisp Parts: Copyright © 2011 Andres Navarro.
+<li>Lua Parts: Copyright © 1994-2010 Lua.org, PUC-Rio.
+<li>IMath Parts: Copyright © 2002-2007 Michael J. Fromberger.
+<li>srfi-78: Copyright © 2005-2006 Sebastian Egner.
+</ul>
+
+<h2 class="unnumbered">MIT/X11 License</h2>
+
+<p>Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+ <p>The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+ <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+<!-- next node should be types -->
+ </body></html>
+
diff --git a/manual/html/Numbers.html b/manual/html/Numbers.html
@@ -0,0 +1,41 @@
+<html lang="en">
+<head>
+<title>Numbers - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Keyed-Variables.html#Keyed-Variables" title="Keyed Variables">
+<link rel="next" href="Strings.html#Strings" title="Strings">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Numbers"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Strings.html#Strings">Strings</a>,
+Previous: <a rel="previous" accesskey="p" href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">13 Numbers</h2>
+
+<p><a name="index-numbers-150"></a>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Pairs-and-lists.html b/manual/html/Pairs-and-lists.html
@@ -0,0 +1,466 @@
+<html lang="en">
+<head>
+<title>Pairs and lists - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Control.html#Control" title="Control">
+<link rel="next" href="Environments.html#Environments" title="Environments">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Pairs-and-lists"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Environments.html#Environments">Environments</a>,
+Previous: <a rel="previous" accesskey="p" href="Control.html#Control">Control</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">6 Pairs and lists</h2>
+
+<p><a name="index-pairs-33"></a><a name="index-nil-34"></a><a name="index-empty-list-35"></a><a name="index-lists-36"></a>
+A pair is an object that refers to two other objects, called its car
+and cdr. The Kernel data type pair is encapsulated.
+
+ <p>The null data type consists of a single immutable value, called nil
+or the empty list and having external representation <code>()</code>, with
+or without whitespace between the parentheses. It is immutable, and
+the null type is encapsulated.
+
+ <p>If <code>a</code> and <code>d</code> are external representations of
+respectively the car and cdr of a pair <code>p</code>, then <code>(a . d)</code>
+is an external representation of <code>p</code>. If the cdr of <code>p</code> is
+nil, then <code>(a)</code> is also an external representation of
+<code>p</code>. If the cdr of <code>p</code> is a pair <code>p2</code>, and <code>(r)</code>
+is an external representation of <code>p2</code>, then <code>(a r)</code> is an
+external representation of <code>p</code>.
+<!-- add xref for write -->
+ When a pair is output (as by write), an external representation with
+the fewest parentheses is used; in the case of a finite list, only one
+set of parentheses is required beyond those used in representing the
+elements of the list. For example, an object with external
+representation <code>(1 . (2 . (3 . ())))</code> would be output using,
+modulo whitespace, external representation <code>(1 2 3)</code>.
+
+<div class="defun">
+— Applicative: <b>pair?</b> (<var>pair? . objects</var>)<var><a name="index-pair_003f-37"></a></var><br>
+<blockquote><p> The primitive type predicate for type pair. <code>pair?</code> returns
+true iff all the objects in <code>objects</code> are of type pair.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>null?</b> (<var>null? . objects</var>)<var><a name="index-null_003f-38"></a></var><br>
+<blockquote><p> The primitive type predicate for type null. <code>null?</code> returns
+true iff all the objects in <code>objects</code> are of type null.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>cons</b> (<var>cons object1 object2</var>)<var><a name="index-cons-39"></a></var><br>
+<blockquote><p> A new mutable pair object is constructed and returned, whose car and
+cdr referents are respectively <code>object1</code> and <code>object2</code>. No
+two objects returned by different calls to cons are <code>eq?</code> to each
+other.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>set-car!</b> (<var>set-car! pair object</var>)<var><a name="index-set_002dcar_0021-40"></a></var><br>
+— Applicative: <b>set-cdr!</b> (<var>set-cdr! pair object</var>)<var><a name="index-set_002dcdr_0021-41"></a></var><br>
+<blockquote><p> <code>pair</code> should be a mutable pair.
+
+ <p>These applicatives set the referent of, respectively, the car
+reference or the cdr reference of <code>pair</code> to <code>object</code>. The
+result of the expression is inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>copy-es-immutable!</b> (<var>copy-es-immutable object</var>)<var><a name="index-copy_002des_002dimmutable_0021-42"></a></var><br>
+<blockquote><p> The short description of this applicative is that it returns an object
+<code>equal?</code> to <code>object</code> with an immutable evaluation structure. The
+“-es-” in the name is short for “evaluation structure”.
+
+ <!-- TODO move the evaluation structure description to the intro -->
+ <p>The evaluation structure of an object <code>o</code> is defined to be the
+set of all pairs that can be reached by following chains of references
+from <code>o</code> without ever passing through a non-pair object. The
+evaluation structure of a non-pair object is empty.
+
+ <p>If <code>object</code> is not a pair, the applicative returns <code>object</code>.
+Otherwise (if <code>object</code> is a pair), the applicative returns an
+immutable pair whose car and cdr would be suitable results for
+<code>(copy-es-immutable (car object))</code> and <code>(copy-es-immutable
+(cdr object))</code>, respectively. Further, the evaluation structure of
+<!-- TODO add xref for isomorphic (and add isomorphic to the intro) -->
+the returned value is isomorphic to that of <code>object</code> at the time
+of copying, with corresponding non-pair referents being <code>eq?</code>.
+
+ <p>NOTE: In Kernel it's undefined whether immutable pairs are copied or
+left “as is” in the result. klisp doesn't copy immutable pairs, but
+that behaviour should not be depended upon.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>list</b> (<var>list . objects</var>)<var><a name="index-list-43"></a></var><br>
+<blockquote><p>The <code>list</code> applicative returns <code>objects</code>.
+
+ <p>The underlying operative of <code>list</code> returns its undifferentiated
+operand tree, regardless of whether that tree is or is not a list.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>list*</b> (<var>list* . objects</var>)<var><a name="index-list_002a-44"></a></var><br>
+<blockquote><p><code>objects</code> should be a finite nonempty list of arguments.
+
+ <p>The following equivalences hold:
+ <pre class="example"> (list* arg1) == arg1
+ (list* arg1 arg2 . args) == (cons arg1 (list* arg2 . args))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>car</b> (<var>car pair</var>)<var><a name="index-car-45"></a></var><br>
+— Applicative: <b>cdr</b> (<var>cdr pair</var>)<var><a name="index-cdr-46"></a></var><br>
+<blockquote><p>These applicatives return, respectively, the car and cdr of <code>pair</code>.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>caar</b> (<var>caar pair</var>)<var><a name="index-caar-47"></a></var><br>
+— Applicative: <b>cadr</b> (<var>cadr pair</var>)<var><a name="index-cadr-48"></a></var><br>
+— Applicative: <b>cdar</b> (<var>cdar pair</var>)<var><a name="index-cdar-49"></a></var><br>
+— Applicative: <b>cddr</b> (<var>cddr pair</var>)<var><a name="index-cddr-50"></a></var><br>
+— Applicative: <b>caaar</b> (<var>caaar pair</var>)<var><a name="index-caaar-51"></a></var><br>
+— Applicative: <b>caadr</b> (<var>caadr pair</var>)<var><a name="index-caadr-52"></a></var><br>
+— Applicative: <b>cadar</b> (<var>cadar pair</var>)<var><a name="index-cadar-53"></a></var><br>
+— Applicative: <b>caddr</b> (<var>caddr pair</var>)<var><a name="index-caddr-54"></a></var><br>
+— Applicative: <b>cdaar</b> (<var>cdaar pair</var>)<var><a name="index-cdaar-55"></a></var><br>
+— Applicative: <b>cdadr</b> (<var>cdadr pair</var>)<var><a name="index-cdadr-56"></a></var><br>
+— Applicative: <b>cddar</b> (<var>cddar pair</var>)<var><a name="index-cddar-57"></a></var><br>
+— Applicative: <b>cdddr</b> (<var>cdddr pair</var>)<var><a name="index-cdddr-58"></a></var><br>
+— Applicative: <b>caaaar</b> (<var>caaaar pair</var>)<var><a name="index-caaaar-59"></a></var><br>
+— Applicative: <b>caaadr</b> (<var>caaadr pair</var>)<var><a name="index-caaadr-60"></a></var><br>
+— Applicative: <b>caadar</b> (<var>caadar pair</var>)<var><a name="index-caadar-61"></a></var><br>
+— Applicative: <b>caaddr</b> (<var>caaddr pair</var>)<var><a name="index-caaddr-62"></a></var><br>
+— Applicative: <b>cadaar</b> (<var>cadaar pair</var>)<var><a name="index-cadaar-63"></a></var><br>
+— Applicative: <b>cadadr</b> (<var>cadadr pair</var>)<var><a name="index-cadadr-64"></a></var><br>
+— Applicative: <b>caddar</b> (<var>caddar pair</var>)<var><a name="index-caddar-65"></a></var><br>
+— Applicative: <b>cadddr</b> (<var>cadddr pair</var>)<var><a name="index-cadddr-66"></a></var><br>
+— Applicative: <b>cdaaar</b> (<var>cdaaar pair</var>)<var><a name="index-cdaaar-67"></a></var><br>
+— Applicative: <b>cdaadr</b> (<var>cdaadr pair</var>)<var><a name="index-cdaadr-68"></a></var><br>
+— Applicative: <b>cdadar</b> (<var>cdadar pair</var>)<var><a name="index-cdadar-69"></a></var><br>
+— Applicative: <b>cdaddr</b> (<var>cdaddr pair</var>)<var><a name="index-cdaddr-70"></a></var><br>
+— Applicative: <b>cddaar</b> (<var>cddaar pair</var>)<var><a name="index-cddaar-71"></a></var><br>
+— Applicative: <b>cddadr</b> (<var>cddadr pair</var>)<var><a name="index-cddadr-72"></a></var><br>
+— Applicative: <b>cdddar</b> (<var>cdddar pair</var>)<var><a name="index-cdddar-73"></a></var><br>
+— Applicative: <b>cddddr</b> (<var>cddddr pair</var>)<var><a name="index-cddddr-74"></a></var><br>
+<blockquote>
+ <!-- TODO add note about pronunciation -->
+ <p>These applicatives are compositions of <code>car</code> and <code>cdr</code>, with
+the “a’s” and “d’s” in the same order as they would appear if all
+the individual “car’s” and “cdr’s” were written out in prefix
+order. Arbitrary compositions up to four deep are provided. There are
+twenty-eight of these applicatives in all.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>get-list-metrics</b> (<var>get-list-metrics object</var>)<var><a name="index-get_002dlist_002dmetrics-75"></a></var><br>
+<blockquote><!-- TODO move definition of improper list to intro, xref data structure -->
+ <p>By definition, an improper list is a data structure whose objects
+are its start together with all objects reachable from the start by
+following the cdr references of pairs, and whose internal references
+are just the cdr references of its pairs. Every object, of whatever
+type, is the start of an improper list. If the start is not a pair,
+the improper list consists of just that object. The acyclic prefix
+length of an improper list <code>L</code> is the number of pairs of <code>L</code>
+that a naive traversal of <code>L</code> would visit only once. The cycle
+length of <code>L</code> is the number of pairs of <code>L</code> that a naive
+traversal would visit repeatedly. Two improper lists are structurally
+<!-- TODO add xref to isomorphic -->
+isomorphic iff they have the same acyclic prefix length and cycle
+length and, if they are terminated by non-pair objects rather than by
+cycles, the non-pair objects have the same type. Applicative
+<code>get-list-metrics</code> constructs and returns a list of exact
+integers of the form <code>(p n a c)</code>, where <code>p</code>, <code>n</code>,
+<code>a</code>, and <code>c</code> are, respectively, the number of pairs in, the
+number of nil objects in, the acyclic prefix length of, and the cycle
+length of, the improper list starting with <code>object</code>. <code>n</code> is
+either <code>0</code> or <code>1</code>, <code>a + c = p</code>, and <code>n</code> and
+<code>c</code> cannot both be non-zero. If <code>c = 0</code>, the improper list
+is acyclic; if <code>n = 1</code>, the improper list is a finite list; if
+<code>n = c = 0</code>, the improper list is not a list; if <code>a = c =
+0</code>, <code>object</code> is not a pair.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>list-tail</b> (<var>list-tail object k</var>)<var><a name="index-list_002dtail-76"></a></var><br>
+<blockquote><p><code>object</code> must be the start of an improper list containing at
+least <code>k</code> pairs.
+
+ <p>The <code>list-tail</code> applicative follows <code>k</code> cdr references
+starting from <code>object</code>.
+
+ <p>The following equivalences hold:
+ <pre class="example"> (list-tail object 0) == object
+ (list-tail object (+ k 1)) == (list-tail (cdr object) k)
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>encycle!</b> (<var>encycle! object k1 k2</var>)<var><a name="index-encycle_0021-77"></a></var><br>
+<blockquote><p> The improper list starting at <code>object</code> must contain at least
+<code>k1 + k2</code> pairs.
+
+ <p>If <code>k2 = 0</code>, the applicative does nothing. If <code>k2 > 0</code>,
+the applicative mutates the improper list starting at <code>object</code> to
+have acyclic prefix length <code>k1</code> and cycle length <code>k2</code>, by
+setting the cdr of the <code>(k1+k2)</code>th pair in the list to refer to
+the <code>(k1 + 1)</code>th pair in the list. The result returned by
+<code>encycle!</code> is inert.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>map</b> (<var>map applicative . lists</var>)<var><a name="index-map-78"></a></var><br>
+<blockquote><p> <code>lists</code> must be a nonempty list of lists; if there are two or
+<!-- TODO add xref to length -->
+more, they must all have the same length.
+
+ <p>The map applicative applies <code>applicative</code> element-wise to the
+elements of the lists in lists (i.e., applies it to a list of the
+first elements of the lists, to a list of the second elements of the
+lists, etc.), using the dynamic environment from which map was called,
+and returns a list of the results, in order. The applications may be
+performed in any order, as long as their results occur in the
+resultant list in the order of their arguments in the original lists.
+If <code>lists</code> is a cyclic list, each argument list to which
+<!-- TODO xref to ismorphic -->
+<code>applicative</code> is applied is structurally isomorphic to <code>lists</code>. If
+any of the elements of <code>lists</code> is a cyclic list, they all must
+be, or they wouldn’t all have the same length. Let <code>a1...an</code> be
+their acyclic prefix lengths, and <code>c1...cn</code> be their cycle
+lengths. The acyclic prefix length <code>a</code> of the resultant list
+will be the maximum of the <code>ak</code>, while the cycle length <code>c</code>
+of the resultant list will be the least common multiple of the
+<code>ck</code>. In the construction of the result, <code>applicative</code> is
+called exactly <code>a + c</code> times.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>length</b> (<var>length object</var>)<var><a name="index-length-79"></a></var><br>
+<blockquote><!-- TODO xref improper-list -->
+ <p>Applicative <code>length</code> returns the (exact) improper-list length
+of <code>object</code>. That is, it returns the number of consecutive cdr
+references that can be followed starting from <code>object</code>. If
+<code>object</code> is not a pair, it returns zero; if <code>object</code> is a
+cyclic list, it returns positive infinity.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>list-ref</b> (<var>list-ref object k</var>)<var><a name="index-list_002dref-80"></a></var><br>
+<blockquote><p> The <code>list-ref</code> applicative returns the <code>car</code> of the object
+obtained by following <code>k</code> cdr references starting from
+<code>object</code>.
+
+ <p>NOTE: In the current report, object is required to be a list. In
+klisp, for now, we prefer the behaviour presented here, as it is more
+in line with the applicative <code>list-tail</code>. That is, we define
+<code>list-ref</code> by the following equivalence:
+ <pre class="example"> (list-ref object k) == (car (list-tail object k))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>append</b> (<var>append . lists</var>)<var><a name="index-append-81"></a></var><br>
+<blockquote><p> Here, all the elements of <code>lists</code> except the last element (if
+any) must be acyclic lists. The <code>append</code> applicative returns a
+freshly allocated list of the elements of all the specified
+<code>lists</code>, in order, except that if there is a last specified
+element of <code>lists</code>, it is not copied, but is simply referenced by
+the cdr of the preceding pair (if any) in the resultant list. If
+<code>lists</code> is cyclic, the cycle of the result list consists of just
+the elements of the lists specified in the cycle in <code>lists</code>. In
+this case, the acyclic prefix length of the result is the sum of the
+lengths of the lists specified in the acyclic prefix of <code>lists</code>,
+and the cycle length of the result is the sum of the lengths of the
+lists specified in the cycle of <code>lists</code>.
+
+ <p>The following equivalences hold:
+ <pre class="example"> (append) == ()
+ (append h) == h
+ (append () h . t) == (append h . t)
+ (append (cons a b) h . t) == (cons a (append b h . t))
+</pre>
+ <!-- TODO add xref/comp to append -->
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>list-neighbors</b> (<var>list-neighbors list</var>)<var><a name="index-list_002dneighbors-82"></a></var><br>
+<blockquote><p> The <code>list-neighbors</code> applicative constructs and returns a list
+of all the consecutive sublists of <code>list</code> of length 2, in order.
+If <code>list</code> is nil, the result is nil. If <code>list</code> is non-nil,
+the length of the result is one less than the length of
+<code>list</code>. If <code>list</code> is cyclic, the result is structurally
+isomorphic to it (i.e., has the same acyclic prefix length and cycle
+length).
+<!-- TODO add xref to isomorphic -->
+
+ <p>For example:
+ <pre class="example"> (list-neighbors (list 1 2 3 4)) ⇒ ((1 2) (2 3) (3 4))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>filter</b> (<var>filter applicative list</var>)<var><a name="index-filter-83"></a></var><br>
+<blockquote><p> Applicative <code>filter</code> passes each of the elements of <code>list</code>
+as an argument to <code>applicative</code>, one at a time in no particular
+order, using a fresh empty environment for each call. The result of
+each call to <code>applicative</code> must be boolean, otherwise an error is
+signaled. <code>filter</code> constructs and returns a list of all elements
+of <code>list</code> on which <code>applicative</code> returned true, in the same
+order as in <code>list</code>. <code>applicative</code> is called exactly as many
+times as there are pairs in <code>list</code>. The resultant list has a
+cycle containing exactly those elements accepted by <code>applicative</code>
+that were in the cycle of <code>list</code>; if there were no such elements,
+the result is acyclic.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>assoc</b> (<var>assoc object pairs</var>)<var><a name="index-assoc-84"></a></var><br>
+<blockquote><p> Applicative <code>assoc</code> returns the first element of <code>pairs</code>
+whose car is <code>equal?</code> to <code>object</code>. If there is no such
+element in <code>pairs</code>, nil is returned.
+<!-- TODO add xref/comp to assq -->
+<!-- TODO add xref to equal? -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>member?</b> (<var>member? object list</var>)<var><a name="index-member_003f-85"></a></var><br>
+<blockquote><p> Applicative <code>member?</code> is a predicate that returns true iff some
+element of <code>list</code> is <code>equal?</code> to <code>object</code>.
+<!-- TODO add xref/comp to memq -->
+<!-- TODO add xref to equal? -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>finite-list?</b> (<var>finite-list? . objects</var>)<var><a name="index-finite_002dlist_003f-86"></a></var><br>
+<blockquote><p> This is the type predicate for type finite-list.
+<code>finite-list?</code> returns true iff all the objects in
+<code>objects</code> are acyclic lists.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>countable-list?</b> (<var>countable-list? . objects</var>)<var><a name="index-countable_002dlist_003f-87"></a></var><br>
+<blockquote><p>This is the type predicate for type list. <code>countable-list?</code>
+returns true iff all the objects in <code>objects</code> are lists.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>reduce</b> (<var>reduce list binary identity </var>[<var>precycle incycle postcycle</var>])<var><a name="index-reduce-88"></a></var><br>
+<blockquote><p> <code>binary</code> should be an applicative. If the short form is used,
+<code>list</code> should be an acyclic. If the long form is used,
+<code>precycle</code>, <code>incycle</code>, and <code>postcycle</code> should be
+applicatives.
+
+ <p>If <code>list</code> is empty, applicative <code>reduce</code> returns
+<code>identity</code>. If <code>list</code> is nonempty but acyclic, applicative
+<code>reduce</code> uses binary operation <code>binary</code> to merge all the
+elements of <code>list</code> into a single object, using any associative
+grouping of the elements. That is, the sequence of objects initially
+found in <code>list</code> is repeatedly decremented in length by applying
+<code>binary</code> to a list of any two consecutive objects, replacing
+those two objects with the result at the point in the sequence where
+they occurred; and when the sequence contains only one object, that
+object is returned. If <code>list</code> is cyclic, the long form must be
+used. The elements of the cycle are passed, one at a time (but just
+once for each position in the cycle), as arguments to unary
+applicative <code>precycle</code>; the finite, cyclic sequence of results
+from <code>precycle</code> is reduced using binary applicative
+<code>incycle</code>; and the result from reducing the cycle is passed as an
+argument to unary applicative <code>postcycle</code>. Binary operation
+<code>binary</code> is used to reduce the sequence consisting of the
+elements of the acyclic prefix of <code>list</code> followed by the result
+returned by <code>postcycle</code>. The only constraint on the order of
+calls to the applicatives is that each call must be made before its
+result is needed (thus, parts of the reduction of the acyclic prefix
+may occur before the contribution from the cycle has been completed).
+
+ <p>Each call to <code>binary</code>, <code>precycle</code>, <code>incycle</code>, or
+<code>postcycle</code> uses the dynamic environment of the call to
+<code>reduce</code>.
+
+ <p>If <code>list</code> is acyclic with length <code>n >= 1</code>,
+<code>binary</code> is called <code>n - 1</code> times. If <code>list</code> is cyclic
+with acyclic prefix length <code>a</code> and cycle length <code>c</code>,
+<code>binary</code> is called <code>a</code> times; <code>precycle</code>, <code>c</code>
+times; <code>incycle</code>, <code>c - 1</code> times; and <code>postcycle</code>, once.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>append!</b> (<var>append! . lists</var>)<var><a name="index-append_0021-89"></a></var><br>
+<blockquote><p> <code>lists</code> must be a nonempty list; its first element must be an
+acyclic nonempty list, and all of its elements except the last element
+(if any) must be acyclic lists.
+
+ <p>The <code>append!</code> applicative sets the cdr of the last pair in each
+nonempty list argument to refer to the next non-nil argument, except
+that if there is a last non-nil argument, it isn’t mutated. It is an
+error for any two of the list arguments to have the same last pair.
+The result returned by this applicative is inert.
+
+ <p>The following equivalences hold:
+ <pre class="example"> (append! v) == #inert
+ (append! u v . w) == ($sequence (append! u v) (append! u . w))
+</pre>
+ </blockquote></div>
+
+<div class="defun">
+— Applicative: <b>copy-es</b> (<var>copy-es object</var>)<var><a name="index-copy_002des-90"></a></var><br>
+<blockquote><p> Briefly, applicative <code>copy-es</code> returns an object initially
+<code>equal?</code> to <code>object</code> with a freshly constructed evaluation
+<!-- TODO add xref to evaluation structure -->
+structure made up of mutable pairs. If <code>object</code> is not a pair,
+the applicative returns <code>object</code>. If <code>object</code> is a pair,
+the applicative returns a freshly constructed pair whose car and cdr
+would be suitable results for <code>(copy-es (car object))</code> and
+<code>(copy-es (cdr object))</code>, respectively. Further, the evaluation
+<!-- TODO add xref to isomorphic -->
+structure of the returned value is structurally isomorphic to that of
+<code>object</code> at the time of copying, with corresponding non-pair
+referents being <code>eq?</code>.
+<!-- TODO add xref/comp to copy-es-immutable and the reverse too! -->
+<!-- TODO add xref to eq?/equal? -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>assq</b> (<var>assq object pairs</var>)<var><a name="index-assq-91"></a></var><br>
+<blockquote><p> Applicative <code>assq</code> returns the first element of <code>pairs</code>
+whose car is <code>eq?</code> to <code>object</code>. If there is no such element
+in <code>pairs</code>, nil is returned.
+<!-- TODO add xref/comp to assoc -->
+<!-- TODO add xref to eq? -->
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>memq?</b> (<var>memq? object list</var>)<var><a name="index-memq_003f-92"></a></var><br>
+<blockquote><p> Applicative <code>memq?</code> is a predicate that returns true iff some
+element of <code>list</code> is <code>eq?</code> to <code>object</code>.
+<!-- TODO add xref/comp to member? -->
+<!-- TODO add xref to eq? -->
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Ports.html b/manual/html/Ports.html
@@ -0,0 +1,325 @@
+<html lang="en">
+<head>
+<title>Ports - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Characters.html#Characters" title="Characters">
+<link rel="next" href="Index.html#Index" title="Index">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Ports"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Index.html#Index">Index</a>,
+Previous: <a rel="previous" accesskey="p" href="Characters.html#Characters">Characters</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">16 Ports</h2>
+
+<p><a name="index-ports-153"></a>
+ A port is an object that mediates character-based input from a
+source or character-based output to a destination. In the former case,
+the port is an input port, in the latter case, an output port.
+
+<!-- TODO add xref to equal? & eq? -->
+ <p>Although ports are not considered immutable, none of the operations
+on ports described in this section constitute mutation. Ports are
+<code>equal?</code> iff <code>eq?</code>. The port type is encapsulated.
+
+ <p>An auxiliary data type used to signal the end of file was reached is
+eof. The eof type consists of a single immutable value, having
+an output only external representation (so that it can never be the
+normal result of a call to read). The eof type is encapsulated.
+
+ <p>SOURCE NOTE: the eof type is not in the Kernel report, it is used in
+klisp and was taken from Scheme.
+
+<div class="defun">
+— Applicative: <b>port?</b> (<var>port? . objects</var>)<var><a name="index-port_003f-154"></a></var><br>
+<blockquote><p> The primitive type predicate for type port. <code>port?</code>
+returns true iff all the objects in <code>objects</code> are of type port.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>input-port?</b> (<var>input-port? . objects</var>)<var><a name="index-input_002dport_003f-155"></a></var><br>
+— Applicative: <b>output-port?</b> (<var>output-port? . objects</var>)<var><a name="index-output_002dport_003f-156"></a></var><br>
+<blockquote><p> Applicative <code>input-port?</code> is a predicate that returns true
+unless one or more of its arguments is not an input port. Applicative
+output-port? is a predicate that returns true unless one or more of
+its arguments is not an output port.
+
+ <p>Every port must be admitted by at least one of these two predicates.
+</p></blockquote></div>
+
+<div class="defun">
+— with-input-from-file: <b>(</b><var>with-input-from-file string combiner</var>)<var><a name="index-g_t_0028-157"></a></var><br>
+— with-output-to-file: <b>(</b><var>with-output-to-file string combiner</var>)<var><a name="index-g_t_0028-158"></a></var><br>
+<blockquote><!-- add xref get-current-input-port/get-current-output-port -->
+ <p>These two applicatives open the file named in <code>string</code> for
+input or output, an invoke the binder of the input-port & output-port
+keyed dynamic variables respectively with the opened port & the passed
+<code>combiner</code> (this means that the combiner is called in a fresh, empty
+dynamic environment). When/if the binder normally returns, the port is closed.
+The result of the applicatives <code>with-input-from-file</code> and
+<code>with-output-from-file</code> is inert.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. In the new scheme report there's also a third
+error-port variable. It is very likely that that will be added to the
+klisp implementation in the near future.
+</p></blockquote></div>
+
+<div class="defun">
+— get-current-input-port: <b>(</b><var>get-current-input-port</var>)<var><a name="index-g_t_0028-159"></a></var><br>
+— get-current-output-port: <b>(</b><var>get-current-output-port</var>)<var><a name="index-g_t_0028-160"></a></var><br>
+<blockquote><p> These are the accessors for the input-port and output-port keyed
+dynamic variables repectively.
+<!-- add xref to with-input-from-file, etc -->
+<!-- add xref and text for these dynamic vars -->
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. In the new scheme report there's also a third
+error-port variable. It is very likely that that will be added to the
+klisp implementation in the near future.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>open-input-file</b> (<var>open-input-file string</var>)<var><a name="index-open_002dinput_002dfile-161"></a></var><br>
+<blockquote><p> <code>string</code> should be the name/path for an existing file.
+
+ <p>Applicative <code>open-input-file</code> creates and returns an input port
+associated with the file represented with <code>string</code>. If the file
+can't be opened (e.g. because it doesn't exists, or there's a
+permissions problem), an error is signaled.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>open-output-file</b> (<var>open-output-file string</var>)<var><a name="index-open_002doutput_002dfile-162"></a></var><br>
+<blockquote><p> <code>string</code> should be the name/path for an existing file.
+
+ <p>Applicative <code>open-output-file</code> creates and returns an output
+port associated with the file represented with <code>string</code>. If the
+file can't be opened (e.g. if there's a permissions problem), an error
+is signaled.
+
+ <p>In klisp, for now, applicative <code>open-output-file</code> truncates the
+file if it already exists, but that could change later (i.e. like in
+scheme the behaviour should be considered unspecified).
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+</p></blockquote></div>
+
+<div class="defun">
+— close-input-file: <b>(</b><var>close-input-file input-port</var>)<var><a name="index-g_t_0028-163"></a></var><br>
+— close-output-file: <b>(</b><var>close-output-file output-port</var>)<var><a name="index-g_t_0028-164"></a></var><br>
+<blockquote><p> These applicatives close the port argument, so that no more
+input/output may be performed on them, and the resources can be
+freed. If the port was already closed these applicatives have no
+effect.
+
+ <p>The result returned by applicatives <code>close-input-file</code> and
+<code>close-output-file</code> is inert.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. There's probably a name error here. These should
+probably be called close-input-port & close-output-port.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>read</b> (<var>read </var>[<var>input-port</var>])<var><a name="index-read-165"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>input-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>read</code> reads & returns the next parseable object
+from the given port, or the eof object if no objects remain. If
+<code>read</code> finds and unparseable object in the port, an error is
+signaled. In that case, the remaining position in the port is
+unspecified.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+</p></blockquote></div>
+
+<div class="defun">
+— write: <b>(</b><var>write object </var>[<var>port</var>])<var><a name="index-g_t_0028-166"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>output-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <!-- TODO add xref to external representation -->
+ <p>Applicative <code>write</code> writes an external representation of
+<code>object</code> to the specified port. This may be an output-only
+representation that can't be read by applicative <code>read</code> in cases
+where the type of <code>object</code> doen't have a parseable external
+representation (e.g. combiners and environments). The result returned
+by <code>write</code> is inert.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>call-with-input-file</b> (<var>call-with-input-file string combiner</var>)<var><a name="index-call_002dwith_002dinput_002dfile-167"></a></var><br>
+— Applicative: <b>call-with-output-file</b> (<var>call-with-output-file string combiner</var>)<var><a name="index-call_002dwith_002doutput_002dfile-168"></a></var><br>
+<blockquote><p> These applicatives open file named in <code>string</code> and call their
+<code>combiner</code> argument in a fresh empty environment passing it as a
+sole operand the opened port. When/if the combiner normally returns a
+value the port is closed and that value is returned as the result of
+the applicative.
+
+ <p>SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>load</b> (<var>load string</var>)<var><a name="index-load-169"></a></var><br>
+<blockquote><!-- TODO add xref, open/input, read -->
+ <p>Applicative <code>load</code> opens for input a file named <code>string</code>;
+reads objects from the file until the end of the file is reached;
+evaluates those objects consecutively in the created environment. The
+result from applicative <code>load</code> is inert.
+
+ <p>SOURCE NOTE: load is enumerated in the Kernel report, but the
+description is not there yet. This seems like a sane way to define
+it, taking the description of <code>get-module</code> that there is in the
+report. The one detail that I think is still open, is whether to
+return <code>#inert</code> (as is the case with klisp currently) or rather
+return the value of the last evaluation.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>get-module</b> (<var>get-module string </var>[<var>environment</var>])<var><a name="index-get_002dmodule-170"></a></var><br>
+<blockquote><!-- TODO add xref standard-environment, open/input, read -->
+ <p>Applicative <code>get-module</code> creates a fresh standard environment;
+opens for input a file named <code>string</code>; reads objects from the
+file until the end of the file is reached; evaluates those objects
+consecutively in the created environment; and, lastly, returns the
+created environment. If the optional argument <code>environment</code> is
+specified, the freshly created standard environment is augmented,
+prior to evaluating read expressions, by binding symbol
+<code>module-parameters</code> to the <code>environment</code> argument.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>eof-object?</b> (<var>eof-object? . objects</var>)<var><a name="index-eof_002dobject_003f-171"></a></var><br>
+<blockquote><p> The primitive type predicate for type eof. <code>eof-object?</code>
+returns true iff all the objects in <code>objects</code> are of type eof.
+
+ <p>SOURCE NOTE: This is not in the report, the idea is from Scheme.
+The <code>eof-object?</code> name is also from scheme, but this will
+probably be changed to just <code>eof?</code>, for consistency with the other
+primitive type predicates.
+</p></blockquote></div>
+
+<div class="defun">
+— read-char: <b>(</b><var>read-char </var>[<var>port</var>])<var><a name="index-g_t_0028-172"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>input-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>read-char</code> reads and returns a character (not
+an external representation of a character) from the specified port, or
+an eof if the end of file was reached.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<div class="defun">
+— peek-char: <b>(</b><var>peek-char </var>[<var>port</var>])<var><a name="index-g_t_0028-173"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>input-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>peek-char</code> reads and returns a character (not
+an external representation of a character) from the specified port, or
+an eof if the end of file was reached. The position of the port
+remains unchanged so that new call to <code>peek-char</code> or
+<code>read-char</code> on the same port return the same character.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<div class="defun">
+— char-ready?: <b>(</b><var>char-ready? </var>[<var>port</var>])<var><a name="index-g_t_0028-174"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>input-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Predicate <code>char-ready?</code> checks to see if a character is
+available in the specified port. If it returns true, then a
+<code>read-char</code> or <code>peek-char</code> on that port is guaranteed not to
+block/hang. For now in klisp this is hardcoded to <code>#t</code> because
+the code to do this is non-portable.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<div class="defun">
+— write-char: <b>(</b><var>write-char char </var>[<var>port</var>])<var><a name="index-g_t_0028-175"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>output-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>write-char</code> writes the <code>char</code> character (not
+an external representation of the character) to the specified port.
+The result returned by <code>write-char</code> is inert.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<div class="defun">
+— newline: <b>(</b><var>newline </var>[<var>port</var>])<var><a name="index-g_t_0028-176"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>output-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>newline</code> writes a newline to the specified port.
+The result returned by <code>newline</code> is inert.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<div class="defun">
+— display: <b>(</b><var>display object </var>[<var>port</var>])<var><a name="index-g_t_0028-177"></a></var><br>
+<blockquote><p> If the <code>port</code> optional argument is not specified, then the
+value of the <code>output-port</code> keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ <p>Applicative <code>display</code> behaves like <code>write</code> except that
+strings are not enclosed in double quotes and no character is escaped
+within those strings and character objects are output as if by
+<code>write-char</code> instead of <code>read</code>. The result returned by
+<code>display</code> is inert.
+
+ <p>SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+</p></blockquote></div>
+
+<!-- appendices -->
+<!-- TODO -->
+<!-- *-texinfo-*- -->
+<!-- TODO correct prev node -->
+ </body></html>
+
diff --git a/manual/html/Printing-Notation.html b/manual/html/Printing-Notation.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>Printing Notation - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Conventions.html#Conventions" title="Conventions">
+<link rel="prev" href="Evaluation-Notation.html#Evaluation-Notation" title="Evaluation Notation">
+<link rel="next" href="Error-Messages.html#Error-Messages" title="Error Messages">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Printing-Notation"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Error-Messages.html#Error-Messages">Error Messages</a>,
+Previous: <a rel="previous" accesskey="p" href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a>,
+Up: <a rel="up" accesskey="u" href="Conventions.html#Conventions">Conventions</a>
+<hr>
+</div>
+
+<h4 class="subsection">1.3.3 Printing Notation</h4>
+
+<p><a name="index-printing-notation-5"></a>
+ Many of the examples in this manual print text when they are
+evaluated. In examples that print text, the printed text is indicated with
+‘<samp><span class="samp">-|</span></samp>’. The value returned by evaluating the form (here
+<code>#t</code>) follows on a separate line.
+
+<pre class="example"> ($sequence (write 1) (write 2) #t)
+ -| 1
+ -| 2
+ ⇒ #t
+</pre>
+ </body></html>
+
diff --git a/manual/html/Promises.html b/manual/html/Promises.html
@@ -0,0 +1,125 @@
+<html lang="en">
+<head>
+<title>Promises - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Encapsulations.html#Encapsulations" title="Encapsulations">
+<link rel="next" href="Keyed-Variables.html#Keyed-Variables" title="Keyed Variables">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Promises"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a>,
+Previous: <a rel="previous" accesskey="p" href="Encapsulations.html#Encapsulations">Encapsulations</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">11 Promises</h2>
+
+<p><a name="index-promises-140"></a>
+<!-- TODO xref to $lazy, memoize, force -->
+A promise is an object that represents the potential to determine a
+value. The value may be the result of an arbitrary computation that
+will not be performed until the value must be determined (constructor
+<code>$lazy</code>); or, in advanced usage, the value may be determined
+before the promise is constructed (constructor <code>memoize</code>).
+
+ <p>The value determined by a promise is obtained by forcing it
+(applicative <code>force</code>). A given promise cannot determine
+different values on different occasions that it is forced. Also, if a
+promise determines its value by computation, and that computation has
+already been completed, forcing the promise again will produce the
+previously determined result without re-initiating the computation to
+determine it.
+
+ <p>The Kernel data type promise is encapsulated.
+
+<!-- TODO add xref to eq? and equal? -->
+ <p>The general rules for predicate <code>eq?</code> only require it to
+distinguish promises if they can exhibit different behavior; the
+resulting leeway for variation between implementations is similar, in
+both cause and effect, to that for <code>eq?</code>-ness of operatives. For
+example, if two promises, constructed on different occasions, would
+perform the same computation to determine their values, and that
+computation has no side-effects and must always return the same value,
+the promises may or may not be <code>eq?</code>. Two promises are
+<code>equal?</code> iff they are <code>eq?</code>.
+
+<div class="defun">
+— Applicative: <b>promise?</b> (<var>promise? . objects</var>)<var><a name="index-promise_003f-141"></a></var><br>
+<blockquote><p> The primitive type predicate for type promise. <code>promise?</code>
+returns true iff all the objects in <code>objects</code> are of type
+promise.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>force</b> (<var>force object</var>)<var><a name="index-force-142"></a></var><br>
+<blockquote><p> If <code>object</code> is a promise, applicative <code>force</code> returns the
+value determined by promise; otherwise, it returns <code>object</code>.
+
+ <p>The means used to force a promise depend on how the promise was
+constructed. The description of each promise constructor specifies
+how to force promises constructed by that constructor.
+</p></blockquote></div>
+
+<div class="defun">
+— Operative: <b>$lazy</b> (<var>$lazy expression</var>)<var><a name="index-g_t_0024lazy-143"></a></var><br>
+<blockquote><p> Operative <code>$lazy</code> constructs and returns a new object of type
+promise, representing potential evaluation of expression in the
+dynamic environment from which <code>$lazy</code> was called.
+
+ <p>When the promise is forced, if a value has not previously been
+determined for it, <code>expression</code> is evaluated in the dynamic
+environment of the constructing call to <code>$lazy</code>. If, when the
+evaluation returns a result, a value is found to have been determined
+for the promise during the evaluation, the result is discarded in
+favor of the previously determined value; otherwise, the result is
+forced, and the value returned by that forcing becomes the value
+determined by the promise.
+
+ <!-- TODO add xref to tail context -->
+ <p>Forcing an undetermined lazy promise (i.e., a promise constructed by
+$lazy for which no value has yet been determined) may cause a
+sequential series of evaluations, each of which returns a promise that
+is forced and thus initiates the next evaluation in the series. The
+implementation must support series of this kind with unbounded length
+(i.e., unbounded number of sequential evaluations).
+
+ <!-- TODO add xref to eq? -->
+ <p>Note that forcing concerns the value determined by a given promise,
+not the result of evaluating a given expression in a given
+environment. Distinct promises (judged by <code>eq?</code> represent
+different occasions of evaluation; so, even if they do represent
+evaluation of the same expression in the same environment, forcing one
+does not necessarily determine the value for the other, and actual
+evaluation will take place the first time each of them is forced.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>memoize</b> (<var>memoize object</var>)<var><a name="index-memoize-144"></a></var><br>
+<blockquote><p> Applicative <code>memoize</code> constructs and returns a new object of
+type promise, representing memoization of <code>object</code>. Whenever the
+promise is forced, it determines <code>object</code>.
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Some-Terms.html b/manual/html/Some-Terms.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>Some Terms - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Conventions.html#Conventions" title="Conventions">
+<link rel="prev" href="Conventions.html#Conventions" title="Conventions">
+<link rel="next" href="Evaluation-Notation.html#Evaluation-Notation" title="Evaluation Notation">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Some-Terms"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a>,
+Previous: <a rel="previous" accesskey="p" href="Conventions.html#Conventions">Conventions</a>,
+Up: <a rel="up" accesskey="u" href="Conventions.html#Conventions">Conventions</a>
+<hr>
+</div>
+
+<h4 class="subsection">1.3.1 Some Terms</h4>
+
+<p>Throughout this manual, the phrases “the Kernel reader” and “the Kernel
+printer” are used to refer to those routines in Lisp that convert
+textual representations of Kernel objects into actual objects, and
+<!-- TODO xref to printed representations -->
+vice versa. XXX Printed Representation XXX, for more details. You, the
+person reading this manual, are assumed to be “the programmer” or
+“the user”.
+
+ <p><a name="index-fonts-2"></a> Examples of Kernel code appear in this font or form: <code>(list 1 2
+3)</code>. Names that represent arguments or metasyntactic variables appear
+in this font or form: <var>first-number</var>.
+
+ </body></html>
+
diff --git a/manual/html/Strings.html b/manual/html/Strings.html
@@ -0,0 +1,41 @@
+<html lang="en">
+<head>
+<title>Strings - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Numbers.html#Numbers" title="Numbers">
+<link rel="next" href="Characters.html#Characters" title="Characters">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Strings"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Characters.html#Characters">Characters</a>,
+Previous: <a rel="previous" accesskey="p" href="Numbers.html#Numbers">Numbers</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">14 Strings</h2>
+
+<p><a name="index-strings-151"></a>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/Symbols.html b/manual/html/Symbols.html
@@ -0,0 +1,75 @@
+<html lang="en">
+<head>
+<title>Symbols - klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Equivalence.html#Equivalence" title="Equivalence">
+<link rel="next" href="Control.html#Control" title="Control">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<a name="Symbols"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="Control.html#Control">Control</a>,
+Previous: <a rel="previous" accesskey="p" href="Equivalence.html#Equivalence">Equivalence</a>,
+Up: <a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr>
+</div>
+
+<!-- node-name, next, previous, up -->
+<h2 class="chapter">4 Symbols</h2>
+
+<p><a name="index-symbols-22"></a><!-- TODO add xref to eq?, identifiers, etc -->
+ Two symbols are eq? iff they have the same external
+representation. Symbols are immutable, and the symbol type is
+encapsulated. The external representations of symbols are usually
+identifiers. However, symbols with other external representations may
+<!-- TODO add xref to string->symbol -->
+be created.
+
+<div class="defun">
+— Applicative: <b>symbol?</b> (<var>symbol? . objects</var>)<var><a name="index-symbol_003f-23"></a></var><br>
+<blockquote><p> The primitive type predicate for type symbol. <code>symbol?</code>
+returns true iff all the objects in <code>objects</code> are of type symbol.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>symbol->string</b> (<var>symbol->string symbol</var>)<var><a name="index-symbol_002d_003estring-24"></a></var><br>
+<blockquote><p> Applicative <code>symbol->string</code> returns the name of <code>symbol</code>
+as a string. The string returned is immutable.
+</p></blockquote></div>
+
+<div class="defun">
+— Applicative: <b>string->symbol</b> (<var>string->symbol string</var>)<var><a name="index-string_002d_003esymbol-25"></a></var><br>
+<blockquote><p> Applicative <code>string->symbol</code> returns the symbol with name
+<code>string</code>. The symbol is always interned, which means, that it is
+always the case that:
+ <pre class="example"> (eq? <symbol> (string->symbol (symbol->string <symbol>)))
+ ⇒ #t
+</pre>
+ <!-- TODO add xrefs for external representation -->
+ <p><code>string->symbol</code> can create symbols whose external
+representation aren't identifiers. Right now klisp uses an output-only
+representation, but in the near future it will probably include some
+kind of escaping mechanism to allow arbitrary symbols to have readable
+external representations as in R7RS Scheme.
+</p></blockquote></div>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/html/index.html b/manual/html/index.html
@@ -0,0 +1,66 @@
+<html lang="en">
+<head>
+<title>klisp Reference Manual</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="klisp Reference Manual">
+<meta name="generator" content="makeinfo 4.13">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="../index.html#dir" title="(dir)">
+<link rel="prev" href="../index.html#dir" title="(dir)">
+<link rel="next" href="License.html#License" title="License">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
+--></style>
+</head>
+<body>
+<h1 class="settitle">klisp Reference Manual</h1>
+<div class="node">
+<a name="Top"></a>
+<p>
+Next: <a rel="next" accesskey="n" href="License.html#License">License</a>,
+Previous: <a rel="previous" accesskey="p" href="../index.html#dir">(dir)</a>,
+Up: <a rel="up" accesskey="u" href="../index.html#dir">(dir)</a>
+<hr>
+</div>
+
+<ul class="menu">
+<li><a accesskey="1" href="License.html#License">License</a>: Conditions for copying and changing klisp.
+<li><a accesskey="2" href="Introduction.html#Introduction">Introduction</a>: Introduction and conventions used.
+<!-- TODO lisp types and other introductions -->
+<li><a accesskey="3" href="Booleans.html#Booleans">Booleans</a>: Booleans module features.
+<li><a accesskey="4" href="Equivalence.html#Equivalence">Equivalence</a>: Equivalence (under & up to) mutation modules features.
+<li><a accesskey="5" href="Symbols.html#Symbols">Symbols</a>: Symbols module features.
+<li><a accesskey="6" href="Control.html#Control">Control</a>: Control module features.
+<li><a accesskey="7" href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a>: Pairs and lists and Pair mutation modules features.
+<li><a accesskey="8" href="Environments.html#Environments">Environments</a>: Environments and Environment mutation modules features.
+<li><a accesskey="9" href="Combiners.html#Combiners">Combiners</a>: Combiners module features.
+<li><a href="Continuations.html#Continuations">Continuations</a>: Continuations module features.
+<li><a href="Encapsulations.html#Encapsulations">Encapsulations</a>: Encapsulations module features.
+<li><a href="Promises.html#Promises">Promises</a>: Promises module features.
+<li><a href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a>: Keyed (dynamic & static) variables module features.
+<li><a href="Numbers.html#Numbers">Numbers</a>: Numbers module features.
+<li><a href="Strings.html#Strings">Strings</a>: Strings module features.
+<li><a href="Characters.html#Characters">Characters</a>: Characters module features.
+<li><a href="Ports.html#Ports">Ports</a>: Ports module features.
+<!-- TODO add error objs to both klisp and the manual -->
+<li><a href="Index.html#Index">Index</a>: Index including concepts, functions, variables,
+ and other terms.
+
+<!-- Appendices -->
+<!-- TODO -->
+<!-- TODO add detailed node listing -->
+ </ul>
+
+<!-- *-texinfo-*- -->
+ </body></html>
+
diff --git a/manual/klisp.info b/manual/klisp.info
@@ -0,0 +1,2038 @@
+This is ../klisp.info, produced by makeinfo version 4.13 from
+klisp.texi.
+
+This file documents klisp.
+
+ This is edition 0.1 of the klisp Reference Manual, for klisp version
+0.1.
+
+ Copyright (C) 2011 Andres Navarro
+
+ Permission is granted to copy and distribute this manual, in whole or
+in part, without fee. Please note that most text of this manual is
+derived from `The Revised(-1) Report on the Kernel Programming
+Language' by John N. Shutt. There's a clause in that reports, under
+the header "Permission to copy this report", that reads:
+
+ This report is intended to belong to the programming community,
+ and so permission is granted to copy it in whole or in part
+ without fee.
+
+
+File: klisp.info, Node: Top, Next: License, Prev: (dir), Up: (dir)
+
+ This Info file contains edition 0.1 of the klisp Reference Manual,
+corresponding to klisp version 0.1.
+
+ Copyright (C) 2011 Andres Navarro
+
+ Permission is granted to copy and distribute this manual, in whole or
+in part, without fee. Please note that most text of this manual is
+derived from `The Revised(-1) Report on the Kernel Programming
+Language' by John N. Shutt. There's a clause in that reports, under
+the header "Permission to copy this report", that reads:
+
+ This report is intended to belong to the programming community,
+ and so permission is granted to copy it in whole or in part
+ without fee.
+
+* Menu:
+
+* License:: Conditions for copying and changing klisp.
+* Introduction:: Introduction and conventions used.
+* Booleans:: Booleans module features.
+* Equivalence:: Equivalence (under & up to) mutation modules features.
+* Symbols:: Symbols module features.
+* Control:: Control module features.
+* Pairs and lists:: Pairs and lists and Pair mutation modules features.
+* Environments:: Environments and Environment mutation modules features.
+* Combiners:: Combiners module features.
+* Continuations:: Continuations module features.
+* Encapsulations:: Encapsulations module features.
+* Promises:: Promises module features.
+* Keyed Variables:: Keyed (dynamic & static) variables module features.
+* Numbers:: Numbers module features.
+* Strings:: Strings module features.
+* Characters:: Characters module features.
+* Ports:: Ports module features.
+* Index:: Index including concepts, functions, variables,
+ and other terms.
+
+
+File: klisp.info, Node: License, Next: Introduction, Prev: Top, Up: Top
+
+ klisp is licensed under the terms of the MIT license reproduced
+below. This means that klisp is free software and can be used for both
+academic and commercial purposes at absolutely no cost. The two
+projects whose code klisp uses, Lua & IMath, are also distributed under
+the MIT license.
+
+ * klisp Parts: Copyright (C) 2011 Andres Navarro.
+
+ * Lua Parts: Copyright (C) 1994-2010 Lua.org, PUC-Rio.
+
+ * IMath Parts: Copyright (C) 2002-2007 Michael J. Fromberger.
+
+ * srfi-78: Copyright (C) 2005-2006 Sebastian Egner.
+
+MIT/X11 License
+***************
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+ The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+File: klisp.info, Node: Introduction, Next: Booleans, Prev: License, Up: Top
+
+1 Introduction
+**************
+
+klisp is an open source interpreter for the Kernel Programming
+Language. It aims at being comprehensive and robust as specified in
+the `Revised(-1) Report on the Kernel Programming Language', but that
+probably won't happen for some time. It is written in C99 under the
+MIT license. It draws heavily from the Lua interpreter source code &
+file structure. It uses the IMath library for arbitrary sized integers
+and rationals.
+
+ The Kernel programming language is a statically scoped and properly
+tail-recursive dialect of Lisp, descended from Scheme. It is designed
+to be simpler and more general than Scheme, with an exceptionally
+clear, simple, and versatile semantics, only one way to form compound
+expressions, and no inessential restrictions on the power of that one
+compound form. Imperative, functional, and message-passing programming
+styles (to name a few) may be conveniently expressed in Kernel.
+
+ An important property of Kernel is that all manipulable entities in
+Kernel are first-class objects. In particular, Kernel has no
+second-class combiners; instead, the roles of special forms and macros
+are subsumed by operatives, which are first-class, statically scoped
+combiners that act directly on their unevaluated operands. Kernel also
+has a second type of combiners, applicatives, which act on their evalu-
+ated arguments. Applicatives are roughly equivalent to Scheme
+procedures. However, an applicative is nothing more than a wrapper to
+induce operand evaluation, around an underlying operative (or, in
+principle, around another applicative, though that isn’t usually done);
+applicatives themselves are mere facilitators to computation.
+
+ You can read more about Kernel at
+`http://web.cs.wpi.edu/~jshutt/kernel.html'.
+
+ klisp is freely available for both academic and commercial purposes.
+See LICENSE for details. it can be downloaded at
+`http://www.bitbucket.org/AndresNavarro/klisp'
+
+ klisp is developed by Andres Navarro, a Computer Science
+undergraduate at Buenos Aires University (UBA). You can reach him at
+<canavarro82@gmail.com>.
+
+ This manual describes klisp version 0.1, presuming some familiarity
+with the Lisp family of languages in general, and with the Kernel
+Programming Language in particular. There are frequent references to
+the Kernel Programming Language Report. Unlike in the report, no
+rationale is provided for any feature, only a description of the
+implemented functionality.
+
+ This is edition 0.1.
+
+* Menu:
+
+* Caveats:: Flaws and a request for help.
+* Kernel History:: Kernel is descended from Scheme.
+* Conventions:: How the manual is formatted.
+* Acknowledgements:: Contributions to this manual.
+
+
+File: klisp.info, Node: Caveats, Next: Kernel History, Prev: Introduction, Up: Introduction
+
+1.1 Caveats
+===========
+
+This is the first draft of this manual. It will be incomplete for some
+time. It will also evolve, together with klisp and the Kernel
+Programming Language, both of which, right now, are in a quite fluid
+state.
+
+ The main reference on Kernel is the preliminary report: `Revised(-1)
+Report on the Kernel Programming Language'. Some sections of the
+report are still incomplete, so both klisp and this manual will use
+specifications from other languages in these sections, trying to follow
+the Kernel spirit. These instances will be documented throughout the
+manual.
+
+ Please mail comments and corrections to <canavarro82@gmail.com>.
+
+
+ -Andres Navarro
+
+
+File: klisp.info, Node: Kernel History, Next: Conventions, Prev: Caveats, Up: Introduction
+
+1.2 Kernel History
+==================
+
+The Kernel Programming Language is a work in progress. It is being
+developed by John N. Shutt, Ph.D, who created it while studying at the
+Worcester Polytechnic Institute (I think about 2002, or so... ASK). It
+is descended from scheme, with the idea that all objects should be
+first class values. In particular, Kernel replaces macros with
+operatives (kinda like statically scoped fexprs and fsubrs) and has
+first class environments. Kernel also has the notion of encapsulated
+objects which limits the ammount of information an implementation can
+share with a Kernel program (e.g. There is no way in Kernel to get the
+parents or a complete list of bindings of an environment object).
+
+ The main reference on Kernel is the preliminary report: `Revised(-1)
+Report on the Kernel Programming Language'. Some sections of the
+report are still incomplete, so both klisp and this manual will use
+specifications from other languages in these sections, trying to follow
+the Kernel spirit. These instances will be documented throughout the
+manual.
+
+ You can read all about Kernel at John's homepage at WPI
+`http://www.cs.wpi.edu/~jshutt/', including the preliminary report on
+the language and his doctoral dissertation which gives a theorethical
+frame for fexprs. You can contact him at <jshutt@cs.wpi.edu>.
+
+
+File: klisp.info, Node: Conventions, Next: Acknowledgements, Prev: Kernel History, Up: Introduction
+
+1.3 Conventions
+===============
+
+This section explains the notational conventions that are used in this
+manual. You may want to skip this section and refer back to it later.
+
+* Menu:
+
+* Some Terms:: Explanation of terms we use in this manual.
+* Evaluation Notation:: The format we use for examples of evaluation.
+* Printing Notation:: The format we use for examples that print output.
+* Error Messages:: The format we use for examples of errors.
+* Format of Descriptions:: Notation for describing functions, variables, etc.
+
+
+File: klisp.info, Node: Some Terms, Next: Evaluation Notation, Prev: Conventions, Up: Conventions
+
+1.3.1 Some Terms
+----------------
+
+Throughout this manual, the phrases "the Kernel reader" and "the Kernel
+printer" are used to refer to those routines in Lisp that convert
+textual representations of Kernel objects into actual objects, and vice
+versa. XXX Printed Representation XXX, for more details. You, the
+person reading this manual, are assumed to be "the programmer" or "the
+user".
+
+ Examples of Kernel code appear in this font or form: `(list 1 2 3)'.
+Names that represent arguments or metasyntactic variables appear in
+this font or form: FIRST-NUMBER.
+
+
+File: klisp.info, Node: Evaluation Notation, Next: Printing Notation, Prev: Some Terms, Up: Conventions
+
+1.3.2 Evaluation Notation
+-------------------------
+
+When you evaluate a piece of Kernel code, it produces a result. In the
+examples in this manual, this is indicated with `=>':
+
+ (car (cons 1 2))
+ => 1
+
+You can read this as "`(car (cons 1 2))' evaluates to 1".
+
+ The semantics of a language feature are sometimes clarified, or even
+defined, in its entry by specifying that two expressions are
+equivalent. This is notated with `=='. For example, the semantics of
+applicative list* can be defined by following equivalences:
+ (list* arg1) == arg1
+ (list* arg1 . more-args) == (cons arg1 (list* . more-args))
+ Notice that in these kind of examples the applicatives or operatives
+referred to are the first class values and not the symbols bound to
+them in the ground environment. This definition would hold even if
+`cons' or `list*' were redefined in the current dynamic environment.
+
+
+File: klisp.info, Node: Printing Notation, Next: Error Messages, Prev: Evaluation Notation, Up: Conventions
+
+1.3.3 Printing Notation
+-----------------------
+
+Many of the examples in this manual print text when they are evaluated.
+In examples that print text, the printed text is indicated with `-|'.
+The value returned by evaluating the form (here `#t') follows on a
+separate line.
+
+ ($sequence (write 1) (write 2) #t)
+ -| 1
+ -| 2
+ => #t
+
+
+File: klisp.info, Node: Error Messages, Next: Format of Descriptions, Prev: Printing Notation, Up: Conventions
+
+1.3.4 Error Messages
+--------------------
+
+Some examples cause errors to be signaled. The report doesn't specify
+what objects are passed to the error continuation, but in klisp,
+objects passed to the error continuation are encapsulated error objects
+that have at least a message and possibly some additional objects and
+context informations (such as source code location). In the examples,
+the error message is shown on a line starting with `error-->'.
+
+ (+ 23 #t)
+ error--> Wrong type argument: (expected number) (#t)
+
+
+File: klisp.info, Node: Format of Descriptions, Prev: Error Messages, Up: Conventions
+
+1.3.5 Format of Descriptions
+----------------------------
+
+Applicatives, operatives, and other objects are described in this manual
+in a uniform format. The first line of a description contains the name
+of the item followed by its operands or arguments, if any. The
+category--operative, applicative, or whatever--appears at the beginning
+of the line. The description follows on succeeding lines, sometimes
+with examples.
+
+* Menu:
+
+* A Sample Applicative Description::
+
+
+File: klisp.info, Node: A Sample Applicative Description, Prev: Format of Descriptions, Up: Format of Descriptions
+
+1.3.5.1 A Sample Applicative Description
+........................................
+
+In an applicative description, the name of the applicative being
+described appears first. It is followed on the same line by an
+applicative combination that includes the name of the applicative and
+the arguments, as would appear in a program. The names used for the
+arguments are also used in the body of the description.
+
+ Here is a description of an imaginary applicative `foo':
+
+ -- Applicative: foo (foo integer1 integer2 . rest)
+ The applicative `foo' subtracts INTEGER1 from INTEGER2, then adds
+ all the rest of the arguments to the result.
+
+ (foo 1 5 3 9)
+ => 16
+
+ More generally,
+
+ (foo W X Y...)
+ ==
+ (+ (- X W) Y...)
+
+ Any parameter whose name contains the name of a type (e.g., INTEGER,
+INTEGER1 or CONTINUATION) is expected to be of that type. A plural of
+a type (such as NUMBERS) often means a list of objects of that type.
+Parameters named OBJECT may be of any type. Additionally parameters
+named K, or KN (for any value of N), should be exact, non-negative
+integers. (XXX Types of Lisp Object XXX, for a list of Kernel object
+types.) Parameters with other sorts of names are discussed
+specifically in the description of the combiner. In some sections,
+features common to parameters of several combiners are described at the
+beginning.
+
+ Operative descriptions have the same format, but the word
+`Applicative' is replaced by `Operative', and `Argument' is replaced
+by `Operand'. Also Operatives always have an environment parameter
+(that can be #ignore or a symbol).
+
+
+File: klisp.info, Node: Acknowledgements, Prev: Conventions, Up: Introduction
+
+1.4 Acknowledgements
+====================
+
+This manual was written by Andres Navarro.
+
+ The structure and some text for this introductory section were
+borrowed from the Elisp Manual by the Free Sofware Foundation. This
+manual also borrows freely from both the Kernel Report and the Scheme
+Reports.
+
+
+File: klisp.info, Node: Booleans, Next: Equivalence, Prev: Introduction, Up: Top
+
+2 Booleans
+**********
+
+The boolean data type consists of two values, which are called true and
+false, and have respectively external representations `#t' and `#f'.
+There are no possible mutations of either of these two values, and the
+boolean type is encapsulated.
+
+ -- Applicative: boolean? (boolean? . objects)
+ The primitive type predicate for type boolean. `boolean?' returns
+ true iff all the objects in `objects' are of type boolean.
+
+ -- Applicative: not? (not? boolean)
+ Applicative `not?' is a predicate that returns the logical
+ negation of its argument.
+
+ -- Applicative: and? (and? . booleans)
+ Applicative `and?' is a predicate that returns true unless one or
+ more of its arguments are false.
+
+ -- Applicative: or? (or? . booleans)
+ Applicative `or?' is a predicate that returns false unless one or
+ more of its arguments are true.
+
+ -- Operative: $and? ($and? . <list>)
+ The `$and?' operative performs a "short-circuit and" of its
+ operands. It evaluates them from left to right, until either an
+ operand evaluates to false, or the end of the list is reached. If
+ the end of the list is reached (which is immediate if `<list>' is
+ `nil'), the operative returns true. If an operand evaluates to
+ false, no further operand evaluations are performed, and the
+ operative returns false. If `<list>' is acyclic, and the last
+ operand is evaluated, it is evaluated as a tail context. If
+ `<list>' is cyclic, an unbounded number of operand evaluations may
+ be performed. If any of the operands evaluates to a non-boolean
+ value, an error is signaled (even if it's the last one).
+
+ -- Operative: $or? ($or? . <list>)
+ The `$or?' operative performs a "short-circuit or" of its
+ operands. It evaluates them from left to right, until either an
+ operand evaluates to true, or the end of the list is reached. If
+ the end of the list is reached (which is immediate if `<list>' is
+ `nil'), the operative returns false. If an operand evaluates to
+ true, no further operand evaluations are performed, and the
+ operative returns true. If `<list>' is acyclic, and the last
+ operand is evaluated, it is evaluated as a tail context. If
+ `<list>' is cyclic, an unbounded number of operand evaluations may
+ be performed. If any of the operands evaluates to a non-boolean
+ value, an error is signaled (even if it's the last one).
+
+
+File: klisp.info, Node: Equivalence, Next: Symbols, Prev: Booleans, Up: Top
+
+3 Equivalence
+*************
+
+Kernel has two general-purpose equivalence predicates (whereas R5RS
+Scheme has three). The two Kernel predicates correspond to the
+abstract notions of equivalence up to mutation (`equal') and
+equivalence in the presence of mutation (`eq?').
+
+ -- Applicative: eq? (eq? . objects)
+ Predicate `eq?' returns true iff all of `objects' are effectively
+ the same object, even in the presence of mutation.
+
+ -- Applicative: equal? (equal? . objects)
+ Predicate `equal?' returns true iff all of `objects' "look" the
+ same as long as nothing is mutated. This is a weaker predicate
+ than `eq?'; that is, `equal?' must return true whenever `eq?'
+ would return true.
+
+
+File: klisp.info, Node: Symbols, Next: Control, Prev: Equivalence, Up: Top
+
+4 Symbols
+*********
+
+Two symbols are eq? iff they have the same external representation.
+Symbols are immutable, and the symbol type is encapsulated. The
+external representations of symbols are usually identifiers. However,
+symbols with other external representations may be created.
+
+ -- Applicative: symbol? (symbol? . objects)
+ The primitive type predicate for type symbol. `symbol?' returns
+ true iff all the objects in `objects' are of type symbol.
+
+ -- Applicative: symbol->string (symbol->string symbol)
+ Applicative `symbol->string' returns the name of `symbol' as a
+ string. The string returned is immutable.
+
+ -- Applicative: string->symbol (string->symbol string)
+ Applicative `string->symbol' returns the symbol with name
+ `string'. The symbol is always interned, which means, that it is
+ always the case that:
+ (eq? <symbol> (string->symbol (symbol->string <symbol>)))
+ => #t
+ `string->symbol' can create symbols whose external
+ representation aren't identifiers. Right now klisp uses an
+ output-only representation, but in the near future it will
+ probably include some kind of escaping mechanism to allow
+ arbitrary symbols to have readable external representations as in
+ R7RS Scheme.
+
+
+File: klisp.info, Node: Control, Next: Pairs and lists, Prev: Symbols, Up: Top
+
+5 Control
+*********
+
+The inert data type is provided for use with control combiners. It
+consists of a single immutable value, having external representation
+`#inert'. The inert type is encapsulated.
+
+ -- Applicative: inert? (inert? . objects)
+ The primitive type predicate for type inert. `inert?' returns true
+ iff all the objects in `objects' are of type inert.
+
+ -- Operative: $if ($if <test> <consequent> <alternative>)
+ The `$if' operative first evaluates `<test>' in the dynamic
+ environment. If the result is not of type boolean, an error is
+ signaled. If the result is true, `<consequent>' is then evaluated
+ in the dynamic environment as a tail context. Otherwise,
+ `<alternative>' is evaluated in the dynamic environment as a tail
+ context.
+
+ -- Operative: $sequence ($sequence . <objects>)
+ The `$sequence' operative evaluates the elements of the list
+ `<objects>' in the dynamic environment, one at a time from left to
+ right. If `<objects>' is a cyclic list, element evaluation
+ continues indefinitely, with elements in the cycle being evaluated
+ repeatedly. If `<objects>' is a nonempty finite list, its last
+ element is evaluated as a tail context. If `<objects>' is the
+ empty list, the result is inert.
+
+ -- Operative: $cond ($cond . <clauses>)
+ `<clauses>' should be a list of clause expressions, each of the
+ form `(<test> . <body>)', where body is a list of expressions.
+
+ The following equivalences define the behaviour of the `$cond'
+ operative:
+ ($cond) == #inert
+ ($cond (<test> . <body>) . <clauses>) ==
+ ($if <test> ($sequence . <body>) ($cond . <clauses>))
+
+ -- Applicative: for-each (for-each . lists)
+ `lists' must be a nonempty list of lists; if there are two or
+ more, they should all be the same length. If lists is empty, or if
+ all of its elements are not lists of the same length, an error is
+ signaled.
+
+ `for-each' behaves identically to `map', except that instead of
+ accumulating and returning a list of the results of the
+ element-wise applications, the results of the applications are
+ discarded and the result returned by `for-each' is inert.
+
+
+File: klisp.info, Node: Pairs and lists, Next: Environments, Prev: Control, Up: Top
+
+6 Pairs and lists
+*****************
+
+A pair is an object that refers to two other objects, called its car
+and cdr. The Kernel data type pair is encapsulated.
+
+ The null data type consists of a single immutable value, called nil
+or the empty list and having external representation `()', with or
+without whitespace between the parentheses. It is immutable, and the
+null type is encapsulated.
+
+ If `a' and `d' are external representations of respectively the car
+and cdr of a pair `p', then `(a . d)' is an external representation of
+`p'. If the cdr of `p' is nil, then `(a)' is also an external
+representation of `p'. If the cdr of `p' is a pair `p2', and `(r)' is
+an external representation of `p2', then `(a r)' is an external
+representation of `p'. When a pair is output (as by write), an
+external representation with the fewest parentheses is used; in the
+case of a finite list, only one set of parentheses is required beyond
+those used in representing the elements of the list. For example, an
+object with external representation `(1 . (2 . (3 . ())))' would be
+output using, modulo whitespace, external representation `(1 2 3)'.
+
+ -- Applicative: pair? (pair? . objects)
+ The primitive type predicate for type pair. `pair?' returns true
+ iff all the objects in `objects' are of type pair.
+
+ -- Applicative: null? (null? . objects)
+ The primitive type predicate for type null. `null?' returns true
+ iff all the objects in `objects' are of type null.
+
+ -- Applicative: cons (cons object1 object2)
+ A new mutable pair object is constructed and returned, whose car
+ and cdr referents are respectively `object1' and `object2'. No
+ two objects returned by different calls to cons are `eq?' to each
+ other.
+
+ -- Applicative: set-car! (set-car! pair object)
+ -- Applicative: set-cdr! (set-cdr! pair object)
+ `pair' should be a mutable pair.
+
+ These applicatives set the referent of, respectively, the car
+ reference or the cdr reference of `pair' to `object'. The result
+ of the expression is inert.
+
+ -- Applicative: copy-es-immutable! (copy-es-immutable object)
+ The short description of this applicative is that it returns an
+ object `equal?' to `object' with an immutable evaluation
+ structure. The "-es-" in the name is short for "evaluation
+ structure".
+
+ The evaluation structure of an object `o' is defined to be the set
+ of all pairs that can be reached by following chains of references
+ from `o' without ever passing through a non-pair object. The
+ evaluation structure of a non-pair object is empty.
+
+ If `object' is not a pair, the applicative returns `object'.
+ Otherwise (if `object' is a pair), the applicative returns an
+ immutable pair whose car and cdr would be suitable results for
+ `(copy-es-immutable (car object))' and `(copy-es-immutable (cdr
+ object))', respectively. Further, the evaluation structure of the
+ returned value is isomorphic to that of `object' at the time of
+ copying, with corresponding non-pair referents being `eq?'.
+
+ NOTE: In Kernel it's undefined whether immutable pairs are copied
+ or left "as is" in the result. klisp doesn't copy immutable
+ pairs, but that behaviour should not be depended upon.
+
+ -- Applicative: list (list . objects)
+ The `list' applicative returns `objects'.
+
+ The underlying operative of `list' returns its undifferentiated
+ operand tree, regardless of whether that tree is or is not a list.
+
+ -- Applicative: list* (list* . objects)
+ `objects' should be a finite nonempty list of arguments.
+
+ The following equivalences hold:
+ (list* arg1) == arg1
+ (list* arg1 arg2 . args) == (cons arg1 (list* arg2 . args))
+
+ -- Applicative: car (car pair)
+ -- Applicative: cdr (cdr pair)
+ These applicatives return, respectively, the car and cdr of `pair'.
+
+ -- Applicative: caar (caar pair)
+ -- Applicative: cadr (cadr pair)
+ -- Applicative: cdar (cdar pair)
+ -- Applicative: cddr (cddr pair)
+ -- Applicative: caaar (caaar pair)
+ -- Applicative: caadr (caadr pair)
+ -- Applicative: cadar (cadar pair)
+ -- Applicative: caddr (caddr pair)
+ -- Applicative: cdaar (cdaar pair)
+ -- Applicative: cdadr (cdadr pair)
+ -- Applicative: cddar (cddar pair)
+ -- Applicative: cdddr (cdddr pair)
+ -- Applicative: caaaar (caaaar pair)
+ -- Applicative: caaadr (caaadr pair)
+ -- Applicative: caadar (caadar pair)
+ -- Applicative: caaddr (caaddr pair)
+ -- Applicative: cadaar (cadaar pair)
+ -- Applicative: cadadr (cadadr pair)
+ -- Applicative: caddar (caddar pair)
+ -- Applicative: cadddr (cadddr pair)
+ -- Applicative: cdaaar (cdaaar pair)
+ -- Applicative: cdaadr (cdaadr pair)
+ -- Applicative: cdadar (cdadar pair)
+ -- Applicative: cdaddr (cdaddr pair)
+ -- Applicative: cddaar (cddaar pair)
+ -- Applicative: cddadr (cddadr pair)
+ -- Applicative: cdddar (cdddar pair)
+ -- Applicative: cddddr (cddddr pair)
+ These applicatives are compositions of `car' and `cdr', with the
+ "a’s" and "d’s" in the same order as they would appear if all the
+ individual "car’s" and "cdr’s" were written out in prefix order.
+ Arbitrary compositions up to four deep are provided. There are
+ twenty-eight of these applicatives in all.
+
+ -- Applicative: get-list-metrics (get-list-metrics object)
+ By definition, an improper list is a data structure whose objects
+ are its start together with all objects reachable from the start by
+ following the cdr references of pairs, and whose internal
+ references are just the cdr references of its pairs. Every
+ object, of whatever type, is the start of an improper list. If
+ the start is not a pair, the improper list consists of just that
+ object. The acyclic prefix length of an improper list `L' is the
+ number of pairs of `L' that a naive traversal of `L' would visit
+ only once. The cycle length of `L' is the number of pairs of `L'
+ that a naive traversal would visit repeatedly. Two improper lists
+ are structurally isomorphic iff they have the same acyclic prefix
+ length and cycle length and, if they are terminated by non-pair
+ objects rather than by cycles, the non-pair objects have the same
+ type. Applicative `get-list-metrics' constructs and returns a
+ list of exact integers of the form `(p n a c)', where `p', `n',
+ `a', and `c' are, respectively, the number of pairs in, the number
+ of nil objects in, the acyclic prefix length of, and the cycle
+ length of, the improper list starting with `object'. `n' is either
+ `0' or `1', `a + c = p', and `n' and `c' cannot both be non-zero.
+ If `c = 0', the improper list is acyclic; if `n = 1', the improper
+ list is a finite list; if `n = c = 0', the improper list is not a
+ list; if `a = c = 0', `object' is not a pair.
+
+ -- Applicative: list-tail (list-tail object k)
+ `object' must be the start of an improper list containing at least
+ `k' pairs.
+
+ The `list-tail' applicative follows `k' cdr references starting
+ from `object'.
+
+ The following equivalences hold:
+ (list-tail object 0) == object
+ (list-tail object (+ k 1)) == (list-tail (cdr object) k)
+
+ -- Applicative: encycle! (encycle! object k1 k2)
+ The improper list starting at `object' must contain at least `k1 +
+ k2' pairs.
+
+ If `k2 = 0', the applicative does nothing. If `k2 > 0', the
+ applicative mutates the improper list starting at `object' to have
+ acyclic prefix length `k1' and cycle length `k2', by setting the
+ cdr of the `(k1+k2)'th pair in the list to refer to the `(k1 +
+ 1)'th pair in the list. The result returned by `encycle!' is
+ inert.
+
+ -- Applicative: map (map applicative . lists)
+ `lists' must be a nonempty list of lists; if there are two or
+ more, they must all have the same length.
+
+ The map applicative applies `applicative' element-wise to the
+ elements of the lists in lists (i.e., applies it to a list of the
+ first elements of the lists, to a list of the second elements of
+ the lists, etc.), using the dynamic environment from which map was
+ called, and returns a list of the results, in order. The
+ applications may be performed in any order, as long as their
+ results occur in the resultant list in the order of their
+ arguments in the original lists. If `lists' is a cyclic list,
+ each argument list to which `applicative' is applied is
+ structurally isomorphic to `lists'. If any of the elements of
+ `lists' is a cyclic list, they all must be, or they wouldn’t all
+ have the same length. Let `a1...an' be their acyclic prefix
+ lengths, and `c1...cn' be their cycle lengths. The acyclic prefix
+ length `a' of the resultant list will be the maximum of the `ak',
+ while the cycle length `c' of the resultant list will be the least
+ common multiple of the `ck'. In the construction of the result,
+ `applicative' is called exactly `a + c' times.
+
+ -- Applicative: length (length object)
+ Applicative `length' returns the (exact) improper-list length of
+ `object'. That is, it returns the number of consecutive cdr
+ references that can be followed starting from `object'. If
+ `object' is not a pair, it returns zero; if `object' is a cyclic
+ list, it returns positive infinity.
+
+ -- Applicative: list-ref (list-ref object k)
+ The `list-ref' applicative returns the `car' of the object
+ obtained by following `k' cdr references starting from `object'.
+
+ NOTE: In the current report, object is required to be a list. In
+ klisp, for now, we prefer the behaviour presented here, as it is
+ more in line with the applicative `list-tail'. That is, we define
+ `list-ref' by the following equivalence:
+ (list-ref object k) == (car (list-tail object k))
+
+ -- Applicative: append (append . lists)
+ Here, all the elements of `lists' except the last element (if any)
+ must be acyclic lists. The `append' applicative returns a freshly
+ allocated list of the elements of all the specified `lists', in
+ order, except that if there is a last specified element of
+ `lists', it is not copied, but is simply referenced by the cdr of
+ the preceding pair (if any) in the resultant list. If `lists' is
+ cyclic, the cycle of the result list consists of just the elements
+ of the lists specified in the cycle in `lists'. In this case, the
+ acyclic prefix length of the result is the sum of the lengths of
+ the lists specified in the acyclic prefix of `lists', and the
+ cycle length of the result is the sum of the lengths of the lists
+ specified in the cycle of `lists'.
+
+ The following equivalences hold:
+ (append) == ()
+ (append h) == h
+ (append () h . t) == (append h . t)
+ (append (cons a b) h . t) == (cons a (append b h . t))
+
+ -- Applicative: list-neighbors (list-neighbors list)
+ The `list-neighbors' applicative constructs and returns a list of
+ all the consecutive sublists of `list' of length 2, in order. If
+ `list' is nil, the result is nil. If `list' is non-nil, the
+ length of the result is one less than the length of `list'. If
+ `list' is cyclic, the result is structurally isomorphic to it
+ (i.e., has the same acyclic prefix length and cycle length).
+
+ For example:
+ (list-neighbors (list 1 2 3 4)) => ((1 2) (2 3) (3 4))
+
+ -- Applicative: filter (filter applicative list)
+ Applicative `filter' passes each of the elements of `list' as an
+ argument to `applicative', one at a time in no particular order,
+ using a fresh empty environment for each call. The result of each
+ call to `applicative' must be boolean, otherwise an error is
+ signaled. `filter' constructs and returns a list of all elements
+ of `list' on which `applicative' returned true, in the same order
+ as in `list'. `applicative' is called exactly as many times as
+ there are pairs in `list'. The resultant list has a cycle
+ containing exactly those elements accepted by `applicative' that
+ were in the cycle of `list'; if there were no such elements, the
+ result is acyclic.
+
+ -- Applicative: assoc (assoc object pairs)
+ Applicative `assoc' returns the first element of `pairs' whose car
+ is `equal?' to `object'. If there is no such element in `pairs',
+ nil is returned.
+
+ -- Applicative: member? (member? object list)
+ Applicative `member?' is a predicate that returns true iff some
+ element of `list' is `equal?' to `object'.
+
+ -- Applicative: finite-list? (finite-list? . objects)
+ This is the type predicate for type finite-list. `finite-list?'
+ returns true iff all the objects in `objects' are acyclic lists.
+
+ -- Applicative: countable-list? (countable-list? . objects)
+ This is the type predicate for type list. `countable-list?'
+ returns true iff all the objects in `objects' are lists.
+
+ -- Applicative: reduce (reduce list binary identity [precycle incycle
+ postcycle])
+ `binary' should be an applicative. If the short form is used,
+ `list' should be an acyclic. If the long form is used, `precycle',
+ `incycle', and `postcycle' should be applicatives.
+
+ If `list' is empty, applicative `reduce' returns `identity'. If
+ `list' is nonempty but acyclic, applicative `reduce' uses binary
+ operation `binary' to merge all the elements of `list' into a
+ single object, using any associative grouping of the elements.
+ That is, the sequence of objects initially found in `list' is
+ repeatedly decremented in length by applying `binary' to a list of
+ any two consecutive objects, replacing those two objects with the
+ result at the point in the sequence where they occurred; and when
+ the sequence contains only one object, that object is returned.
+ If `list' is cyclic, the long form must be used. The elements of
+ the cycle are passed, one at a time (but just once for each
+ position in the cycle), as arguments to unary applicative
+ `precycle'; the finite, cyclic sequence of results from `precycle'
+ is reduced using binary applicative `incycle'; and the result from
+ reducing the cycle is passed as an argument to unary applicative
+ `postcycle'. Binary operation `binary' is used to reduce the
+ sequence consisting of the elements of the acyclic prefix of
+ `list' followed by the result returned by `postcycle'. The only
+ constraint on the order of calls to the applicatives is that each
+ call must be made before its result is needed (thus, parts of the
+ reduction of the acyclic prefix may occur before the contribution
+ from the cycle has been completed).
+
+ Each call to `binary', `precycle', `incycle', or `postcycle' uses
+ the dynamic environment of the call to `reduce'.
+
+ If `list' is acyclic with length `n >= 1', `binary' is called `n -
+ 1' times. If `list' is cyclic with acyclic prefix length `a' and
+ cycle length `c', `binary' is called `a' times; `precycle', `c'
+ times; `incycle', `c - 1' times; and `postcycle', once.
+
+ -- Applicative: append! (append! . lists)
+ `lists' must be a nonempty list; its first element must be an
+ acyclic nonempty list, and all of its elements except the last
+ element (if any) must be acyclic lists.
+
+ The `append!' applicative sets the cdr of the last pair in each
+ nonempty list argument to refer to the next non-nil argument,
+ except that if there is a last non-nil argument, it isn’t mutated.
+ It is an error for any two of the list arguments to have the same
+ last pair. The result returned by this applicative is inert.
+
+ The following equivalences hold:
+ (append! v) == #inert
+ (append! u v . w) == ($sequence (append! u v) (append! u . w))
+
+ -- Applicative: copy-es (copy-es object)
+ Briefly, applicative `copy-es' returns an object initially
+ `equal?' to `object' with a freshly constructed evaluation
+ structure made up of mutable pairs. If `object' is not a pair,
+ the applicative returns `object'. If `object' is a pair, the
+ applicative returns a freshly constructed pair whose car and cdr
+ would be suitable results for `(copy-es (car object))' and
+ `(copy-es (cdr object))', respectively. Further, the evaluation
+ structure of the returned value is structurally isomorphic to that
+ of `object' at the time of copying, with corresponding non-pair
+ referents being `eq?'.
+
+ -- Applicative: assq (assq object pairs)
+ Applicative `assq' returns the first element of `pairs' whose car
+ is `eq?' to `object'. If there is no such element in `pairs', nil
+ is returned.
+
+ -- Applicative: memq? (memq? object list)
+ Applicative `memq?' is a predicate that returns true iff some
+ element of `list' is `eq?' to `object'.
+
+
+File: klisp.info, Node: Environments, Next: Combiners, Prev: Pairs and lists, Up: Top
+
+7 Environments
+**************
+
+An environment consists of a set of bindings, and a list of zero or
+more references to other environments called its parents. Changing the
+set of bindings of an environment, or setting the referent of the
+reference in a binding, is a mutation of the environment. (Changing the
+parent list, or a referent in the list, would be a mutation of the
+environment too, but there is no facility provided to do it.) The
+Kernel data type environment is encapsulated. Among other things,
+there is no facility provided for enumerating all the variables
+exhibited by an environment (which is not required, after all, to be a
+finite set), and no facility for identifying the parents of an
+environment. Two environments are `equal?' iff they are `eq?'.
+
+ An auxiliary data type used by combiners that perform binding is
+ignore. The ignore type consists of a single immutable value, having
+external representation `#ignore'. The ignore type is encapsulated.
+
+ -- Applicative: environment? (environment? . objects)
+ The primitive type predicate for type environment. `environment?'
+ returns true iff all the objects in `objects' are of type
+ environment.
+
+ -- Applicative: ignore? (ignore? . objects)
+ The primitive type predicate for type ignore. `ignore?' returns
+ true iff all the objects in `objects' are of type ignore.
+
+ -- Applicative: eval (eval expression environment)
+ The `eval' applicative evaluates `expression' as a tail context in
+ `environment', and returns the resulting value.
+
+ -- Applicative: make-environment (make-environment . environments)
+ The applicative constructs and returns a new environment, with
+ initially no local bindings, and parent environments the
+ environments listed in `environments'. The constructed environment
+ internally stores its list of parents independent of the
+ first-class list `environments', so that subsequent mutation of
+ `environments' will not change the parentage of the constructed
+ environment. If the provided list `environments' is cyclic, the
+ constructed environment will still check each of its parents at
+ most once, and signal an error if no binding is found locally or
+ in any of the parents. No two objects returned by different calls
+ to `make-environment' are `eq?' to each other.
+
+ -- Operative: $define! ($define! <definiend> <expression>)
+ `<definiend>' should be a formal parameter tree, as described
+ below; otherwise, an error is signaled.
+
+ The `$define!' operative evaluates `<expression>' in the dynamic
+ environment and matches `<definiend>' to the result in the dynamic
+ environment, binding each symbol in definiend in the dynamic
+ environment to the corresponding part of the result; the matching
+ process will be further described below. The ancestors of the
+ dynamic environment, if any, are unaffected by the matching
+ process, as are all bindings, local to the dynamic environment, of
+ symbols not in `<definiend>'. The result returned by `$define!' is
+ inert.
+
+ A formal parameter tree has the following context-free structure:
+ ptree:: symbol | #ignore | () | (ptree . ptree)
+
+ That is, a formal parameter tree is either a symbol, or ignore, or
+ nil, or a pair whose car and cdr referents are formal parameter
+ trees. A formal parameter tree must also be acyclic, and no one
+ symbol can occur more than once in it. It is not an error for a
+ pair in the tree to be reachable from the root by more than one
+ path, as long as there is no cycle; but if any particular symbol
+ were reachable from the root by more than one path, that would
+ count as occurring more than once. Thus, if a pair is reachable
+ by more than one path, there must be no symbols reachable from it.
+
+ Matching of a formal parameter tree `t' to an object `o' in an
+ environment `e' proceeds recursively as follows. If the matching
+ process fails, an error is signaled.
+ * If `t' is a symbol, then `t' is bound to `o' in `e'.
+
+ * If `t' is `#ignore', no action is taken.
+
+ * If `t' is nil, then `o' must be nil (else matching fails).
+
+ * If `t' is a pair, then `o' must be a pair (else matching
+ fails). The car of `t' is matched to the car of `o' in `e',
+ and the cdr of `t' is matched to the cdr of `o' in `e'.
+
+ -- Operative: $let ($let <bindings> . <objects>)
+ `<bindings>' should be a finite list of
+ formal-parameter-tree/expression pairings, each of the form
+ `(formals expression)', where each `formals' is a formal
+ parameter, and no symbol occurs in more than one of the `formals'.
+
+ The following equivalence holds:
+
+ ($let ((form1 exp1) ... (formn expn)) . objects) ==
+ (($lambda (form1 ... formn) . objects) exp1 ... expn)
+
+ Thus, the `expk' are first evaluated in the dynamic environment,
+ in any order; then a child environment `e' of the dynamic
+ environment is created, with the `formk' matched in `e' to the
+ results of the evaluations of the `expk'; and finally the
+ subexpressions of `objects' are evaluated in `e' from left to
+ right, with the last (if any) evaluated as a tail context, or if
+ `objects' is empty the result is inert.
+
+ -- Operative: $binds? ($binds? <exp> . <symbols>)
+ Operative `$binds' evaluates `<exp>' in the dynamic environment;
+ call the result `env'. `env' must be an environment. The
+ operative is a predicate that returns true iff all its later
+ operands, `<symbols>', are visibly bound in `env'.
+
+ -- Applicative: get-current-environment (get-current-environment)
+ The `get-current-environment' applicative returns the dynamic
+ environment in which it is called.
+
+ -- Applicative: make-kernel-standard-environment
+ (make-kernel-standard-environment)
+ The `make-kernel-standard-environment' applicative returns a
+ standard environment; that is, a child of the ground environment
+ with no local bindings.
+
+ -- Operative: $let* ($let* <bindings> . <body>)
+ `<bindings>' should be a finite list of
+ formal-parameter-tree/expression pairings, each of the form
+ `(formals expression)', where each `formals' is a formal parameter
+ tree; `<body>' should be a list of expressions.
+
+ The following equivalences hold:
+
+ ($let* () . body) == ($let () . body)
+
+ ($let* ((form exp) . bindings) . body) ==
+ ($let ((form exp)) ($let* bindings . body))
+
+ -- Operative: $letrec ($letrec <bindings> . <body>)
+ `<bindings>' and `<body>' should be as described for `$let'.
+
+ The following equivalence holds:
+ ($letrec ((form1 exp1) ... (formn expn)) . body) ==
+ ($let () ($define! (form1 ... formn) (list exp1 ... expn)) . body)
+
+ -- Operative: $letrec* ($letrec* <bindings> . <body>)
+ `<bindings>' and `<body>' should be as described for `$let*'.
+
+ The following equivalences hold:
+ ($letrec* () . body) == ($letrec () . body)
+
+ ($letrec* ((form exp) . bindings) . body) ==
+ ($letrec ((form exp)) ($letrec* bindings . body))
+
+ -- Operative: $let-redirect ($let-redirect <exp> <bindings> . <body>)
+ `<bindings>' and `<body>' should be as described for `$let'.
+
+ The following equivalence holds:
+
+ ($let-redirect exp ((form1 exp1) ... (formn . body) expn)) ==
+ ((eval (list $lambda (form1 ... formn) body) exp) expn ... expn)
+
+ -- Operative: $let-safe ($let-safe <bindings> . <body>)
+ `<bindings>' and `<body>' should be as described for `$let'.
+
+ The following equivalence holds:
+
+ ($let-safe bindings . body) ==
+ ($let-redirect (make-kernel-standard-environment) bindings . body)
+
+ -- Operative: $remote-eval ($remote-eval <exp1> <exp2>)
+ Operative `$remote-eval' evaluates `<exp2>' in the dynamic
+ environment, then evaluates `<exp1>' as a tail context in the
+ environment that must result from the first evaluation.
+
+ -- Operative: ($bindings-environment . <bindings>)
+ `<bindings>' should be as described for `$let'.
+
+ The following equivalence holds:
+
+ ($bindings->environment . bindings) ==
+ ($let-redirect (make-environment) bindings (get-current-environment))
+
+ -- Operative: $set! ($set! <exp1> <formals> <exp2>)
+ `<formals>' should be as described for the `$define!' operative.
+ The `$set!' operative evaluates `<exp1>' and `<exp2>' in the
+ dynamic environment; call the results `env' and `obj'. If `env'
+ is not an environment, an error is signaled. Then the operative
+ matches `<formals>' to `obj' in environment `env'. Thus, the
+ symbols of `<formals>' are bound in `env' to the corresponding
+ parts of `obj'. The result returned by `$set!' is inert.
+
+ -- Operative: $provide! ($provide! <symbols> . <body>)
+ `<symbols>' must be a finite list of symbols, containing no
+ duplicates. `<body>' must be a finite list.
+
+ The `$provide!' operative constructs a child `e' of the dynamic
+ environment `d'; evaluates the elements of `<body>' in `e', from
+ left to right, discarding all of the results; and exports all of
+ the bindings of symbols in `<symbols>' from `e' to `d', i.e.,
+ binds each symbol in `d' to the result of looking it up in `e'.
+ The result returned by `$provide!' is inert.
+
+ The following equivalence holds:
+
+ ($provide! symbols . body) ==
+ ($define! symbols ($let () ($sequence . body) (list . symbols)))
+
+ -- Operative: $import! ($import! <exp> . <symbols>)
+ `<symbols>' must be a list of symbols.
+
+ The `$import!' operative evaluates `<exp>' in the dynamic
+ environment; call the result `env'. `env' must be an environment.
+ Each distinct symbol `s' in `<symbols>' is evaluated in `env', and
+ `s' is bound in the dynamic environment to the result of this
+ evaluation.
+
+ The following equivalence holds:
+
+ ($import! exp . symbols) ==
+ ($define! symbols ($remote-eval (list symbols) exp))
+
+
+File: klisp.info, Node: Combiners, Next: Continuations, Prev: Environments, Up: Top
+
+8 Combiners
+***********
+
+There are two types of combiners in Kernel, operative and applicative.
+Both types are encapsulated. All combiners are immutable. Two
+applicatives are `eq?' iff their underlying combiners are `eq?'.
+However, `eq?'-ness of operatives is only constrained by the general
+rules for `eq?', which leave considerable leeway for variation between
+implementations. klisp only considers `eq?' those operatives
+constructed by the same call to a constructor (e.g. `$vau'). Two
+combiners are `equal?' iff they are `eq?'.
+
+ -- Applicative: operative? (operative? . objects)
+ The primitive type predicate for type operative. `operative?'
+ returns true iff all the objects in `objects' are of type
+ operative.
+
+ -- Applicative: applicative? (applicative? . objects)
+ The primitive type predicate for type applicative. `applicative?'
+ returns true iff all the objects in `objects' are of type
+ applicative.
+
+ -- Operative: $vau ($vau <formals> <eformal> . <objects>)
+ `<formals>' should be a formal parameter tree; `<eformal>' should
+ be either a symbol or `#ignore'. If `<formals>' does not have the
+ correct form for a formal parameter tree, or if `<eformal>' is a
+ symbol that also occurs in `<formals>', an error is signaled.
+
+ A `vau' expression evaluates to an operative; an operative created
+ in this way is said to be compound. The environment in which the
+ `vau' expression was evaluated is remembered as part of the
+ compound operative, called the compound operative’s static
+ environment. `<formals>' and `<objects>' are copied as by
+ `copy-es-immutable' and the copies are stored as part of the
+ operative being constructed. This avoids problem if these
+ structures are later mutated.
+
+ When the compound operative created by `$vau' is later called with
+ an object and an environment, here called respectively the operand
+ tree and the dynamic environment, the following happens:
+
+ 1. A new, initially empty environment is created, with the static
+ environment as its parent. This will be called the local
+ environment.
+
+ 2. A stored copy of the formal parameter tree formals is matched
+ in the local environment to the operand tree, locally binding
+ the symbols of formals to the corresponding parts of the
+ operand tree. eformal is matched to the dynamic environment;
+ that is, if eformal is a symbol then that symbol is bound in
+ the local environment to the dynamic environment.
+
+ 3. A stored copy of the expressions is evaluated sequentially
+ from left to right, with the last (if any) evaluated as a
+ tail context, or if the list of expressions is empty, the
+ result is inert.
+
+ NOTE: Because compound operatives are not a distinct type in
+ Kernel, they are covered by the encapsulation of type operative.
+ In particular, an implementation of Kernel cannot provide a
+ feature that supports extracting the static environment of any
+ given compound operative, nor that supports determining whether or
+ not a given operative is compound.
+
+ -- Applicative: wrap (wrap combiner)
+ The `wrap' applicative returns an applicative whose underlying
+ combiner is `combiner'.
+
+ -- Applicative: unwrap (unwrap applicative)
+ The `unwrap' applicative returns the underlying combiner of
+ `applicative'.
+
+ -- Operative: $lambda ($lambda <formals> . <objects>)
+ `<formals>' should be a formal parameter tree.
+
+ The `$lambda' operative is defined by the following equivalence:
+ ($lambda formals . objects) ==
+ (wrap ($vau formals #ignore . objects))
+
+ -- Applicative: apply (apply applicative object [environment])
+ Applicative `apply' combines the underlying combiner of
+ `applicative' with `object' in a tail context with dynamic
+ environment `environment' (if the long form is used) or in an
+ empty environment (if the short form is used).
+
+ The following equivalences hold:
+ (apply applicative object environment) ==
+ (eval (cons (unwrap applicative) object) environment)
+
+ (apply applicative object) ==
+ (apply applicative object (make-environment))
+
+ -- Applicative: map (map applicative . lists)
+ `lists' must be a nonempty list of lists; if there are two or
+ more, they must all have the same length. If `lists' is empty, or
+ if all of its elements are not lists of the same length, an error
+ is signaled.
+
+ The `map' applicative applies `applicative' element-wise to the
+ elements of the lists in `lists' (i.e., applies it to a list of
+ the first elements of the `lists', to a list of the second
+ elements of the `lists', etc.), using the dynamic environment from
+ which `map' was called, and returns a list of the results, in
+ order. The applications may be performed in any order, as long as
+ their results occur in the resultant list in the order of their
+ arguments in the original `lists'. If `lists' is a cyclic list,
+ each argument list to which `applicative' is applied is
+ structurally isomorphic to `lists'. If any of the elements of
+ `lists' is a cyclic list, they all must be, or they wouldn’t all
+ have the same length. Let `a1...an' be their acyclic prefix
+ lengths, and `c1...cn' be their cycle lengths. The acyclic prefix
+ length `a' of the resultant list will be the maximum of the `ak',
+ while the cycle length `c' of the resultant list will be the least
+ common multiple of the `ck'. In the construction of the result,
+ applicative is called exactly `a + c' times.
+
+ -- Applicative: combiner? (combiner? . objects)
+ The primitive type predicate for type combiner. `combiner?'
+ returns true iff all the objects in `objects' are of type combiner
+ (i.e. applicative or operative).
+
+
+File: klisp.info, Node: Continuations, Next: Encapsulations, Prev: Combiners, Up: Top
+
+9 Continuations
+***************
+
+A continuation is a plan for all future computation, parameterized by a
+value to be provided, and contingent on the states of all mutable data
+structures (which notably may include environments). When the Kernel
+evaluator is invoked, the invoker provides a continuation to which the
+result of the evaluation will normally be returned.
+
+ For example, when `$if' evaluates its test operand, the continuation
+provided for the result expects to be given a boolean value; and,
+depending on which boolean it gets, it will evaluate either the
+consequent or the alternative operand as a tail context — that is, the
+continuation provided for the result of evaluating the selected operand
+is the same continuation that was provided for the result of the call
+to `$if'.
+
+ A Kernel program may sometimes capture a continuation; that is,
+acquire a reference to it as a first-class object. The basic means of
+continuation capture is applicative `call/cc'. Given a first-class
+continuation `c', a combiner can be constructed that will abnormally
+pass its operand tree to `c' (as opposed to the normal return of values
+to continuations). In the simplest case, the abnormally passed value
+arrives at `c' as if it had been normally returned to `c'. In general,
+continuations bypassed by the abnormal pass may have entry/exit guards
+attached to them, and these guards can intercept the abnormal pass
+before it reaches `c'. Each entry/exit guard consists of a selector
+continuation, which designates which abnormal passes the guard will
+intercept, and an interceptor applicative that performs the
+interception when selected.
+
+ Continuations are immutable, and are `equal?' iff `eq?'. The
+continuation type is encapsulated.
+
+ -- Applicative: continuation? (continuation? . objects)
+ The primitive type predicate for type continuation.
+ `continuation?' returns true iff all the objects in `objects' are
+ of type continuation.
+
+ -- Applicative: call/cc (call/cc combiner)
+ Calls `combiner' in the dynamic environment as a tail context,
+ passing as sole operand to it the continuation to which `call/cc'
+ would normally return its result. (That is, constructs such a
+ combination and evaluates it in the dynamic environment.)
+
+ -- Applicative: extend-continuation (extend-continuation continuation
+ applicative [environment])
+ The `extend-continuation' applicative constructs and returns a new
+ child of `continuation' that, when it normally receives a value v,
+ calls the underlying combiner of `applicative' with dynamic
+ environment `environment' (or an empty environment if none was
+ specified) and operand tree `v', the result of the call normally
+ to be returned to `continuation'.
+
+ The following equivalnece defines the short version:
+ (extend-continuation c a) ==
+ (extend-continuation c a (make-environment))
+
+ -- Applicative: guard-continuation (guard-continuation entry-guards
+ continuation exit-guards)
+ `entry-guards' and `exit-guards' should each be a list of clauses;
+ each clause should be a list of length two, whose first element is
+ a continuation, and whose second element is an applicative whose
+ underlying combiner is operative.
+
+ Applicative `guard-continuation' constructs two continuations: a
+ child of continuation, called the `outer continuation'; and a
+ child of the `outer continuation', called the `inner
+ continuation'. The `inner continuation' is returned as the result
+ of the call to `guard-continuation'.
+
+ When the `inner continuation' normally receives a value, it passes
+ the value normally to the `outer continuation'; and when the
+ `outer continuation' normally receives a value, it passes the
+ value normally to `continuation'. Thus, in the absence of abnormal
+ passing, the inner and outer continuations each have the same
+ behavior as `continuation'.
+
+ The two elements of each guard clause are called, respectively, the
+ `selector' and the `interceptor'. The `selector' continuation is
+ used in deciding whether to intercept a given abnormal pass, and
+ the `interceptor' applicative is called to perform customized
+ action when interception occurs.
+
+ At the beginning of the call to `guard-continuation', internal
+ copies are made of the evaluation structures of `entry-guards' and
+ `exit-guards', so that the selectors and interceptors contained in
+ the arguments at that time remain fixed thereafter, independent of
+ any subsequent mutations to the arguments.
+
+ -- Applicative: continuation->applicative (continuation->applicative
+ continuation)
+ Returns an applicative whose underlying operative abnormally passes
+ its operand tree to `continuation', thus: A series of interceptors
+ are selected to handle the abnormal pass, and a continuation is
+ derived that will normally perform all the interceptions in
+ sequence and pass some value to the destination of the originally
+ abnormal pass. The operand tree is then normally passed to the
+ derived continuation.
+
+ -- Variable: root-continuation
+ This continuation is the ancestor of all other continuations. When
+ it normally receives a value, it terminates the Kernel session.
+ (For example, if the system is running a read-eval-print loop, it
+ exits the loop.)
+
+ -- Variable: error-continuation
+ The dynamic extent of this continuation is mutually disjoint from
+ the dynamic extent in which Kernel computation usually occurs
+ (such as the dynamic extent in which the Kernel system would run a
+ read-eval-print loop).
+
+ When this continuation normally receives a value, it provides a
+ diagnostic message to the user of the Kernel system, on the
+ assumption that the received value is an attempt to describe some
+ error that aborted a computation; and then resumes operation of
+ the Kernel system at some point that is outside of all
+ user-defined computation. (For example, if the system is running a
+ read-eval-print loop, operation may resume by continuing from the
+ top of the loop.)
+
+ The diagnostic message is not made available to any Kernel
+ computation, and is therefore permitted to contain information that
+ violates abstractions within the system.
+
+ When an error is signaled during a Kernel computation, the
+ signaling action consists of an abnormal pass to some continuation
+ in the dynamic extent of `error-continuation'.
+
+ -- Applicative: apply-continuation (apply-continuation continuation
+ object)
+ Applicative `apply-continuation' converts its first argument to an
+ applicative as if by `continuation->applicative', and then applies
+ it as usual.
+
+ That is:
+ (apply-continuation continuation object) ==
+ (apply (continuation->applicative continuation) object)
+
+ -- Operative: ($let/cc <symbol> . <objects>)
+ A child environment `e' of the dynamic environment is created,
+ containing a binding of `<symbol>' to the continuation to which
+ the result of the call to `$let/cc' should normally return; then,
+ the subexpressions of `<objects>' are evaluated in `e' from left
+ to right, with the last (if any) evaluated as a tail context, or
+ if `<objects>' is empty the result is inert.
+
+ That is:
+ ($let/cc symbol . objects) ==
+ (call/cc ($lambda (symbol) . objects))
+
+ -- Applicative: guard-dynamic-extent (guard-dynamic-extent
+ entry-guards combiner exit-guards)
+ This applicative extends the current continuation with the
+ specified guards, and calls `combiner' in the dynamic extent of
+ the new continuation, with no operands and the dynamic environment
+ of the call to `guard-dynamic-extent'.
+
+ -- Applicative: exit (exit)
+ Applicative `exit' initiates an abnormal transfer of `#inert' to
+ `root-continuation'.
+
+ That is:
+ (exit ) == (apply-continuation root-continuation #inert)
+
+
+File: klisp.info, Node: Encapsulations, Next: Promises, Prev: Continuations, Up: Top
+
+10 Encapsulations
+*****************
+
+An encapsulation is an object that refers to another object, called its
+content. The Kernel data type encapsulation is encapsulated. Two
+encapsulations are `equal?' iff they are `eq?'. Encapsulations are
+immutable.
+
+ -- Applicative: make-encapsulation-type (make-encapsulation-type)
+ Returns a list of the form `(e p? d)', where `e', `p'?, and `d'
+ are applicatives, as follows. Each call to
+ `make-encapsulation-type' returns different applicatives `e',
+ `p?', and `d'.
+
+ * `e' is an applicative that takes one argument, and returns a
+ fresh encapsulation with the argument as content.
+ Encapsulations returned on different occasions are not `eq?'.
+
+ * `p?' is a primitive type predicate, that takes zero or more
+ arguments and returns true iff all of them are encapsulations
+ generated by `e'.
+
+ * `d' is an applicative that takes one argument; if the
+ argument is not an encapsulation generated by `e', an error
+ is signaled, otherwise the content of the encapsulation is
+ returned.
+
+ That is, the predicate `p?' only recognizes, and the decapsulator
+ `d' only extracts the content of, encapsulations created by the
+ encapsulator `e' that was returned by the same call to
+ `make-encapsulation-type'.
+
+
+File: klisp.info, Node: Promises, Next: Keyed Variables, Prev: Encapsulations, Up: Top
+
+11 Promises
+***********
+
+A promise is an object that represents the potential to determine a
+value. The value may be the result of an arbitrary computation that
+will not be performed until the value must be determined (constructor
+`$lazy'); or, in advanced usage, the value may be determined before the
+promise is constructed (constructor `memoize').
+
+ The value determined by a promise is obtained by forcing it
+(applicative `force'). A given promise cannot determine different
+values on different occasions that it is forced. Also, if a promise
+determines its value by computation, and that computation has already
+been completed, forcing the promise again will produce the previously
+determined result without re-initiating the computation to determine it.
+
+ The Kernel data type promise is encapsulated.
+
+ The general rules for predicate `eq?' only require it to distinguish
+promises if they can exhibit different behavior; the resulting leeway
+for variation between implementations is similar, in both cause and
+effect, to that for `eq?'-ness of operatives. For example, if two
+promises, constructed on different occasions, would perform the same
+computation to determine their values, and that computation has no
+side-effects and must always return the same value, the promises may or
+may not be `eq?'. Two promises are `equal?' iff they are `eq?'.
+
+ -- Applicative: promise? (promise? . objects)
+ The primitive type predicate for type promise. `promise?' returns
+ true iff all the objects in `objects' are of type promise.
+
+ -- Applicative: force (force object)
+ If `object' is a promise, applicative `force' returns the value
+ determined by promise; otherwise, it returns `object'.
+
+ The means used to force a promise depend on how the promise was
+ constructed. The description of each promise constructor specifies
+ how to force promises constructed by that constructor.
+
+ -- Operative: $lazy ($lazy expression)
+ Operative `$lazy' constructs and returns a new object of type
+ promise, representing potential evaluation of expression in the
+ dynamic environment from which `$lazy' was called.
+
+ When the promise is forced, if a value has not previously been
+ determined for it, `expression' is evaluated in the dynamic
+ environment of the constructing call to `$lazy'. If, when the
+ evaluation returns a result, a value is found to have been
+ determined for the promise during the evaluation, the result is
+ discarded in favor of the previously determined value; otherwise,
+ the result is forced, and the value returned by that forcing
+ becomes the value determined by the promise.
+
+ Forcing an undetermined lazy promise (i.e., a promise constructed
+ by $lazy for which no value has yet been determined) may cause a
+ sequential series of evaluations, each of which returns a promise
+ that is forced and thus initiates the next evaluation in the
+ series. The implementation must support series of this kind with
+ unbounded length (i.e., unbounded number of sequential
+ evaluations).
+
+ Note that forcing concerns the value determined by a given promise,
+ not the result of evaluating a given expression in a given
+ environment. Distinct promises (judged by `eq?' represent
+ different occasions of evaluation; so, even if they do represent
+ evaluation of the same expression in the same environment, forcing
+ one does not necessarily determine the value for the other, and
+ actual evaluation will take place the first time each of them is
+ forced.
+
+ -- Applicative: memoize (memoize object)
+ Applicative `memoize' constructs and returns a new object of type
+ promise, representing memoization of `object'. Whenever the
+ promise is forced, it determines `object'.
+
+
+File: klisp.info, Node: Keyed Variables, Next: Numbers, Prev: Promises, Up: Top
+
+12 Keyed Variables
+******************
+
+A keyed variable is a device that associates a non-symbolic key (in the
+form of an accessor applicative) with a value depending on the context
+in which lookup occurs. Kernel provides two types of keyed variables:
+dynamic & static. Keyed Dynamic Variables use the dynamic extent as
+context and Keyed Static Variables use the dynamic environment.
+
+12.1 Keyed Dynamic Variables
+============================
+
+A keyed dynamic variable is a device that associates a non-symbolic key
+(in the form of an accessor applicative) with a value depending on the
+dynamic extent in which lookup occurs.
+
+ -- Applicative: make-keyed-dynamic-variable
+ (make-keyed-dynamic-variable)
+ Returns a list of the form `(b a)', where `b' and `a' are
+ applicatives, as follows. Each call to
+ `make-keyed-dynamic-variable' returns different `b' and `a'.
+
+ * `b' is an applicative that takes two arguments, the second of
+ which must be a combiner. It calls its second argument with
+ no operands (nil operand tree) in a fresh empty environment,
+ and returns the result.
+
+ * `a' is an applicative that takes zero arguments. If the call
+ to `a' occurs within the dynamic extent of a call to `b', then
+ `a' returns the value of the first argument passed to `b' in
+ the smallest enclosing dynamic extent of a call to `b'. If the
+ call to `a' is not within the dynamic extent of any call to
+ `b', an error is signaled.
+
+12.2 Keyed Static Variables
+===========================
+
+A keyed static variable is a device that binds data in an environment
+by a non-symbolic key, where the key is an accessor applicative.
+
+ -- Applicative: make-keyed-static-variable (make-keyed-static-variable)
+ Returns a list of the form `(b a)', where `b' and `a' are
+ applicatives, as follows. Each call to
+ `make-keyed-static-variable' returns different `b' and `a'.
+
+ * `b' is an applicative that takes two arguments, the second of
+ which must be an environment. It constructs and returns a
+ child-environment of its second argument, with initially no
+ local bindings.
+
+ * `a' is an applicative that takes zero arguments. If the
+ dynamic environment `e' of the call to a has an improper
+ ancestor that was constructed by a call to `b', then a
+ returns the value of the first argument passed to `b' in the
+ first such environment encountered by a depth-first traversal
+ of the improper ancestors of `e'. If `e' has no improper
+ ancestors constructed via `b', an error is signaled.
+
+
+File: klisp.info, Node: Numbers, Next: Strings, Prev: Keyed Variables, Up: Top
+
+13 Numbers
+**********
+
+
+File: klisp.info, Node: Strings, Next: Characters, Prev: Numbers, Up: Top
+
+14 Strings
+**********
+
+
+File: klisp.info, Node: Characters, Next: Ports, Prev: Strings, Up: Top
+
+15 Characters
+*************
+
+
+File: klisp.info, Node: Ports, Next: Index, Prev: Characters, Up: Top
+
+16 Ports
+********
+
+A port is an object that mediates character-based input from a source
+or character-based output to a destination. In the former case, the
+port is an input port, in the latter case, an output port.
+
+ Although ports are not considered immutable, none of the operations
+on ports described in this section constitute mutation. Ports are
+`equal?' iff `eq?'. The port type is encapsulated.
+
+ An auxiliary data type used to signal the end of file was reached is
+eof. The eof type consists of a single immutable value, having an
+output only external representation (so that it can never be the normal
+result of a call to read). The eof type is encapsulated.
+
+ SOURCE NOTE: the eof type is not in the Kernel report, it is used in
+klisp and was taken from Scheme.
+
+ -- Applicative: port? (port? . objects)
+ The primitive type predicate for type port. `port?' returns true
+ iff all the objects in `objects' are of type port.
+
+ -- Applicative: input-port? (input-port? . objects)
+ -- Applicative: output-port? (output-port? . objects)
+ Applicative `input-port?' is a predicate that returns true unless
+ one or more of its arguments is not an input port. Applicative
+ output-port? is a predicate that returns true unless one or more of
+ its arguments is not an output port.
+
+ Every port must be admitted by at least one of these two
+ predicates.
+
+ -- with-input-from-file: (with-input-from-file string combiner)
+ -- with-output-to-file: (with-output-to-file string combiner)
+ These two applicatives open the file named in `string' for input
+ or output, an invoke the binder of the input-port & output-port
+ keyed dynamic variables respectively with the opened port & the
+ passed `combiner' (this means that the combiner is called in a
+ fresh, empty dynamic environment). When/if the binder normally
+ returns, the port is closed. The result of the applicatives
+ `with-input-from-file' and `with-output-from-file' is inert.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing. In the new scheme report there's also a third
+ error-port variable. It is very likely that that will be added to
+ the klisp implementation in the near future.
+
+ -- get-current-input-port: (get-current-input-port)
+ -- get-current-output-port: (get-current-output-port)
+ These are the accessors for the input-port and output-port keyed
+ dynamic variables repectively.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing. In the new scheme report there's also a third
+ error-port variable. It is very likely that that will be added to
+ the klisp implementation in the near future.
+
+ -- Applicative: open-input-file (open-input-file string)
+ `string' should be the name/path for an existing file.
+
+ Applicative `open-input-file' creates and returns an input port
+ associated with the file represented with `string'. If the file
+ can't be opened (e.g. because it doesn't exists, or there's a
+ permissions problem), an error is signaled.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing.
+
+ -- Applicative: open-output-file (open-output-file string)
+ `string' should be the name/path for an existing file.
+
+ Applicative `open-output-file' creates and returns an output port
+ associated with the file represented with `string'. If the file
+ can't be opened (e.g. if there's a permissions problem), an error
+ is signaled.
+
+ In klisp, for now, applicative `open-output-file' truncates the
+ file if it already exists, but that could change later (i.e. like
+ in scheme the behaviour should be considered unspecified).
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing.
+
+ -- close-input-file: (close-input-file input-port)
+ -- close-output-file: (close-output-file output-port)
+ These applicatives close the port argument, so that no more
+ input/output may be performed on them, and the resources can be
+ freed. If the port was already closed these applicatives have no
+ effect.
+
+ The result returned by applicatives `close-input-file' and
+ `close-output-file' is inert.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing. There's probably a name error here. These
+ should probably be called close-input-port & close-output-port.
+
+ -- Applicative: read (read [input-port])
+ If the `port' optional argument is not specified, then the value
+ of the `input-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `read' reads & returns the next parseable object from
+ the given port, or the eof object if no objects remain. If `read'
+ finds and unparseable object in the port, an error is signaled.
+ In that case, the remaining position in the port is unspecified.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing.
+
+ -- write: (write object [port])
+ If the `port' optional argument is not specified, then the value
+ of the `output-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `write' writes an external representation of `object'
+ to the specified port. This may be an output-only representation
+ that can't be read by applicative `read' in cases where the type
+ of `object' doen't have a parseable external representation (e.g.
+ combiners and environments). The result returned by `write' is
+ inert.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing.
+
+ -- Applicative: call-with-input-file (call-with-input-file string
+ combiner)
+ -- Applicative: call-with-output-file (call-with-output-file string
+ combiner)
+ These applicatives open file named in `string' and call their
+ `combiner' argument in a fresh empty environment passing it as a
+ sole operand the opened port. When/if the combiner normally
+ returns a value the port is closed and that value is returned as
+ the result of the applicative.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text
+ is still missing.
+
+ -- Applicative: load (load string)
+ Applicative `load' opens for input a file named `string'; reads
+ objects from the file until the end of the file is reached;
+ evaluates those objects consecutively in the created environment.
+ The result from applicative `load' is inert.
+
+ SOURCE NOTE: load is enumerated in the Kernel report, but the
+ description is not there yet. This seems like a sane way to define
+ it, taking the description of `get-module' that there is in the
+ report. The one detail that I think is still open, is whether to
+ return `#inert' (as is the case with klisp currently) or rather
+ return the value of the last evaluation.
+
+ -- Applicative: get-module (get-module string [environment])
+ Applicative `get-module' creates a fresh standard environment;
+ opens for input a file named `string'; reads objects from the file
+ until the end of the file is reached; evaluates those objects
+ consecutively in the created environment; and, lastly, returns the
+ created environment. If the optional argument `environment' is
+ specified, the freshly created standard environment is augmented,
+ prior to evaluating read expressions, by binding symbol
+ `module-parameters' to the `environment' argument.
+
+ -- Applicative: eof-object? (eof-object? . objects)
+ The primitive type predicate for type eof. `eof-object?' returns
+ true iff all the objects in `objects' are of type eof.
+
+ SOURCE NOTE: This is not in the report, the idea is from Scheme.
+ The `eof-object?' name is also from scheme, but this will probably
+ be changed to just `eof?', for consistency with the other
+ primitive type predicates.
+
+ -- read-char: (read-char [port])
+ If the `port' optional argument is not specified, then the value
+ of the `input-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `read-char' reads and returns a character (not an
+ external representation of a character) from the specified port, or
+ an eof if the end of file was reached.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+ -- peek-char: (peek-char [port])
+ If the `port' optional argument is not specified, then the value
+ of the `input-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `peek-char' reads and returns a character (not an
+ external representation of a character) from the specified port, or
+ an eof if the end of file was reached. The position of the port
+ remains unchanged so that new call to `peek-char' or `read-char'
+ on the same port return the same character.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+ -- char-ready?: (char-ready? [port])
+ If the `port' optional argument is not specified, then the value
+ of the `input-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Predicate `char-ready?' checks to see if a character is available
+ in the specified port. If it returns true, then a `read-char' or
+ `peek-char' on that port is guaranteed not to block/hang. For now
+ in klisp this is hardcoded to `#t' because the code to do this is
+ non-portable.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+ -- write-char: (write-char char [port])
+ If the `port' optional argument is not specified, then the value
+ of the `output-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `write-char' writes the `char' character (not an
+ external representation of the character) to the specified port.
+ The result returned by `write-char' is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+ -- newline: (newline [port])
+ If the `port' optional argument is not specified, then the value
+ of the `output-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `newline' writes a newline to the specified port. The
+ result returned by `newline' is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+ -- display: (display object [port])
+ If the `port' optional argument is not specified, then the value
+ of the `output-port' keyed dynamic variable is used. If the port
+ is closed, an error is signaled.
+
+ Applicative `display' behaves like `write' except that strings are
+ not enclosed in double quotes and no character is escaped within
+ those strings and character objects are output as if by
+ `write-char' instead of `read'. The result returned by `display'
+ is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+
+
+File: klisp.info, Node: Index, Next: (dir), Prev: Ports, Up: Top
+
+Index
+*****
+
+
+* Menu:
+
+* $and?: Booleans. (line 28)
+* $binds?: Environments. (line 108)
+* $cond: Control. (line 32)
+* $define!: Environments. (line 49)
+* $if: Control. (line 15)
+* $import!: Environments. (line 207)
+* $lambda: Combiners. (line 76)
+* $lazy: Promises. (line 43)
+* $let: Environments. (line 89)
+* $let*: Environments. (line 124)
+* $let-redirect: Environments. (line 153)
+* $let-safe: Environments. (line 161)
+* $letrec: Environments. (line 137)
+* $letrec*: Environments. (line 144)
+* $or?: Booleans. (line 41)
+* $provide!: Environments. (line 191)
+* $remote-eval: Environments. (line 169)
+* $sequence: Control. (line 23)
+* $set!: Environments. (line 182)
+* $vau: Combiners. (line 26)
+* ( <1>: Ports. (line 37)
+* ( <2>: Continuations. (line 143)
+* (: Environments. (line 174)
+* and?: Booleans. (line 20)
+* append: Pairs and lists. (line 208)
+* append!: Pairs and lists. (line 306)
+* applicative descriptions: A Sample Applicative Description.
+ (line 6)
+* applicative?: Combiners. (line 21)
+* applicatives: Combiners. (line 6)
+* apply: Combiners. (line 83)
+* apply-continuation: Continuations. (line 134)
+* assoc: Pairs and lists. (line 252)
+* assq: Pairs and lists. (line 333)
+* boolean?: Booleans. (line 12)
+* booleans: Booleans. (line 6)
+* caaaar: Pairs and lists. (line 101)
+* caaadr: Pairs and lists. (line 102)
+* caaar: Pairs and lists. (line 93)
+* caadar: Pairs and lists. (line 103)
+* caaddr: Pairs and lists. (line 104)
+* caadr: Pairs and lists. (line 94)
+* caar: Pairs and lists. (line 89)
+* cadaar: Pairs and lists. (line 105)
+* cadadr: Pairs and lists. (line 106)
+* cadar: Pairs and lists. (line 95)
+* caddar: Pairs and lists. (line 107)
+* cadddr: Pairs and lists. (line 108)
+* caddr: Pairs and lists. (line 96)
+* cadr: Pairs and lists. (line 90)
+* call-with-input-file: Ports. (line 131)
+* call-with-output-file: Ports. (line 133)
+* call/cc: Continuations. (line 43)
+* car: Pairs and lists. (line 85)
+* cdaaar: Pairs and lists. (line 109)
+* cdaadr: Pairs and lists. (line 110)
+* cdaar: Pairs and lists. (line 97)
+* cdadar: Pairs and lists. (line 111)
+* cdaddr: Pairs and lists. (line 112)
+* cdadr: Pairs and lists. (line 98)
+* cdar: Pairs and lists. (line 91)
+* cddaar: Pairs and lists. (line 113)
+* cddadr: Pairs and lists. (line 114)
+* cddar: Pairs and lists. (line 99)
+* cdddar: Pairs and lists. (line 115)
+* cddddr: Pairs and lists. (line 116)
+* cdddr: Pairs and lists. (line 100)
+* cddr: Pairs and lists. (line 92)
+* cdr: Pairs and lists. (line 86)
+* characters: Characters. (line 6)
+* combiner?: Combiners. (line 120)
+* combiners: Combiners. (line 6)
+* cons: Pairs and lists. (line 35)
+* continuation->applicative: Continuations. (line 95)
+* continuation?: Continuations. (line 38)
+* continuations: Continuations. (line 6)
+* control: Control. (line 6)
+* copy-es: Pairs and lists. (line 321)
+* copy-es-immutable!: Pairs and lists. (line 49)
+* countable-list?: Pairs and lists. (line 265)
+* description format: Format of Descriptions.
+ (line 6)
+* documentation notation: Evaluation Notation. (line 6)
+* empty list: Pairs and lists. (line 6)
+* encapsulations: Encapsulations. (line 6)
+* encycle!: Pairs and lists. (line 158)
+* environment?: Environments. (line 23)
+* environments: Environments. (line 6)
+* eof-object?: Ports. (line 166)
+* eq?: Equivalence. (line 12)
+* equal?: Equivalence. (line 16)
+* equivalence: Equivalence. (line 6)
+* error message notation: Error Messages. (line 6)
+* error-continuation: Continuations. (line 110)
+* eval: Environments. (line 32)
+* evaluation notation: Evaluation Notation. (line 6)
+* exit: Continuations. (line 162)
+* extend-continuation: Continuations. (line 50)
+* filter: Pairs and lists. (line 239)
+* finite-list?: Pairs and lists. (line 261)
+* fonts: Some Terms. (line 13)
+* foo: A Sample Applicative Description.
+ (line 15)
+* for-each: Control. (line 42)
+* force: Promises. (line 35)
+* get-current-environment: Environments. (line 114)
+* get-list-metrics: Pairs and lists. (line 123)
+* get-module: Ports. (line 156)
+* guard-continuation: Continuations. (line 63)
+* guard-dynamic-extent: Continuations. (line 156)
+* ignore: Environments. (line 6)
+* ignore?: Environments. (line 28)
+* inert: Control. (line 6)
+* inert?: Control. (line 11)
+* input-port?: Ports. (line 27)
+* Kernel history: Kernel History. (line 6)
+* keyed dynamic variables: Keyed Variables. (line 15)
+* keyed static variables: Keyed Variables. (line 40)
+* keyed variables: Keyed Variables. (line 6)
+* length: Pairs and lists. (line 191)
+* list: Pairs and lists. (line 72)
+* list*: Pairs and lists. (line 78)
+* list-neighbors: Pairs and lists. (line 228)
+* list-ref: Pairs and lists. (line 198)
+* list-tail: Pairs and lists. (line 147)
+* lists: Pairs and lists. (line 6)
+* load: Ports. (line 143)
+* make-encapsulation-type: Encapsulations. (line 12)
+* make-environment: Environments. (line 36)
+* make-kernel-standard-environment: Environments. (line 119)
+* make-keyed-dynamic-variable: Keyed Variables. (line 21)
+* make-keyed-static-variable: Keyed Variables. (line 44)
+* map <1>: Combiners. (line 96)
+* map: Pairs and lists. (line 169)
+* member?: Pairs and lists. (line 257)
+* memoize: Promises. (line 74)
+* memq?: Pairs and lists. (line 338)
+* nil: Pairs and lists. (line 6)
+* not?: Booleans. (line 16)
+* null?: Pairs and lists. (line 31)
+* numbers: Numbers. (line 6)
+* object descriptions: A Sample Applicative Description.
+ (line 6)
+* open-input-file: Ports. (line 62)
+* open-output-file: Ports. (line 73)
+* operative descriptions: A Sample Applicative Description.
+ (line 6)
+* operative?: Combiners. (line 16)
+* operatives: Combiners. (line 6)
+* or?: Booleans. (line 24)
+* output-port?: Ports. (line 28)
+* pair?: Pairs and lists. (line 27)
+* pairs: Pairs and lists. (line 6)
+* port?: Ports. (line 23)
+* ports: Ports. (line 6)
+* printing notation: Printing Notation. (line 6)
+* promise?: Promises. (line 31)
+* promises: Promises. (line 6)
+* read: Ports. (line 102)
+* reduce: Pairs and lists. (line 270)
+* root-continuation: Continuations. (line 104)
+* set-car!: Pairs and lists. (line 41)
+* set-cdr!: Pairs and lists. (line 42)
+* string->symbol: Symbols. (line 20)
+* strings: Strings. (line 6)
+* symbol->string: Symbols. (line 16)
+* symbol?: Symbols. (line 12)
+* symbols: Symbols. (line 6)
+* unwrap: Combiners. (line 72)
+* wrap: Combiners. (line 68)
+
+
+
+Tag Table:
+Node: Top703
+Node: License2601
+Node: Introduction4272
+Node: Caveats7095
+Node: Kernel History7881
+Node: Conventions9326
+Node: Some Terms9997
+Node: Evaluation Notation10668
+Node: Printing Notation11689
+Node: Error Messages12165
+Node: Format of Descriptions12813
+Node: A Sample Applicative Description13377
+Node: Acknowledgements15140
+Node: Booleans15526
+Node: Equivalence18068
+Node: Symbols18861
+Node: Control20227
+Node: Pairs and lists22544
+Node: Environments39567
+Node: Combiners49774
+Node: Continuations55810
+Node: Encapsulations63984
+Node: Promises65437
+Node: Keyed Variables69360
+Node: Numbers72131
+Node: Strings72240
+Node: Characters72344
+Node: Ports72452
+Node: Index83737
+
+End Tag Table
diff --git a/manual/src/Makefile b/manual/src/Makefile
@@ -0,0 +1,28 @@
+# Makefile for the klisp manual
+# some of this is from the elisp manual
+
+srcs = klisp.texi index.texi \
+ intro.texi \
+ booleans.texi equivalence.texi symbols.texi \
+ control.texi pairs_lists.texi \
+ environments.texi combiners.texi \
+ continuations.texi encapsulations.texi \
+ promises.texi keyed_vars.texi \
+ numbers.texi strings.texi \
+ characters.texi ports.texi
+
+#TODO add dvi/pdf output
+#TODO check what happens with xrefs
+
+.PHONY: all clean
+
+all: clean info html
+
+info: $(srcs)
+ makeinfo -o ../klisp.info klisp.texi
+
+html: $(srcs)
+ makeinfo --html -o ../html klisp.texi
+
+clean:
+ rm -r -f ../klisp.info ../html
diff --git a/manual/src/booleans.texi b/manual/src/booleans.texi
@@ -0,0 +1,65 @@
+@c -*-texinfo-*-
+@setfilename ../src/booleans
+
+@node Booleans, Equivalence, Introduction, Top
+@comment node-name, next, previous, up
+
+@chapter Booleans
+@cindex booleans
+
+ The boolean data type consists of two values, which are called true
+and false, and have respectively external representations @code{#t}
+and @code{#f}. There are no possible mutations of either of these two
+@c add encapsulated cross ref
+values, and the boolean type is encapsulated.
+
+@deffn Applicative boolean? (boolean? . objects)
+ The primitive type predicate for type boolean. @code{boolean?}
+returns true iff all the objects in @code{objects} are of type boolean.
+@end deffn
+
+@deffn Applicative not? (not? boolean)
+ Applicative @code{not?} is a predicate that returns the logical
+negation of its argument.
+@end deffn
+
+@deffn Applicative and? (and? . booleans)
+ Applicative @code{and?} is a predicate that returns true unless one
+or more of its arguments are false.
+@end deffn
+
+@deffn Applicative or? (or? . booleans)
+ Applicative @code{or?} is a predicate that returns false unless one
+or more of its arguments are true.
+@end deffn
+
+@deffn Operative $and? ($and? . <list>)
+ The @code{$and?} operative performs a ``short-circuit and'' of its
+operands. It evaluates them from left to right, until either an
+operand evaluates to false, or the end of the list is reached. If the
+end of the list is reached (which is immediate if @code{<list>} is
+@code{nil}), the operative returns true. If an operand evaluates to
+false, no further operand evaluations are performed, and the operative
+returns false. If @code{<list>} is acyclic, and the last operand is
+@c TODO cross ref tail-contect
+evaluated, it is evaluated as a tail context. If @code{<list>} is
+cyclic, an unbounded number of operand evaluations may be
+performed. If any of the operands evaluates to a non-boolean value, an
+error is signaled (even if it's the last one).
+@end deffn
+
+@deffn Operative $or? ($or? . <list>)
+ The @code{$or?} operative performs a ``short-circuit or'' of its
+operands. It evaluates them from left to right, until either an
+operand evaluates to true, or the end of the list is reached. If the
+end of the list is reached (which is immediate if @code{<list>} is
+@code{nil}), the operative returns false. If an operand evaluates to
+true, no further operand evaluations are performed, and the operative
+returns true. If @code{<list>} is acyclic, and the last operand is
+@c TODO cross ref tail-context
+evaluated, it is evaluated as a tail context. If @code{<list>} is
+cyclic, an unbounded number of operand evaluations may be
+performed. If any of the operands evaluates to a non-boolean value, an
+error is signaled (even if it's the last one).
+@end deffn
+
diff --git a/manual/src/characters.texi b/manual/src/characters.texi
@@ -0,0 +1,8 @@
+@c -*-texinfo-*-
+@setfilename ../src/characters
+
+@node Characters, Ports, Strings, Top
+@comment node-name, next, previous, up
+
+@chapter Characters
+@cindex characters
diff --git a/manual/src/combiners.texi b/manual/src/combiners.texi
@@ -0,0 +1,156 @@
+@c -*-texinfo-*-
+@setfilename ../src/combiners
+
+@node Combiners, Continuations, Environments, Top
+@comment node-name, next, previous, up
+
+@chapter Combiners
+@cindex combiners
+@cindex applicatives
+@cindex operatives
+
+ There are two types of combiners in Kernel, operative and
+applicative. Both types are encapsulated. All combiners are immutable.
+Two applicatives are @code{eq?} iff their underlying combiners are
+@code{eq?}. However, @code{eq?}-ness of operatives is only
+constrained by the general rules for @code{eq?}, which leave
+considerable leeway for variation between implementations. klisp only
+considers @code{eq?} those operatives constructed by the same call to
+a constructor (e.g. @code{$vau}). Two combiners are @code{equal?}
+iff they are @code{eq?}.
+@c TODO add xref for eq? and equal?
+
+@deffn Applicative operative? (operative? . objects)
+ The primitive type predicate for type operative. @code{operative?}
+returns true iff all the objects in @code{objects} are of type
+operative.
+@end deffn
+
+@deffn Applicative applicative? (applicative? . objects)
+ The primitive type predicate for type applicative.
+@code{applicative?} returns true iff all the objects in
+@code{objects} are of type applicative.
+@end deffn
+
+@deffn Operative $vau ($vau <formals> <eformal> . <objects>)
+@c TODO add xref to formal parameter tree
+@code{<formals>} should be a formal parameter tree; @code{<eformal>}
+should be either a symbol or @code{#ignore}. If @code{<formals>} does
+not have the correct form for a formal parameter tree, or if
+@code{<eformal>} is a symbol that also occurs in @code{<formals>}, an
+error is signaled.
+
+ A @code{vau} expression evaluates to an operative; an operative
+created in this way is said to be compound. The environment in which
+the @code{vau} expression was evaluated is remembered as part of the compound
+operative, called the compound operative’s static environment.
+@code{<formals>} and @code{<objects>} are copied as by
+@code{copy-es-immutable} and the copies are stored as part of the
+operative being constructed. This avoids problem if these structures
+are later mutated.
+
+@c TODO add xref to eval or apply as example
+When the compound operative created by @code{$vau} is later called
+with an object and an environment, here called respectively the
+operand tree and the dynamic environment, the following happens:
+
+@enumerate
+@item
+A new, initially empty environment is created, with the static
+environment as its parent. This will be called the local environment.
+
+@item
+A stored copy of the formal parameter tree formals is matched in the
+local environment to the operand tree, locally binding the symbols of
+@c TODO add xref to matching
+formals to the corresponding parts of the operand tree. eformal is
+matched to the dynamic environment; that is, if eformal is a symbol
+then that symbol is bound in the local environment to the dynamic
+environment.
+
+@item
+@c TODO add xref to tail context.
+A stored copy of the expressions is evaluated sequentially from left
+to right, with the last (if any) evaluated as a tail context, or if
+the list of expressions is empty, the result is inert.
+@end enumerate
+
+ NOTE: Because compound operatives are not a distinct type in Kernel,
+they are covered by the encapsulation of type operative. In
+particular, an implementation of Kernel cannot provide a feature that
+supports extracting the static environment of any given compound
+operative, nor that supports determining whether or not a given
+operative is compound.
+@end deffn
+
+
+@deffn Applicative wrap (wrap combiner)
+ The @code{wrap} applicative returns an applicative whose underlying
+combiner is @code{combiner}.
+@end deffn
+
+@deffn Applicative unwrap (unwrap applicative)
+ The @code{unwrap} applicative returns the underlying combiner of
+@code{applicative}.
+@end deffn
+
+@deffn Operative $lambda ($lambda <formals> . <objects>)
+ @code{<formals>} should be a formal parameter tree.
+
+ The @code{$lambda} operative is defined by the following equivalence:
+@example
+($lambda formals . objects) @equiv{}
+ (wrap ($vau formals #ignore . objects))
+@end example
+@end deffn
+
+@deffn Applicative apply (apply applicative object [environment])
+ Applicative @code{apply} combines the underlying combiner of
+@code{applicative} with @code{object} in a tail context with dynamic
+environment @code{environment} (if the long form is used) or in an
+empty environment (if the short form is used).
+
+The following equivalences hold:
+@example
+(apply applicative object environment) @equiv{}
+ (eval (cons (unwrap applicative) object) environment)
+
+(apply applicative object) @equiv{}
+ (apply applicative object (make-environment))
+@end example
+@end deffn
+
+@deffn Applicative map (map applicative . lists)
+ @code{lists} must be a nonempty list of lists; if there are two or
+@c TODO add xref to length
+more, they must all have the same length. If @code{lists} is empty, or
+if all of its elements are not lists of the same length, an error is
+signaled.
+
+ The @code{map} applicative applies @code{applicative} element-wise
+to the elements of the lists in @code{lists} (i.e., applies it to a
+list of the first elements of the @code{lists}, to a list of the
+second elements of the @code{lists}, etc.), using the dynamic
+environment from which @code{map} was called, and returns a list of
+the results, in order. The applications may be performed in any order,
+as long as their results occur in the resultant list in the order of
+their arguments in the original @code{lists}. If @code{lists} is a
+cyclic list, each argument list to which @code{applicative} is applied
+is structurally isomorphic to @code{lists}. If any of the elements of
+@code{lists} is a cyclic list, they all must be, or they wouldn’t all
+have the same length. Let @code{a1...an} be their acyclic prefix
+lengths, and @code{c1...cn} be their cycle lengths. The acyclic
+prefix length @code{a} of the resultant list will be the maximum of
+the @code{ak}, while the cycle length @code{c} of the resultant list
+will be the least common multiple of the @code{ck}. In the
+construction of the result, applicative is called exactly @code{a + c}
+times.
+@c TODO comp/xref for-each
+@end deffn
+
+@deffn Applicative combiner? (combiner? . objects)
+ The primitive type predicate for type combiner. @code{combiner?}
+returns true iff all the objects in @code{objects} are of type
+combiner (i.e. applicative or operative).
+@end deffn
+
diff --git a/manual/src/continuations.texi b/manual/src/continuations.texi
@@ -0,0 +1,198 @@
+@c -*-texinfo-*-
+@setfilename ../src/continuations
+
+@node Continuations, Encapsulations, Combiners, Top
+@comment node-name, next, previous, up
+
+@chapter Continuations
+@cindex continuations
+
+ A continuation is a plan for all future computation, parameterized
+by a value to be provided, and contingent on the states of all mutable
+data structures (which notably may include environments). When the
+Kernel evaluator is invoked, the invoker provides a continuation to
+which the result of the evaluation will normally be returned.
+
+ For example, when @code{$if} evaluates its test operand, the
+continuation provided for the result expects to be given a boolean
+value; and, depending on which boolean it gets, it will evaluate
+either the consequent or the alternative operand as a tail context —
+that is, the continuation provided for the result of evaluating the
+selected operand is the same continuation that was provided for the
+result of the call to @code{$if}.
+
+ A Kernel program may sometimes capture a continuation; that is,
+acquire a reference to it as a first-class object. The basic means of
+continuation capture is applicative @code{call/cc}. Given a
+first-class continuation @code{c}, a combiner can be constructed that
+will abnormally pass its operand tree to @code{c} (as opposed to the
+@c TODO add xref to abnormal pass
+normal return of values to continuations). In the simplest case, the
+abnormally passed value arrives at @code{c} as if it had been normally
+returned to @code{c}. In general, continuations bypassed by the
+abnormal pass may have entry/exit guards attached to them, and these
+guards can intercept the abnormal pass before it reaches @code{c}.
+Each entry/exit guard consists of a selector continuation, which
+designates which abnormal passes the guard will intercept, and an
+interceptor applicative that performs the interception when selected.
+@c TODO add xref to guard-continuation, continuation->applicative
+@c and abnormal pass
+
+ Continuations are immutable, and are @code{equal?} iff @code{eq?}.
+The continuation type is encapsulated.
+
+@c TODO add dynamic extent & guard selection/interception to the intro
+@deffn Applicative continuation? (continuation? . objects)
+ The primitive type predicate for type continuation.
+@code{continuation?} returns true iff all the objects in
+@code{objects} are of type continuation.
+@end deffn
+
+@deffn Applicative call/cc (call/cc combiner)
+ Calls @code{combiner} in the dynamic environment as a tail context,
+passing as sole operand to it the continuation to which @code{call/cc}
+would normally return its result. (That is, constructs such a
+combination and evaluates it in the dynamic environment.)
+@c TODO add xref Cf. operative $let/cc , §7.3.2.
+@end deffn
+
+@deffn Applicative extend-continuation (extend-continuation continuation applicative [environment])
+ The @code{extend-continuation} applicative constructs and returns a
+new child of @code{continuation} that, when it normally receives a
+value v, calls the underlying combiner of @code{applicative} with
+dynamic environment @code{environment} (or an empty environment if
+none was specified) and operand tree @code{v}, the result of the call
+normally to be returned to @code{continuation}.
+
+ The following equivalnece defines the short version:
+@example
+(extend-continuation c a) @equiv{}
+ (extend-continuation c a (make-environment))
+@end example
+@end deffn
+
+@deffn Applicative guard-continuation (guard-continuation entry-guards continuation exit-guards)
+ @code{entry-guards} and @code{exit-guards} should each be a list of
+clauses; each clause should be a list of length two, whose first
+element is a continuation, and whose second element is an applicative
+whose underlying combiner is operative.
+
+ Applicative @code{guard-continuation} constructs two continuations:
+a child of continuation, called the @code{outer continuation}; and a
+child of the @code{outer continuation}, called the @code{inner
+continuation}. The @code{inner continuation} is returned as the
+result of the call to @code{guard-continuation}.
+
+ When the @code{inner continuation} normally receives a value, it
+passes the value normally to the @code{outer continuation}; and when
+the @code{outer continuation} normally receives a value, it passes the
+value normally to @code{continuation}. Thus, in the absence of
+abnormal passing, the inner and outer continuations each have the same
+behavior as @code{continuation}.
+
+ The two elements of each guard clause are called, respectively, the
+@code{selector} and the @code{interceptor}. The @code{selector}
+continuation is used in deciding whether to intercept a given abnormal
+pass, and the @code{interceptor} applicative is called to perform
+@c TODO add xref to selection and interception
+customized action when interception occurs.
+
+@c TODO add xref to evaluation structure
+At the beginning of the call to @code{guard-continuation}, internal
+copies are made of the evaluation structures of @code{entry-guards}
+and @code{exit-guards}, so that the selectors and interceptors
+contained in the arguments at that time remain fixed thereafter,
+independent of any subsequent mutations to the arguments.
+@end deffn
+
+@deffn Applicative continuation->applicative (continuation->applicative continuation)
+ Returns an applicative whose underlying operative abnormally passes
+its operand tree to @code{continuation}, thus: A series of
+interceptors are selected to handle the abnormal pass, and a
+continuation is derived that will normally perform all the
+interceptions in sequence and pass some value to the destination of
+the originally abnormal pass. The operand tree is then normally
+passed to the derived continuation.
+@c TODO add xref to selection and interception
+@end deffn
+
+@defvar root-continuation
+ This continuation is the ancestor of all other continuations. When
+it normally receives a value, it terminates the Kernel session. (For
+example, if the system is running a read-eval-print loop, it exits the
+loop.)
+@c TODO add xref Cf. applicative exit, §7.3.4.
+@end defvar
+
+@defvar error-continuation
+ The dynamic extent of this continuation is mutually disjoint from
+the dynamic extent in which Kernel computation usually occurs (such as
+the dynamic extent in which the Kernel system would run a
+read-eval-print loop).
+
+ When this continuation normally receives a value, it provides a
+diagnostic message to the user of the Kernel system, on the assumption
+that the received value is an attempt to describe some error that
+aborted a computation; and then resumes operation of the Kernel system
+at some point that is outside of all user-defined computation. (For
+example, if the system is running a read-eval-print loop, operation
+may resume by continuing from the top of the loop.)
+
+ The diagnostic message is not made available to any Kernel
+computation, and is therefore permitted to contain information that
+violates abstractions within the system.
+
+@c TODO add details about klisp error messages
+ When an error is signaled during a Kernel computation, the signaling
+action consists of an abnormal pass to some continuation in the
+dynamic extent of @code{error-continuation}.
+@end defvar
+
+@deffn Applicative apply-continuation (apply-continuation continuation object)
+ Applicative @code{apply-continuation} converts its first argument to
+an applicative as if by @code{continuation->applicative}, and then
+applies it as usual.
+
+ That is:
+@example
+(apply-continuation continuation object) @equiv{}
+ (apply (continuation->applicative continuation) object)
+@end example
+@end deffn
+
+@deffn Operative ($let/cc <symbol> . <objects>)
+ A child environment @code{e} of the dynamic environment is created,
+containing a binding of @code{<symbol>} to the continuation to which
+the result of the call to @code{$let/cc} should normally return; then,
+the subexpressions of @code{<objects>} are evaluated in @code{e} from
+left to right, with the last (if any) evaluated as a tail context, or
+if @code{<objects>} is empty the result is inert.
+
+ That is:
+@example
+($let/cc symbol . objects) @equiv{}
+ (call/cc ($lambda (symbol) . objects))
+@end example
+@end deffn
+
+@deffn Applicative guard-dynamic-extent (guard-dynamic-extent entry-guards combiner exit-guards)
+ This applicative extends the current continuation with the specified
+guards, and calls @code{combiner} in the dynamic extent of the new
+continuation, with no operands and the dynamic environment of the call
+to @code{guard-dynamic-extent}.
+@end deffn
+
+@deffn Applicative exit (exit)
+@c TODO add xref
+ Applicative @code{exit} initiates an abnormal transfer of
+@code{#inert} to @code{root-continuation}.
+
+ That is:
+@example
+(exit ) @equiv{} (apply-continuation root-continuation #inert)
+@end example
+@end deffn
+
+
+
+
diff --git a/manual/src/control.texi b/manual/src/control.texi
@@ -0,0 +1,64 @@
+@c -*-texinfo-*-
+@setfilename ../src/control
+
+@node Control, Pairs and lists, Symbols, Top
+@comment node-name, next, previous, up
+
+@chapter Control
+@cindex control
+@cindex inert
+ The inert data type is provided for use with control combiners. It
+consists of a single immutable value, having external representation
+@code{#inert}. The inert type is encapsulated.
+
+@deffn Applicative inert? (inert? . objects)
+ The primitive type predicate for type inert. @code{inert?}
+returns true iff all the objects in @code{objects} are of type inert.
+@end deffn
+
+@deffn Operative $if ($if <test> <consequent> <alternative>)
+ The @code{$if} operative first evaluates @code{<test>} in the
+dynamic environment. If the result is not of type boolean, an error
+is signaled. If the result is true, @code{<consequent>} is then
+@c TODO add xref to tail context
+evaluated in the dynamic environment as a tail context. Otherwise,
+@code{<alternative>} is evaluated in the dynamic environment as a tail
+context.
+@end deffn
+
+@deffn Operative $sequence ($sequence . <objects>)
+The @code{$sequence} operative evaluates the elements of the list
+@code{<objects>} in the dynamic environment, one at a time from left
+to right. If @code{<objects>} is a cyclic list, element evaluation
+continues indefinitely, with elements in the cycle being evaluated
+repeatedly. If @code{<objects>} is a nonempty finite list, its last
+@c TODO add xref for tail context.
+element is evaluated as a tail context. If @code{<objects>} is the
+empty list, the result is inert.
+@end deffn
+
+@deffn Operative $cond ($cond . <clauses>)
+@code{<clauses>} should be a list of clause expressions, each of the
+form @code{(<test> . <body>)}, where body is a list of expressions.
+
+The following equivalences define
+the behaviour of the @code{$cond} operative:
+@example
+($cond) @equiv{} #inert
+($cond (<test> . <body>) . <clauses>) @equiv{}
+ ($if <test> ($sequence . <body>) ($cond . <clauses>))
+@end example
+@end deffn
+
+@deffn Applicative for-each (for-each . lists)
+@code{lists} must be a nonempty list of lists; if there are two or
+more, they should all be the same length. If lists is empty, or if all
+of its elements are not lists of the same length, an error is
+signaled.
+
+@c TODO add xref to map
+@code{for-each} behaves identically to @code{map}, except that instead
+of accumulating and returning a list of the results of the
+element-wise applications, the results of the applications are
+discarded and the result returned by @code{for-each} is inert.
+@end deffn
diff --git a/manual/src/encapsulations.texi b/manual/src/encapsulations.texi
@@ -0,0 +1,43 @@
+@c -*-texinfo-*-
+@setfilename ../src/encapsulations
+
+@node Encapsulations, Promises, Continuations, Top
+@comment node-name, next, previous, up
+
+@chapter Encapsulations
+@cindex encapsulations
+
+An encapsulation is an object that refers to another object, called
+its content. The Kernel data type encapsulation is encapsulated. Two
+encapsulations are @code{equal?} iff they are @code{eq?}.
+Encapsulations are immutable.
+
+@c TODO this is a little spartan... maybe add some more content
+@deffn Applicative make-encapsulation-type (make-encapsulation-type)
+ Returns a list of the form @code{(e p? d)}, where @code{e},
+@code{p}?, and @code{d} are applicatives, as follows. Each call to
+@code{make-encapsulation-type} returns different applicatives
+@code{e}, @code{p?}, and @code{d}.
+
+@itemize @bullet
+@item
+@code{e} is an applicative that takes one argument, and returns a
+fresh encapsulation with the argument as content. Encapsulations
+returned on different occasions are not @code{eq?}.
+
+@item
+@code{p?} is a primitive type predicate, that takes zero or more
+arguments and returns true iff all of them are encapsulations
+generated by @code{e}.
+
+@item
+@code{d} is an applicative that takes one argument; if the argument is
+not an encapsulation generated by @code{e}, an error is signaled,
+otherwise the content of the encapsulation is returned.
+@end itemize
+
+That is, the predicate @code{p?} only recognizes, and the decapsulator
+@code{d} only extracts the content of, encapsulations created by the
+encapsulator @code{e} that was returned by the same call to
+@code{make-encapsulation-type}.
+@end deffn
diff --git a/manual/src/environments.texi b/manual/src/environments.texi
@@ -0,0 +1,298 @@
+@c -*-texinfo-*-
+@setfilename ../src/environments
+
+@node Environments, Combiners, Pairs and lists, Top
+@comment node-name, next, previous, up
+
+@chapter Environments
+@cindex environments
+@cindex ignore
+
+ An environment consists of a set of bindings, and a list of zero or
+more references to other environments called its parents.
+@c TODO add xref to lookup algo & ground env
+Changing the set of bindings of an environment, or setting the
+referent of the reference in a binding, is a mutation of the
+environment. (Changing the parent list, or a referent in the list,
+would be a mutation of the environment too, but there is no facility
+provided to do it.) The Kernel data type environment is encapsulated.
+Among other things, there is no facility provided for enumerating all
+the variables exhibited by an environment (which is not required,
+after all, to be a finite set), and no facility for identifying the
+parents of an environment. Two environments are @code{equal?} iff
+they are @code{eq?}.
+
+ An auxiliary data type used by combiners that perform binding is
+ignore. The ignore type consists of a single immutable value, having
+external representation @code{#ignore}. The ignore type is
+encapsulated.
+
+@deffn Applicative environment? (environment? . objects)
+ The primitive type predicate for type environment.
+@code{environment?} returns true iff all the objects in @code{objects}
+are of type environment.
+@end deffn
+
+@deffn Applicative ignore? (ignore? . objects)
+ The primitive type predicate for type ignore. @code{ignore?}
+returns true iff all the objects in @code{objects} are of type ignore.
+@end deffn
+
+@deffn Applicative eval (eval expression environment)
+@c TODO add xref to tail context
+@c TODO add xref to evaluation description
+ The @code{eval} applicative evaluates @code{expression} as a tail
+context in @code{environment}, and returns the resulting value.
+@end deffn
+
+@deffn Applicative make-environment (make-environment . environments)
+ The applicative constructs and returns a new environment, with
+initially no local bindings, and parent environments the environments
+listed in @code{environments}. The constructed environment internally
+stores its list of parents independent of the first-class list
+@code{environments}, so that subsequent mutation of
+@code{environments} will not change the parentage of the constructed
+environment. If the provided list @code{environments} is cyclic, the
+constructed environment will still check each of its parents at most
+once, and signal an error if no binding is found locally or in any of
+@c TODO add xref to cons, mutation, eq? and equal?
+the parents. No two objects returned by different calls to
+@code{make-environment} are @code{eq?} to each other.
+@end deffn
+
+@deffn Operative $define! ($define! <definiend> <expression>)
+@c TODO move formal parameter tree definition to the intro
+@c TODO move matching definition to the intro
+ @code{<definiend>} should be a formal parameter tree, as described
+below; otherwise, an error is signaled.
+
+ The @code{$define!} operative evaluates @code{<expression>} in the
+dynamic environment and matches @code{<definiend>} to the result in
+the dynamic environment, binding each symbol in definiend in the
+dynamic environment to the corresponding part of the result; the
+matching process will be further described below. The ancestors of the
+dynamic environment, if any, are unaffected by the matching process,
+as are all bindings, local to the dynamic environment, of symbols not
+in @code{<definiend>}. The result returned by @code{$define!} is
+inert.
+
+ A formal parameter tree has the following context-free structure:
+@example
+ptree:: symbol | #ignore | () | (ptree . ptree)
+@end example
+
+ That is, a formal parameter tree is either a symbol, or ignore, or
+nil, or a pair whose car and cdr referents are formal parameter trees.
+A formal parameter tree must also be acyclic, and no one symbol can
+occur more than once in it. It is not an error for a pair in the tree
+to be reachable from the root by more than one path, as long as there
+is no cycle; but if any particular symbol were reachable from the root
+by more than one path, that would count as occurring more than once.
+Thus, if a pair is reachable by more than one path, there must be no
+symbols reachable from it.
+
+ Matching of a formal parameter tree @code{t} to an object @code{o}
+in an environment @code{e} proceeds recursively as follows. If the
+matching process fails, an error is signaled.
+@itemize @bullet
+@item
+If @code{t} is a symbol, then @code{t} is bound to @code{o} in
+@code{e}.
+
+@item
+If @code{t} is @code{#ignore}, no action is taken.
+
+@item
+If @code{t} is nil, then @code{o} must be nil (else matching fails).
+
+@item
+If @code{t} is a pair, then @code{o} must be a pair (else matching
+fails). The car of @code{t} is matched to the car of @code{o} in
+@code{e}, and the cdr of @code{t} is matched to the cdr of @code{o} in
+@code{e}.
+@end itemize
+@end deffn
+
+@deffn Operative $let ($let <bindings> . <objects>)
+@c TODO add xref to formal parameter tree
+ @code{<bindings>} should be a finite list of
+formal-parameter-tree/expression pairings, each of the form
+@code{(formals expression)}, where each @code{formals} is a formal
+parameter, and no symbol occurs in more than one of the
+@code{formals}.
+
+The following equivalence holds:
+
+@example
+($let ((form1 exp1) ... (formn expn)) . objects) @equiv{}
+ (($lambda (form1 ... formn) . objects) exp1 ... expn)
+@end example
+
+@c TODO add xref to tail context
+Thus, the @code{expk} are first evaluated in the dynamic environment,
+in any order; then a child environment @code{e} of the dynamic
+environment is created, with the @code{formk} matched in @code{e} to
+the results of the evaluations of the @code{expk}; and finally the
+subexpressions of @code{objects} are evaluated in @code{e} from left
+to right, with the last (if any) evaluated as a tail context, or if
+@code{objects} is empty the result is inert.
+@end deffn
+
+@deffn Operative $binds? ($binds? <exp> . <symbols>)
+ Operative @code{$binds} evaluates @code{<exp>} in the dynamic
+environment; call the result @code{env}. @code{env} must be an
+environment. The operative is a predicate that returns true iff all
+its later operands, @code{<symbols>}, are visibly bound in @code{env}.
+@end deffn
+
+@deffn Applicative get-current-environment (get-current-environment)
+ The @code{get-current-environment} applicative returns the dynamic
+environment in which it is called.
+@end deffn
+
+@deffn Applicative make-kernel-standard-environment (make-kernel-standard-environment)
+@c TODO add xref to ground environment/standard environment
+ The @code{make-kernel-standard-environment} applicative returns a
+standard environment; that is, a child of the ground environment with
+no local bindings.
+@end deffn
+
+@deffn Operative $let* ($let* <bindings> . <body>)
+@c TODO add xref to formal ptree
+ @code{<bindings>} should be a finite list of
+formal-parameter-tree/expression pairings, each of the form
+@code{(formals expression)}, where each @code{formals} is a formal
+parameter tree; @code{<body>} should be a list of expressions.
+
+The following equivalences hold:
+
+@example
+($let* () . body) @equiv{} ($let () . body)
+
+($let* ((form exp) . bindings) . body) @equiv{}
+ ($let ((form exp)) ($let* bindings . body))
+@end example
+@end deffn
+
+@deffn Operative $letrec ($letrec <bindings> . <body>)
+@c add xref for $let
+ @code{<bindings>} and @code{<body>} should be as described for
+@code{$let}.
+
+ The following equivalence holds:
+@example
+($letrec ((form1 exp1) ... (formn expn)) . body) @equiv{}
+ ($let () ($define! (form1 ... formn) (list exp1 ... expn)) . body)
+@end example
+@end deffn
+
+@deffn Operative $letrec* ($letrec* <bindings> . <body>)
+@c TODO add xref to $let*
+ @code{<bindings>} and @code{<body>} should be as described for
+@code{$let*}.
+
+ The following equivalences hold:
+@example
+($letrec* () . body) @equiv{} ($letrec () . body)
+
+($letrec* ((form exp) . bindings) . body) @equiv{}
+ ($letrec ((form exp)) ($letrec* bindings . body))
+@end example
+@end deffn
+
+@deffn Operative $let-redirect ($let-redirect <exp> <bindings> . <body>)
+@c TODO add xref to $let
+ @code{<bindings>} and @code{<body>} should be as described for
+@code{$let}.
+
+ The following equivalence holds:
+
+@example
+($let-redirect exp ((form1 exp1) ... (formn . body) expn)) @equiv{}
+ ((eval (list $lambda (form1 ... formn) body) exp) expn ... expn)
+@end example
+@end deffn
+
+@deffn Operative $let-safe ($let-safe <bindings> . <body>)
+@c TODO add xref to $let
+ @code{<bindings>} and @code{<body>} should be as described for
+@code{$let}.
+
+ The following equivalence holds:
+
+@example
+($let-safe bindings . body) @equiv{}
+ ($let-redirect (make-kernel-standard-environment) bindings . body)
+@end example
+@end deffn
+
+@deffn Operative $remote-eval ($remote-eval <exp1> <exp2>)
+@c TODO add xref to tail context
+ Operative @code{$remote-eval} evaluates @code{<exp2>} in the dynamic
+environment, then evaluates @code{<exp1>} as a tail context in the
+environment that must result from the first evaluation.
+@end deffn
+
+@deffn Operative ($bindings-environment . <bindings>)
+@c TODO add xref to $let
+ @code{<bindings>} should be as described for @code{$let}.
+
+ The following equivalence holds:
+
+@example
+($bindings->environment . bindings) @equiv{}
+ ($let-redirect (make-environment) bindings (get-current-environment))
+@end example
+@end deffn
+
+@deffn Operative $set! ($set! <exp1> <formals> <exp2>)
+@c TODO add xref to $define!
+@c TODO add xref to matching algo
+ @code{<formals>} should be as described for the @code{$define!}
+operative. The @code{$set!} operative evaluates @code{<exp1>} and
+@code{<exp2>} in the dynamic environment; call the results @code{env}
+and @code{obj}. If @code{env} is not an environment, an error is
+signaled. Then the operative matches @code{<formals>} to @code{obj}
+in environment @code{env}. Thus, the symbols of @code{<formals>} are
+bound in @code{env} to the corresponding parts of @code{obj}.
+The result returned by @code{$set!} is inert.
+@end deffn
+
+@deffn Operative $provide! ($provide! <symbols> . <body>)
+ @code{<symbols>} must be a finite list of symbols, containing no
+duplicates. @code{<body>} must be a finite list.
+
+ The @code{$provide!} operative constructs a child @code{e} of the
+dynamic environment @code{d}; evaluates the elements of @code{<body>}
+in @code{e}, from left to right, discarding all of the results; and
+exports all of the bindings of symbols in @code{<symbols>} from
+@code{e} to @code{d}, i.e., binds each symbol in @code{d} to the
+result of looking it up in @code{e}. The result returned by
+@code{$provide!} is inert.
+
+The following equivalence holds:
+
+@example
+($provide! symbols . body) @equiv{}
+($define! symbols ($let () ($sequence . body) (list . symbols)))
+@end example
+@end deffn
+
+@deffn Operative $import! ($import! <exp> . <symbols>)
+ @code{<symbols>} must be a list of symbols.
+
+ The @code{$import!} operative evaluates @code{<exp>} in the dynamic
+environment; call the result @code{env}. @code{env} must be an
+environment. Each distinct symbol @code{s} in @code{<symbols>} is
+evaluated in @code{env}, and @code{s} is bound in the dynamic
+environment to the result of this evaluation.
+
+The following equivalence holds:
+
+@example
+($import! exp . symbols) @equiv{}
+($define! symbols ($remote-eval (list symbols) exp))
+@end example
+@end deffn
+
+
diff --git a/manual/src/equivalence.texi b/manual/src/equivalence.texi
@@ -0,0 +1,27 @@
+@c -*-texinfo-*-
+@setfilename ../src/equivalence
+
+@node Equivalence, Symbols, Booleans, Top
+@comment node-name, next, previous, up
+
+@chapter Equivalence
+@cindex equivalence
+
+ Kernel has two general-purpose equivalence predicates (whereas R5RS
+Scheme has three). The two Kernel predicates correspond to the
+abstract notions of equivalence up to mutation (@code{equal}) and
+equivalence in the presence of mutation (@code{eq?}).
+
+@deffn Applicative eq? (eq? . objects)
+ Predicate @code{eq?} returns true iff all of @code{objects} are
+effectively the same object, even in the presence of mutation.
+@c todo maybe add more content here, specifical to klisp
+@end deffn
+
+@deffn Applicative equal? (equal? . objects)
+ Predicate @code{equal?} returns true iff all of @code{objects}
+``look'' the same as long as nothing is mutated. This is a weaker
+predicate than @code{eq?}; that is, @code{equal?} must return true
+whenever @code{eq?} would return true.
+@c todo maybe add more content here, specifical to klisp
+@end deffn
diff --git a/manual/src/index.texi b/manual/src/index.texi
@@ -0,0 +1,10 @@
+@c -*-texinfo-*-
+@setfilename ../src/index
+
+@c TODO correct prev node
+@node Index, (dir), Ports, Top
+@c this is from the elisp manual... Should read a little about this.
+@unnumbered Index
+
+@printindex fn
+
diff --git a/manual/src/intro.texi b/manual/src/intro.texi
@@ -0,0 +1,336 @@
+@c -*-texinfo-*-
+@setfilename ../src/intro
+
+@node License, Introduction, Top, Top
+@comment node-name, next, previous, up
+
+klisp is licensed under the terms of the MIT license reproduced below.
+This means that klisp is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+The two projects whose code klisp uses, Lua & IMath, are also distributed
+under the MIT license.
+
+@itemize @bullet
+@item
+klisp Parts: Copyright @copyright{} 2011 Andres Navarro.
+@item
+Lua Parts: Copyright @copyright{} 1994-2010 Lua.org, PUC-Rio.
+@item
+IMath Parts: Copyright @copyright{} 2002-2007 Michael J. Fromberger.
+@item
+srfi-78: Copyright @copyright{} 2005-2006 Sebastian Egner.
+@end itemize
+
+@unnumbered MIT/X11 License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+@c next node should be types
+@node Introduction, Booleans, License, Top
+@chapter Introduction
+
+ klisp is an open source interpreter for the Kernel Programming
+Language. It aims at being comprehensive and robust as specified in
+the @cite{Revised(-1) Report on the Kernel Programming Language}, but
+that probably won't happen for some time. It is written in C99 under
+the MIT license. It draws heavily from the Lua interpreter source
+code & file structure. It uses the IMath library for arbitrary sized
+integers and rationals.
+
+ The Kernel programming language is a statically scoped and properly
+tail-recursive dialect of Lisp, descended from Scheme. It is designed
+to be simpler and more general than Scheme, with an exceptionally
+clear, simple, and versatile semantics, only one way to form compound
+expressions, and no inessential restrictions on the power of that one
+compound form. Imperative, functional, and message-passing programming
+styles (to name a few) may be conveniently expressed in Kernel.
+
+ An important property of Kernel is that all manipulable entities in
+Kernel are first-class objects. In particular, Kernel has no
+second-class combiners; instead, the roles of special forms and macros
+are subsumed by operatives, which are first-class, statically scoped
+combiners that act directly on their unevaluated operands. Kernel
+also has a second type of combiners, applicatives, which act on their
+evalu- ated arguments. Applicatives are roughly equivalent to Scheme
+procedures. However, an applicative is nothing more than a wrapper to
+induce operand evaluation, around an underlying operative (or, in
+principle, around another applicative, though that isn’t usually
+done); applicatives themselves are mere facilitators to computation.
+
+ You can read more about Kernel at
+@url{http://web.cs.wpi.edu/~jshutt/kernel.html}.
+
+ klisp is freely available for both academic and commercial purposes.
+See LICENSE for details. it can be downloaded at
+@url{http://www.bitbucket.org/AndresNavarro/klisp}
+
+ klisp is developed by Andres Navarro, a Computer Science
+undergraduate at Buenos Aires University (UBA). You can reach him at
+@email{canavarro82@@gmail.com}.
+
+ This manual describes klisp version 0.1, presuming some familiarity
+with the Lisp family of languages in general, and with the Kernel
+Programming Language in particular. There are frequent references to
+the Kernel Programming Language Report. Unlike in the report, no
+rationale is provided for any feature, only a description of the
+implemented functionality.
+
+ This is edition 0.1.
+
+@menu
+* Caveats:: Flaws and a request for help.
+* Kernel History:: Kernel is descended from Scheme.
+* Conventions:: How the manual is formatted.
+* Acknowledgements:: Contributions to this manual.
+@end menu
+
+@node Caveats, Kernel History, Introduction, Introduction
+@section Caveats
+
+ This is the first draft of this manual. It will be incomplete for
+some time. It will also evolve, together with klisp and the Kernel
+Programming Language, both of which, right now, are in a quite fluid
+state.
+
+@c this is below, in history
+ The main reference on Kernel is the preliminary report:
+@cite{Revised(-1) Report on the Kernel Programming Language}. Some
+sections of the report are still incomplete, so both klisp and this
+manual will use specifications from other languages in these sections,
+trying to follow the Kernel spirit. These instances will be documented
+throughout the manual.
+
+Please mail comments and corrections to
+@email{canavarro82@@gmail.com}.
+
+@noindent
+@display
+ --Andres Navarro
+@end display
+
+@node Kernel History, Conventions, Caveats, Introduction
+@section Kernel History
+@cindex Kernel history
+
+ The Kernel Programming Language is a work in progress. It is being
+developed by John N. Shutt, Ph.D, who created it while studying at the
+Worcester Polytechnic Institute (I think about 2002, or so... ASK). It
+is descended from scheme, with the idea that all objects should be
+first class values. In particular, Kernel replaces macros with
+operatives (kinda like statically scoped fexprs and fsubrs) and has
+first class environments. Kernel also has the notion of encapsulated
+objects which limits the ammount of information an implementation can
+share with a Kernel program (e.g. There is no way in Kernel to get the
+parents or a complete list of bindings of an environment object).
+
+@c this is repeated above, in caveats
+ The main reference on Kernel is the preliminary report:
+@cite{Revised(-1) Report on the Kernel Programming Language}. Some
+sections of the report are still incomplete, so both klisp and this
+manual will use specifications from other languages in these sections,
+trying to follow the Kernel spirit. These instances will be documented
+throughout the manual.
+
+ You can read all about Kernel at John's homepage at WPI
+@url{http://www.cs.wpi.edu/~jshutt/}, including the preliminary report
+on the language and his doctoral dissertation which gives a
+theorethical frame for fexprs. You can contact him at
+@email{jshutt@@cs.wpi.edu}.
+
+@node Conventions, Acknowledgements, Kernel History, Introduction
+@section Conventions
+
+ This section explains the notational conventions that are used in this
+manual. You may want to skip this section and refer back to it later.
+
+@menu
+* Some Terms:: Explanation of terms we use in this manual.
+@c TODO add sections for booleans, parameter trees, list structures,
+@c naming conventions, etc.
+* Evaluation Notation:: The format we use for examples of evaluation.
+* Printing Notation:: The format we use for examples that print output.
+* Error Messages:: The format we use for examples of errors.
+* Format of Descriptions:: Notation for describing functions, variables, etc.
+@end menu
+
+@node Some Terms, Evaluation Notation, Conventions, Conventions
+@subsection Some Terms
+
+ Throughout this manual, the phrases ``the Kernel reader'' and ``the Kernel
+printer'' are used to refer to those routines in Lisp that convert
+textual representations of Kernel objects into actual objects, and
+@c TODO xref to printed representations
+vice versa. XXX Printed Representation XXX, for more details. You, the
+person reading this manual, are assumed to be ``the programmer'' or
+``the user''.
+
+@cindex fonts
+ Examples of Kernel code appear in this font or form: @code{(list 1 2
+3)}. Names that represent arguments or metasyntactic variables appear
+in this font or form: @var{first-number}.
+
+@node Evaluation Notation, Printing Notation, Some Terms, Conventions
+@subsection Evaluation Notation
+@cindex evaluation notation
+@cindex documentation notation
+
+ When you evaluate a piece of Kernel code, it produces a result. In the
+examples in this manual, this is indicated with @samp{@result{}}:
+
+@example
+(car (cons 1 2))
+ @result{} 1
+@end example
+
+@noindent
+You can read this as ``@code{(car (cons 1 2))} evaluates to 1''.
+
+ The semantics of a language feature are sometimes clarified, or even
+defined, in its entry by specifying that two expressions are
+equivalent. This is notated with @samp{@equiv{}}. For example, the
+semantics of applicative list* can be defined by following
+equivalences:
+@example
+(list* arg1) @equiv{} arg1
+(list* arg1 . more-args) @equiv{} (cons arg1 (list* . more-args))
+@end example
+Notice that in these kind of examples the applicatives or operatives
+referred to are the first class values and not the symbols bound to
+them in the ground environment. This definition would hold even if
+@code{cons} or @code{list*} were redefined in the current dynamic
+environment.
+
+@node Printing Notation, Error Messages, Evaluation Notation, Conventions
+@subsection Printing Notation
+@cindex printing notation
+
+ Many of the examples in this manual print text when they are
+evaluated. In examples that print text, the printed text is indicated with
+@samp{@print{}}. The value returned by evaluating the form (here
+@code{#t}) follows on a separate line.
+
+@group
+@example
+($sequence (write 1) (write 2) #t)
+ @print{} 1
+ @print{} 2
+ @result{} #t
+@end example
+@end group
+
+@node Error Messages, Format of Descriptions, Printing Notation, Conventions
+@subsection Error Messages
+@cindex error message notation
+
+ Some examples cause errors to be signaled. The report doesn't
+specify what objects are passed to the error continuation, but in
+klisp, objects passed to the error continuation are encapsulated error
+objects that have at least a message and possibly some additional
+objects and context informations (such as source code location). In
+the examples, the error message is shown on a line starting with
+@samp{@error{}}.
+
+@example
+(+ 23 #t)
+@error{} Wrong type argument: (expected number) (#t)
+@end example
+
+@node Format of Descriptions, , Error Messages, Conventions
+@subsection Format of Descriptions
+@cindex description format
+
+ Applicatives, operatives, and other objects are described in this manual
+in a uniform format. The first line of a description contains the
+name of the item followed by its operands or arguments, if any.
+@ifinfo
+The category---operative, applicative, or whatever---appears at the
+beginning of the line.
+@end ifinfo
+@iftex
+The category---operative, applicative, or whatever---is printed next to the
+right margin.
+@end iftex
+The description follows on succeeding lines, sometimes with examples.
+
+@menu
+* A Sample Applicative Description::
+@c TODO add operative and/or variable like root-continuation
+@end menu
+
+@node A Sample Applicative Description, , Format of Descriptions, Format of Descriptions
+@subsubsection A Sample Applicative Description
+@cindex applicative descriptions
+@cindex operative descriptions
+@cindex object descriptions
+
+ In an applicative description, the name of the applicative being
+described appears first. It is followed on the same line by an
+applicative combination that includes the name of the applicative and
+the arguments, as would appear in a program. The names used for the
+arguments are also used in the body of the description.
+
+ Here is a description of an imaginary applicative @code{foo}:
+
+@deffn Applicative foo (foo integer1 integer2 . rest)
+ The applicative @code{foo} subtracts @var{integer1} from @var{integer2},
+then adds all the rest of the arguments to the result.
+
+@example
+(foo 1 5 3 9)
+ @result{} 16
+@end example
+
+More generally,
+
+@example
+(foo @var{w} @var{x} @var{y}@dots{})
+@equiv{}
+(+ (- @var{x} @var{w}) @var{y}@dots{})
+@end example
+@end deffn
+
+ Any parameter whose name contains the name of a type (e.g.,
+@var{integer}, @var{integer1} or @var{continuation}) is expected to be of that
+type. A plural of a type (such as @var{numbers}) often means a list of
+objects of that type. Parameters named @var{object} may be of any
+type. Additionally parameters named @var{k}, or @var{kn} (for any
+value of @var{n}), should be exact, non-negative integers.
+@c TODO add xref types of objects
+(XXX Types of Lisp Object XXX, for a list of Kernel object types.)
+Parameters with other sorts of names are
+discussed specifically in the description of the combiner. In some
+sections, features common to parameters of several combiners are
+described at the beginning.
+
+@c TODO xref to ptree
+@c TODO clean this up a little
+ Operative descriptions have the same format, but the word
+`Applicative' is replaced by `Operative', and `Argument' is replaced
+by `Operand'. Also Operatives always have an environment parameter
+(that can be #ignore or a symbol).
+
+@node Acknowledgements,, Conventions, Introduction
+@section Acknowledgements
+
+ This manual was written by Andres Navarro.
+
+ The structure and some text for this introductory section were
+borrowed from the Elisp Manual by the Free Sofware Foundation. This
+manual also borrows freely from both the Kernel Report and the Scheme
+Reports.
diff --git a/manual/src/keyed_vars.texi b/manual/src/keyed_vars.texi
@@ -0,0 +1,76 @@
+@c -*-texinfo-*-
+@setfilename ../src/keyed variables
+
+@node Keyed Variables, Numbers, Promises, Top
+@comment node-name, next, previous, up
+
+@chapter Keyed Variables
+@cindex keyed variables
+
+ A keyed variable is a device that associates a non-symbolic key (in
+the form of an accessor applicative) with a value depending on the
+context in which lookup occurs. Kernel provides two types of keyed
+variables: dynamic & static. Keyed Dynamic Variables use the dynamic
+extent as context and Keyed Static Variables use the dynamic
+environment.
+
+@section Keyed Dynamic Variables
+@cindex keyed dynamic variables
+@c add cf xref static
+@c TODO add xref to dynamic extent
+ A keyed dynamic variable is a device that associates a non-symbolic
+key (in the form of an accessor applicative) with a value depending on
+the dynamic extent in which lookup occurs.
+
+@deffn Applicative make-keyed-dynamic-variable (make-keyed-dynamic-variable)
+ Returns a list of the form @code{(b a)}, where @code{b} and @code{a}
+are applicatives, as follows. Each call to
+@code{make-keyed-dynamic-variable} returns different @code{b} and
+@code{a}.
+
+@itemize @bullet
+@item
+@code{b} is an applicative that takes two arguments, the second of
+which must be a combiner. It calls its second argument with no
+operands (nil operand tree) in a fresh empty environment, and returns
+the result.
+
+@item
+@code{a} is an applicative that takes zero arguments. If the call to
+@code{a} occurs within the dynamic extent of a call to @code{b}, then
+@code{a} returns the value of the first argument passed to @code{b} in
+the smallest enclosing dynamic extent of a call to @code{b}. If the
+call to @code{a} is not within the dynamic extent of any call to
+@code{b}, an error is signaled.
+@end itemize
+@end deffn
+
+@section Keyed Static Variables
+@cindex keyed static variables
+ A keyed static variable is a device that binds data in an
+environment by a non-symbolic key, where the key is an accessor
+applicative.
+@c add cf xref dynamic
+
+@deffn Applicative make-keyed-static-variable (make-keyed-static-variable)
+ Returns a list of the form @code{(b a)}, where @code{b} and @code{a}
+are applicatives, as follows. Each call to @code{make-keyed-static-variable}
+returns different @code{b} and @code{a}.
+
+@itemize @bullet
+@item
+@code{b} is an applicative that takes two arguments, the second of
+which must be an environment. It constructs and returns a
+child-environment of its second argument, with initially no local
+bindings.
+
+@item
+@code{a} is an applicative that takes zero arguments. If the dynamic
+environment @code{e} of the call to a has an improper ancestor that
+was constructed by a call to @code{b}, then a returns the value of the
+first argument passed to @code{b} in the first such environment
+encountered by a depth-first traversal of the improper ancestors of
+@code{e}. If @code{e} has no improper ancestors constructed via
+@code{b}, an error is signaled.
+@end itemize
+@end deffn
diff --git a/manual/src/klisp.texi b/manual/src/klisp.texi
@@ -0,0 +1,150 @@
+input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename klisp
+@settitle klisp Reference Manual
+@c %**end of header
+
+@c TODO probably don't use all of these, this is from elisp
+@c Combine indices.
+@synindex cp fn
+@syncodeindex vr fn
+@syncodeindex ky fn
+@syncodeindex pg fn
+@syncodeindex tp fn
+@c oops: texinfo-format-buffer ignores synindex
+@c
+
+@ifinfo
+This file documents klisp.
+
+@c The edition number appears in several places in this file
+@c and also in the file intro.texi.
+This is edition 0.1 of the klisp Reference Manual,
+for klisp version 0.1.
+
+Copyright (C) 2011 Andres Navarro
+
+Permission is granted to copy and distribute this manual, in whole or
+in part, without fee. Please note that most text of this
+manual is derived from @cite{The Revised(-1) Report on the Kernel
+Programming Language} by John N. Shutt. There's a clause in that
+reports, under the header ``Permission to copy this report'', that
+reads:
+@quotation
+This report is intended to belong to the programming community, and so
+permission is granted to copy it in whole or in part without fee.
+@end quotation
+@end ifinfo
+
+@setchapternewpage odd
+
+@titlepage
+@title klisp Reference Manual
+@subtitle klisp version 0.1
+@c The edition number appears in several places in this file
+@c and also in the file intro.texi.
+@subtitle Edition 0.1, May 2011
+
+@author by Andres Navarro
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 2011 Andres Navarro
+
+@sp 2
+This is edition 0.1 of the @cite{klisp Reference Manual},
+for klisp Version 01.,@*
+May 2011.@*
+
+@sp 2
+
+Permission is granted to copy and distribute this manual, in whole or
+in part, without fee. Please note that most text of this
+manual is derived from @cite{The Revised(-1) Report on the Kernel
+Programming Language} by John N. Shutt. There's a clause in that
+reports, under the header ``Permission to copy this report'', that
+reads:
+@quotation
+This report is intended to belong to the programming community, and so
+permission is granted to copy it in whole or in part without fee.
+@end quotation
+@end titlepage
+@page
+
+@node Top, License, (dir), (dir)
+
+@ifinfo
+This Info file contains edition 0.1 of the klisp Reference Manual,
+corresponding to klisp version 0.1.
+
+Copyright @copyright{} 2011 Andres Navarro
+
+Permission is granted to copy and distribute this manual, in whole or
+in part, without fee. Please note that most text of this
+manual is derived from @cite{The Revised(-1) Report on the Kernel
+Programming Language} by John N. Shutt. There's a clause in that
+reports, under the header ``Permission to copy this report'', that
+reads:
+@quotation
+This report is intended to belong to the programming community, and so
+permission is granted to copy it in whole or in part without fee.
+@end quotation
+@end ifinfo
+
+@menu
+* License:: Conditions for copying and changing klisp.
+* Introduction:: Introduction and conventions used.
+@c TODO lisp types and other introductions
+* Booleans:: Booleans module features.
+* Equivalence:: Equivalence (under & up to) mutation modules features.
+* Symbols:: Symbols module features.
+* Control:: Control module features.
+* Pairs and lists:: Pairs and lists and Pair mutation modules features.
+* Environments:: Environments and Environment mutation modules features.
+* Combiners:: Combiners module features.
+* Continuations:: Continuations module features.
+* Encapsulations:: Encapsulations module features.
+* Promises:: Promises module features.
+* Keyed Variables:: Keyed (dynamic & static) variables module features.
+* Numbers:: Numbers module features.
+* Strings:: Strings module features.
+* Characters:: Characters module features.
+* Ports:: Ports module features.
+@c TODO add error objs to both klisp and the manual
+* Index:: Index including concepts, functions, variables,
+ and other terms.
+
+@c Appendices
+@c TODO
+
+@c TODO add detailed node listing
+@end menu
+
+@include intro.texi
+@include booleans.texi
+@include equivalence.texi
+@include symbols.texi
+@include control.texi
+@include pairs_lists.texi
+@include environments.texi
+@include combiners.texi
+@include continuations.texi
+@include encapsulations.texi
+@include promises.texi
+@include keyed_vars.texi
+@include numbers.texi
+@include strings.texi
+@include characters.texi
+@include ports.texi
+
+@c appendices
+@c TODO
+
+@include index.texi
+
+@c Print the tables of contents
+@summarycontents
+@contents
+
+@c That's all
+
+@bye
diff --git a/manual/src/numbers.texi b/manual/src/numbers.texi
@@ -0,0 +1,8 @@
+@c -*-texinfo-*-
+@setfilename ../src/numbers
+
+@node Numbers, Strings, Keyed Variables, Top
+@comment node-name, next, previous, up
+
+@chapter Numbers
+@cindex numbers
diff --git a/manual/src/pairs_lists.texi b/manual/src/pairs_lists.texi
@@ -0,0 +1,415 @@
+@c -*-texinfo-*-
+@setfilename ../src/pairs_lists
+
+@node Pairs and lists, Environments, Control, Top
+@comment node-name, next, previous, up
+
+@chapter Pairs and lists
+@cindex pairs
+@cindex nil
+@cindex empty list
+@cindex lists
+
+A pair is an object that refers to two other objects, called its car
+and cdr. The Kernel data type pair is encapsulated.
+
+ The null data type consists of a single immutable value, called nil
+or the empty list and having external representation @code{()}, with
+or without whitespace between the parentheses. It is immutable, and
+the null type is encapsulated.
+
+ If @code{a} and @code{d} are external representations of
+respectively the car and cdr of a pair @code{p}, then @code{(a . d)}
+is an external representation of @code{p}. If the cdr of @code{p} is
+nil, then @code{(a)} is also an external representation of
+@code{p}. If the cdr of @code{p} is a pair @code{p2}, and @code{(r)}
+is an external representation of @code{p2}, then @code{(a r)} is an
+external representation of @code{p}.
+@c add xref for write
+ When a pair is output (as by write), an external representation with
+the fewest parentheses is used; in the case of a finite list, only one
+set of parentheses is required beyond those used in representing the
+elements of the list. For example, an object with external
+representation @code{(1 . (2 . (3 . ())))} would be output using,
+modulo whitespace, external representation @code{(1 2 3)}.
+
+@deffn Applicative pair? (pair? . objects)
+ The primitive type predicate for type pair. @code{pair?} returns
+true iff all the objects in @code{objects} are of type pair.
+@end deffn
+
+@deffn Applicative null? (null? . objects)
+ The primitive type predicate for type null. @code{null?} returns
+true iff all the objects in @code{objects} are of type null.
+@end deffn
+
+@deffn Applicative cons (cons object1 object2)
+ A new mutable pair object is constructed and returned, whose car and
+cdr referents are respectively @code{object1} and @code{object2}. No
+two objects returned by different calls to cons are @code{eq?} to each
+other.
+@end deffn
+
+@deffn Applicative set-car! (set-car! pair object)
+@deffnx Applicative set-cdr! (set-cdr! pair object)
+ @code{pair} should be a mutable pair.
+
+ These applicatives set the referent of, respectively, the car
+reference or the cdr reference of @code{pair} to @code{object}. The
+result of the expression is inert.
+@end deffn
+
+@deffn Applicative copy-es-immutable! (copy-es-immutable object)
+ The short description of this applicative is that it returns an object
+@code{equal?} to @code{object} with an immutable evaluation structure. The
+``-es-'' in the name is short for ``evaluation structure''.
+
+@c TODO move the evaluation structure description to the intro
+ The evaluation structure of an object @code{o} is defined to be the
+set of all pairs that can be reached by following chains of references
+from @code{o} without ever passing through a non-pair object. The
+evaluation structure of a non-pair object is empty.
+
+ If @code{object} is not a pair, the applicative returns @code{object}.
+Otherwise (if @code{object} is a pair), the applicative returns an
+immutable pair whose car and cdr would be suitable results for
+@code{(copy-es-immutable (car object))} and @code{(copy-es-immutable
+(cdr object))}, respectively. Further, the evaluation structure of
+@c TODO add xref for isomorphic (and add isomorphic to the intro)
+the returned value is isomorphic to that of @code{object} at the time
+of copying, with corresponding non-pair referents being @code{eq?}.
+
+ NOTE: In Kernel it's undefined whether immutable pairs are copied or
+left ``as is'' in the result. klisp doesn't copy immutable pairs, but
+that behaviour should not be depended upon.
+@end deffn
+
+@deffn Applicative list (list . objects)
+The @code{list} applicative returns @code{objects}.
+
+ The underlying operative of @code{list} returns its undifferentiated
+operand tree, regardless of whether that tree is or is not a list.
+@end deffn
+
+@deffn Applicative list* (list* . objects)
+@code{objects} should be a finite nonempty list of arguments.
+
+ The following equivalences hold:
+@example
+(list* arg1) @equiv{} arg1
+(list* arg1 arg2 . args) @equiv{} (cons arg1 (list* arg2 . args))
+@end example
+@end deffn
+
+@deffn Applicative car (car pair)
+@deffnx Applicative cdr (cdr pair)
+These applicatives return, respectively, the car and cdr of @code{pair}.
+@end deffn
+@deffn Applicative caar (caar pair)
+@deffnx Applicative cadr (cadr pair)
+@deffnx Applicative cdar (cdar pair)
+@deffnx Applicative cddr (cddr pair)
+@deffnx Applicative caaar (caaar pair)
+@deffnx Applicative caadr (caadr pair)
+@deffnx Applicative cadar (cadar pair)
+@deffnx Applicative caddr (caddr pair)
+@deffnx Applicative cdaar (cdaar pair)
+@deffnx Applicative cdadr (cdadr pair)
+@deffnx Applicative cddar (cddar pair)
+@deffnx Applicative cdddr (cdddr pair)
+@deffnx Applicative caaaar (caaaar pair)
+@deffnx Applicative caaadr (caaadr pair)
+@deffnx Applicative caadar (caadar pair)
+@deffnx Applicative caaddr (caaddr pair)
+@deffnx Applicative cadaar (cadaar pair)
+@deffnx Applicative cadadr (cadadr pair)
+@deffnx Applicative caddar (caddar pair)
+@deffnx Applicative cadddr (cadddr pair)
+@deffnx Applicative cdaaar (cdaaar pair)
+@deffnx Applicative cdaadr (cdaadr pair)
+@deffnx Applicative cdadar (cdadar pair)
+@deffnx Applicative cdaddr (cdaddr pair)
+@deffnx Applicative cddaar (cddaar pair)
+@deffnx Applicative cddadr (cddadr pair)
+@deffnx Applicative cdddar (cdddar pair)
+@deffnx Applicative cddddr (cddddr pair)
+
+@c TODO add note about pronunciation
+These applicatives are compositions of @code{car} and @code{cdr}, with
+the ``a’s'' and ``d’s'' in the same order as they would appear if all
+the individual ``car’s'' and ``cdr’s'' were written out in prefix
+order. Arbitrary compositions up to four deep are provided. There are
+twenty-eight of these applicatives in all.
+@end deffn
+
+@deffn Applicative get-list-metrics (get-list-metrics object)
+@c TODO move definition of improper list to intro, xref data structure
+ By definition, an improper list is a data structure whose objects
+are its start together with all objects reachable from the start by
+following the cdr references of pairs, and whose internal references
+are just the cdr references of its pairs. Every object, of whatever
+type, is the start of an improper list. If the start is not a pair,
+the improper list consists of just that object. The acyclic prefix
+length of an improper list @code{L} is the number of pairs of @code{L}
+that a naive traversal of @code{L} would visit only once. The cycle
+length of @code{L} is the number of pairs of @code{L} that a naive
+traversal would visit repeatedly. Two improper lists are structurally
+@c TODO add xref to isomorphic
+isomorphic iff they have the same acyclic prefix length and cycle
+length and, if they are terminated by non-pair objects rather than by
+cycles, the non-pair objects have the same type. Applicative
+@code{get-list-metrics} constructs and returns a list of exact
+integers of the form @code{(p n a c)}, where @code{p}, @code{n},
+@code{a}, and @code{c} are, respectively, the number of pairs in, the
+number of nil objects in, the acyclic prefix length of, and the cycle
+length of, the improper list starting with @code{object}. @code{n} is
+either @code{0} or @code{1}, @code{a + c = p}, and @code{n} and
+@code{c} cannot both be non-zero. If @code{c = 0}, the improper list
+is acyclic; if @code{n = 1}, the improper list is a finite list; if
+@code{n = c = 0}, the improper list is not a list; if @code{a = c =
+0}, @code{object} is not a pair.
+@end deffn
+
+@deffn Applicative list-tail (list-tail object k)
+@code{object} must be the start of an improper list containing at
+least @code{k} pairs.
+
+ The @code{list-tail} applicative follows @code{k} cdr references
+starting from @code{object}.
+
+The following equivalences hold:
+@example
+(list-tail object 0) @equiv{} object
+(list-tail object (+ k 1)) @equiv{} (list-tail (cdr object) k)
+@end example
+@end deffn
+
+@deffn Applicative encycle! (encycle! object k1 k2)
+ The improper list starting at @code{object} must contain at least
+@code{k1 + k2} pairs.
+
+ If @code{k2 = 0}, the applicative does nothing. If @code{k2 > 0},
+the applicative mutates the improper list starting at @code{object} to
+have acyclic prefix length @code{k1} and cycle length @code{k2}, by
+setting the cdr of the @code{(k1+k2)}th pair in the list to refer to
+the @code{(k1 + 1)}th pair in the list. The result returned by
+@code{encycle!} is inert.
+@end deffn
+
+@deffn Applicative map (map applicative . lists)
+ @code{lists} must be a nonempty list of lists; if there are two or
+@c TODO add xref to length
+more, they must all have the same length.
+
+ The map applicative applies @code{applicative} element-wise to the
+elements of the lists in lists (i.e., applies it to a list of the
+first elements of the lists, to a list of the second elements of the
+lists, etc.), using the dynamic environment from which map was called,
+and returns a list of the results, in order. The applications may be
+performed in any order, as long as their results occur in the
+resultant list in the order of their arguments in the original lists.
+If @code{lists} is a cyclic list, each argument list to which
+@c TODO xref to ismorphic
+@code{applicative} is applied is structurally isomorphic to @code{lists}. If
+any of the elements of @code{lists} is a cyclic list, they all must
+be, or they wouldn’t all have the same length. Let @code{a1...an} be
+their acyclic prefix lengths, and @code{c1...cn} be their cycle
+lengths. The acyclic prefix length @code{a} of the resultant list
+will be the maximum of the @code{ak}, while the cycle length @code{c}
+of the resultant list will be the least common multiple of the
+@code{ck}. In the construction of the result, @code{applicative} is
+called exactly @code{a + c} times.
+@end deffn
+
+@deffn Applicative length (length object)
+@c TODO xref improper-list
+ Applicative @code{length} returns the (exact) improper-list length
+of @code{object}. That is, it returns the number of consecutive cdr
+references that can be followed starting from @code{object}. If
+@code{object} is not a pair, it returns zero; if @code{object} is a
+cyclic list, it returns positive infinity.
+@end deffn
+
+@deffn Applicative list-ref (list-ref object k)
+ The @code{list-ref} applicative returns the @code{car} of the object
+obtained by following @code{k} cdr references starting from
+@code{object}.
+
+NOTE: In the current report, object is required to be a list. In
+klisp, for now, we prefer the behaviour presented here, as it is more
+in line with the applicative @code{list-tail}. That is, we define
+@code{list-ref} by the following equivalence:
+@example
+(list-ref object k) @equiv{} (car (list-tail object k))
+@end example
+@end deffn
+
+@deffn Applicative append (append . lists)
+ Here, all the elements of @code{lists} except the last element (if
+any) must be acyclic lists. The @code{append} applicative returns a
+freshly allocated list of the elements of all the specified
+@code{lists}, in order, except that if there is a last specified
+element of @code{lists}, it is not copied, but is simply referenced by
+the cdr of the preceding pair (if any) in the resultant list. If
+@code{lists} is cyclic, the cycle of the result list consists of just
+the elements of the lists specified in the cycle in @code{lists}. In
+this case, the acyclic prefix length of the result is the sum of the
+lengths of the lists specified in the acyclic prefix of @code{lists},
+and the cycle length of the result is the sum of the lengths of the
+lists specified in the cycle of @code{lists}.
+
+The following equivalences hold:
+@example
+(append) @equiv{} ()
+(append h) @equiv{} h
+(append () h . t) @equiv{} (append h . t)
+(append (cons a b) h . t) @equiv{} (cons a (append b h . t))
+@end example
+@c TODO add xref/comp to append
+@end deffn
+
+@deffn Applicative list-neighbors (list-neighbors list)
+ The @code{list-neighbors} applicative constructs and returns a list
+of all the consecutive sublists of @code{list} of length 2, in order.
+If @code{list} is nil, the result is nil. If @code{list} is non-nil,
+the length of the result is one less than the length of
+@code{list}. If @code{list} is cyclic, the result is structurally
+isomorphic to it (i.e., has the same acyclic prefix length and cycle
+length).
+@c TODO add xref to isomorphic
+
+ For example:
+@example
+(list-neighbors (list 1 2 3 4)) @result{} ((1 2) (2 3) (3 4))
+@end example
+@end deffn
+
+@deffn Applicative filter (filter applicative list)
+ Applicative @code{filter} passes each of the elements of @code{list}
+as an argument to @code{applicative}, one at a time in no particular
+order, using a fresh empty environment for each call. The result of
+each call to @code{applicative} must be boolean, otherwise an error is
+signaled. @code{filter} constructs and returns a list of all elements
+of @code{list} on which @code{applicative} returned true, in the same
+order as in @code{list}. @code{applicative} is called exactly as many
+times as there are pairs in @code{list}. The resultant list has a
+cycle containing exactly those elements accepted by @code{applicative}
+that were in the cycle of @code{list}; if there were no such elements,
+the result is acyclic.
+@end deffn
+
+@deffn Applicative assoc (assoc object pairs)
+ Applicative @code{assoc} returns the first element of @code{pairs}
+whose car is @code{equal?} to @code{object}. If there is no such
+element in @code{pairs}, nil is returned.
+@c TODO add xref/comp to assq
+@c TODO add xref to equal?
+@end deffn
+
+@deffn Applicative member? (member? object list)
+ Applicative @code{member?} is a predicate that returns true iff some
+element of @code{list} is @code{equal?} to @code{object}.
+@c TODO add xref/comp to memq
+@c TODO add xref to equal?
+@end deffn
+
+@deffn Applicative finite-list? (finite-list? . objects)
+ This is the type predicate for type finite-list.
+@code{finite-list?} returns true iff all the objects in
+@code{objects} are acyclic lists.
+@end deffn
+
+@deffn Applicative countable-list? (countable-list? . objects)
+This is the type predicate for type list. @code{countable-list?}
+returns true iff all the objects in @code{objects} are lists.
+@end deffn
+
+@deffn Applicative reduce (reduce list binary identity [precycle incycle postcycle])
+ @code{binary} should be an applicative. If the short form is used,
+@code{list} should be an acyclic. If the long form is used,
+@code{precycle}, @code{incycle}, and @code{postcycle} should be
+applicatives.
+
+ If @code{list} is empty, applicative @code{reduce} returns
+@code{identity}. If @code{list} is nonempty but acyclic, applicative
+@code{reduce} uses binary operation @code{binary} to merge all the
+elements of @code{list} into a single object, using any associative
+grouping of the elements. That is, the sequence of objects initially
+found in @code{list} is repeatedly decremented in length by applying
+@code{binary} to a list of any two consecutive objects, replacing
+those two objects with the result at the point in the sequence where
+they occurred; and when the sequence contains only one object, that
+object is returned. If @code{list} is cyclic, the long form must be
+used. The elements of the cycle are passed, one at a time (but just
+once for each position in the cycle), as arguments to unary
+applicative @code{precycle}; the finite, cyclic sequence of results
+from @code{precycle} is reduced using binary applicative
+@code{incycle}; and the result from reducing the cycle is passed as an
+argument to unary applicative @code{postcycle}. Binary operation
+@code{binary} is used to reduce the sequence consisting of the
+elements of the acyclic prefix of @code{list} followed by the result
+returned by @code{postcycle}. The only constraint on the order of
+calls to the applicatives is that each call must be made before its
+result is needed (thus, parts of the reduction of the acyclic prefix
+may occur before the contribution from the cycle has been completed).
+
+ Each call to @code{binary}, @code{precycle}, @code{incycle}, or
+@code{postcycle} uses the dynamic environment of the call to
+@code{reduce}.
+
+ If @code{list} is acyclic with length @code{n >= 1},
+@code{binary} is called @code{n - 1} times. If @code{list} is cyclic
+with acyclic prefix length @code{a} and cycle length @code{c},
+@code{binary} is called @code{a} times; @code{precycle}, @code{c}
+times; @code{incycle}, @code{c - 1} times; and @code{postcycle}, once.
+@end deffn
+
+@deffn Applicative append! (append! . lists)
+ @code{lists} must be a nonempty list; its first element must be an
+acyclic nonempty list, and all of its elements except the last element
+(if any) must be acyclic lists.
+
+ The @code{append!} applicative sets the cdr of the last pair in each
+nonempty list argument to refer to the next non-nil argument, except
+that if there is a last non-nil argument, it isn’t mutated. It is an
+error for any two of the list arguments to have the same last pair.
+The result returned by this applicative is inert.
+
+ The following equivalences hold:
+@example
+(append! v) @equiv{} #inert
+(append! u v . w) @equiv{} ($sequence (append! u v) (append! u . w))
+@end example
+@end deffn
+
+@deffn Applicative copy-es (copy-es object)
+ Briefly, applicative @code{copy-es} returns an object initially
+@code{equal?} to @code{object} with a freshly constructed evaluation
+@c TODO add xref to evaluation structure
+structure made up of mutable pairs. If @code{object} is not a pair,
+the applicative returns @code{object}. If @code{object} is a pair,
+the applicative returns a freshly constructed pair whose car and cdr
+would be suitable results for @code{(copy-es (car object))} and
+@code{(copy-es (cdr object))}, respectively. Further, the evaluation
+@c TODO add xref to isomorphic
+structure of the returned value is structurally isomorphic to that of
+@code{object} at the time of copying, with corresponding non-pair
+referents being @code{eq?}.
+@c TODO add xref/comp to copy-es-immutable and the reverse too!
+@c TODO add xref to eq?/equal?
+@end deffn
+
+@deffn Applicative assq (assq object pairs)
+ Applicative @code{assq} returns the first element of @code{pairs}
+whose car is @code{eq?} to @code{object}. If there is no such element
+in @code{pairs}, nil is returned.
+@c TODO add xref/comp to assoc
+@c TODO add xref to eq?
+@end deffn
+
+@deffn Applicative memq? (memq? object list)
+ Applicative @code{memq?} is a predicate that returns true iff some
+element of @code{list} is @code{eq?} to @code{object}.
+@c TODO add xref/comp to member?
+@c TODO add xref to eq?
+@end deffn
diff --git a/manual/src/ports.texi b/manual/src/ports.texi
@@ -0,0 +1,272 @@
+@c -*-texinfo-*-
+@setfilename ../src/ports
+
+@node Ports, Index, Characters, Top
+@comment node-name, next, previous, up
+
+@chapter Ports
+@cindex ports
+
+ A port is an object that mediates character-based input from a
+source or character-based output to a destination. In the former case,
+the port is an input port, in the latter case, an output port.
+
+@c TODO add xref to equal? & eq?
+ Although ports are not considered immutable, none of the operations
+on ports described in this section constitute mutation. Ports are
+@code{equal?} iff @code{eq?}. The port type is encapsulated.
+
+ An auxiliary data type used to signal the end of file was reached is
+eof. The eof type consists of a single immutable value, having
+an output only external representation (so that it can never be the
+normal result of a call to read). The eof type is encapsulated.
+
+SOURCE NOTE: the eof type is not in the Kernel report, it is used in
+klisp and was taken from Scheme.
+
+@deffn Applicative port? (port? . objects)
+ The primitive type predicate for type port. @code{port?}
+returns true iff all the objects in @code{objects} are of type port.
+@end deffn
+
+@deffn Applicative input-port? (input-port? . objects)
+@deffnx Applicative output-port? (output-port? . objects)
+ Applicative @code{input-port?} is a predicate that returns true
+unless one or more of its arguments is not an input port. Applicative
+output-port? is a predicate that returns true unless one or more of
+its arguments is not an output port.
+
+ Every port must be admitted by at least one of these two predicates.
+@end deffn
+
+@deffn with-input-from-file (with-input-from-file string combiner)
+@deffnx with-output-to-file (with-output-to-file string combiner)
+@c add xref get-current-input-port/get-current-output-port
+ These two applicatives open the file named in @code{string} for
+input or output, an invoke the binder of the input-port & output-port
+keyed dynamic variables respectively with the opened port & the passed
+@code{combiner} (this means that the combiner is called in a fresh, empty
+dynamic environment). When/if the binder normally returns, the port is closed.
+The result of the applicatives @code{with-input-from-file} and
+@code{with-output-from-file} is inert.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. In the new scheme report there's also a third
+error-port variable. It is very likely that that will be added to the
+klisp implementation in the near future.
+@end deffn
+
+@deffn get-current-input-port (get-current-input-port)
+@deffnx get-current-output-port (get-current-output-port)
+ These are the accessors for the input-port and output-port keyed
+dynamic variables repectively.
+@c add xref to with-input-from-file, etc
+@c add xref and text for these dynamic vars
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. In the new scheme report there's also a third
+error-port variable. It is very likely that that will be added to the
+klisp implementation in the near future.
+@end deffn
+
+@deffn Applicative open-input-file (open-input-file string)
+ @code{string} should be the name/path for an existing file.
+
+ Applicative @code{open-input-file} creates and returns an input port
+associated with the file represented with @code{string}. If the file
+can't be opened (e.g. because it doesn't exists, or there's a
+permissions problem), an error is signaled.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+@end deffn
+
+@deffn Applicative open-output-file (open-output-file string)
+ @code{string} should be the name/path for an existing file.
+
+ Applicative @code{open-output-file} creates and returns an output
+port associated with the file represented with @code{string}. If the
+file can't be opened (e.g. if there's a permissions problem), an error
+is signaled.
+
+ In klisp, for now, applicative @code{open-output-file} truncates the
+file if it already exists, but that could change later (i.e. like in
+scheme the behaviour should be considered unspecified).
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+@end deffn
+
+@deffn close-input-file (close-input-file input-port)
+@deffnx close-output-file (close-output-file output-port)
+ These applicatives close the port argument, so that no more
+input/output may be performed on them, and the resources can be
+freed. If the port was already closed these applicatives have no
+effect.
+
+ The result returned by applicatives @code{close-input-file} and
+@code{close-output-file} is inert.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing. There's probably a name error here. These should
+probably be called close-input-port & close-output-port.
+@end deffn
+
+@deffn Applicative read (read [input-port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{input-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{read} reads & returns the next parseable object
+from the given port, or the eof object if no objects remain. If
+@code{read} finds and unparseable object in the port, an error is
+signaled. In that case, the remaining position in the port is
+unspecified.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+@end deffn
+
+@deffn write (write object [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{output-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+@c TODO add xref to external representation
+ Applicative @code{write} writes an external representation of
+@code{object} to the specified port. This may be an output-only
+representation that can't be read by applicative @code{read} in cases
+where the type of @code{object} doen't have a parseable external
+representation (e.g. combiners and environments). The result returned
+by @code{write} is inert.
+
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+@end deffn
+
+@deffn Applicative call-with-input-file (call-with-input-file string combiner)
+@deffnx Applicative call-with-output-file (call-with-output-file string combiner)
+ These applicatives open file named in @code{string} and call their
+@code{combiner} argument in a fresh empty environment passing it as a
+sole operand the opened port. When/if the combiner normally returns a
+value the port is closed and that value is returned as the result of
+the applicative.
+
+ SOURCE NOTE: this is enumerated in the Kernel report but the text is
+still missing.
+@end deffn
+
+@deffn Applicative load (load string)
+@c TODO add xref, open/input, read
+ Applicative @code{load} opens for input a file named @code{string};
+reads objects from the file until the end of the file is reached;
+evaluates those objects consecutively in the created environment. The
+result from applicative @code{load} is inert.
+
+ SOURCE NOTE: load is enumerated in the Kernel report, but the
+description is not there yet. This seems like a sane way to define
+it, taking the description of @code{get-module} that there is in the
+report. The one detail that I think is still open, is whether to
+return @code{#inert} (as is the case with klisp currently) or rather
+return the value of the last evaluation.
+@end deffn
+
+@deffn Applicative get-module (get-module string [environment])
+@c TODO add xref standard-environment, open/input, read
+ Applicative @code{get-module} creates a fresh standard environment;
+opens for input a file named @code{string}; reads objects from the
+file until the end of the file is reached; evaluates those objects
+consecutively in the created environment; and, lastly, returns the
+created environment. If the optional argument @code{environment} is
+specified, the freshly created standard environment is augmented,
+prior to evaluating read expressions, by binding symbol
+@code{module-parameters} to the @code{environment} argument.
+@end deffn
+
+@deffn Applicative eof-object? (eof-object? . objects)
+ The primitive type predicate for type eof. @code{eof-object?}
+returns true iff all the objects in @code{objects} are of type eof.
+
+ SOURCE NOTE: This is not in the report, the idea is from Scheme.
+The @code{eof-object?} name is also from scheme, but this will
+probably be changed to just @code{eof?}, for consistency with the other
+primitive type predicates.
+@end deffn
+
+@deffn read-char (read-char [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{input-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{read-char} reads and returns a character (not
+an external representation of a character) from the specified port, or
+an eof if the end of file was reached.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
+
+@deffn peek-char (peek-char [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{input-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{peek-char} reads and returns a character (not
+an external representation of a character) from the specified port, or
+an eof if the end of file was reached. The position of the port
+remains unchanged so that new call to @code{peek-char} or
+@code{read-char} on the same port return the same character.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
+
+@deffn char-ready? (char-ready? [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{input-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Predicate @code{char-ready?} checks to see if a character is
+available in the specified port. If it returns true, then a
+@code{read-char} or @code{peek-char} on that port is guaranteed not to
+block/hang. For now in klisp this is hardcoded to @code{#t} because
+the code to do this is non-portable.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
+
+@deffn write-char (write-char char [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{output-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{write-char} writes the @code{char} character (not
+an external representation of the character) to the specified port.
+The result returned by @code{write-char} is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
+
+@deffn newline (newline [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{output-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{newline} writes a newline to the specified port.
+The result returned by @code{newline} is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
+
+@deffn display (display object [port])
+ If the @code{port} optional argument is not specified, then the
+value of the @code{output-port} keyed dynamic variable is used. If the
+port is closed, an error is signaled.
+
+ Applicative @code{display} behaves like @code{write} except that
+strings are not enclosed in double quotes and no character is escaped
+within those strings and character objects are output as if by
+@code{write-char} instead of @code{read}. The result returned by
+@code{display} is inert.
+
+ SOURCE NOTE: this is missing from Kernel, it is taken from Scheme.
+@end deffn
diff --git a/manual/src/promises.texi b/manual/src/promises.texi
@@ -0,0 +1,89 @@
+@c -*-texinfo-*-
+@setfilename ../src/promises
+
+@node Promises, Keyed Variables, Encapsulations, Top
+@comment node-name, next, previous, up
+
+@chapter Promises
+@cindex promises
+
+@c TODO xref to $lazy, memoize, force
+A promise is an object that represents the potential to determine a
+value. The value may be the result of an arbitrary computation that
+will not be performed until the value must be determined (constructor
+@code{$lazy}); or, in advanced usage, the value may be determined
+before the promise is constructed (constructor @code{memoize}).
+
+ The value determined by a promise is obtained by forcing it
+(applicative @code{force}). A given promise cannot determine
+different values on different occasions that it is forced. Also, if a
+promise determines its value by computation, and that computation has
+already been completed, forcing the promise again will produce the
+previously determined result without re-initiating the computation to
+determine it.
+
+ The Kernel data type promise is encapsulated.
+
+@c TODO add xref to eq? and equal?
+ The general rules for predicate @code{eq?} only require it to
+distinguish promises if they can exhibit different behavior; the
+resulting leeway for variation between implementations is similar, in
+both cause and effect, to that for @code{eq?}-ness of operatives. For
+example, if two promises, constructed on different occasions, would
+perform the same computation to determine their values, and that
+computation has no side-effects and must always return the same value,
+the promises may or may not be @code{eq?}. Two promises are
+@code{equal?} iff they are @code{eq?}.
+
+@deffn Applicative promise? (promise? . objects)
+ The primitive type predicate for type promise. @code{promise?}
+returns true iff all the objects in @code{objects} are of type
+promise.
+@end deffn
+
+@deffn Applicative force (force object)
+ If @code{object} is a promise, applicative @code{force} returns the
+value determined by promise; otherwise, it returns @code{object}.
+
+ The means used to force a promise depend on how the promise was
+constructed. The description of each promise constructor specifies
+how to force promises constructed by that constructor.
+@end deffn
+
+@deffn Operative $lazy ($lazy expression)
+ Operative @code{$lazy} constructs and returns a new object of type
+promise, representing potential evaluation of expression in the
+dynamic environment from which @code{$lazy} was called.
+
+ When the promise is forced, if a value has not previously been
+determined for it, @code{expression} is evaluated in the dynamic
+environment of the constructing call to @code{$lazy}. If, when the
+evaluation returns a result, a value is found to have been determined
+for the promise during the evaluation, the result is discarded in
+favor of the previously determined value; otherwise, the result is
+forced, and the value returned by that forcing becomes the value
+determined by the promise.
+
+@c TODO add xref to tail context
+ Forcing an undetermined lazy promise (i.e., a promise constructed by
+$lazy for which no value has yet been determined) may cause a
+sequential series of evaluations, each of which returns a promise that
+is forced and thus initiates the next evaluation in the series. The
+implementation must support series of this kind with unbounded length
+(i.e., unbounded number of sequential evaluations).
+
+@c TODO add xref to eq?
+ Note that forcing concerns the value determined by a given promise,
+not the result of evaluating a given expression in a given
+environment. Distinct promises (judged by @code{eq?} represent
+different occasions of evaluation; so, even if they do represent
+evaluation of the same expression in the same environment, forcing one
+does not necessarily determine the value for the other, and actual
+evaluation will take place the first time each of them is forced.
+@end deffn
+
+@deffn Applicative memoize (memoize object)
+ Applicative @code{memoize} constructs and returns a new object of
+type promise, representing memoization of @code{object}. Whenever the
+promise is forced, it determines @code{object}.
+@end deffn
diff --git a/manual/src/strings.texi b/manual/src/strings.texi
@@ -0,0 +1,8 @@
+@c -*-texinfo-*-
+@setfilename ../src/strings
+
+@node Strings, Characters, Numbers, Top
+@comment node-name, next, previous, up
+
+@chapter Strings
+@cindex strings
diff --git a/manual/src/symbols.texi b/manual/src/symbols.texi
@@ -0,0 +1,41 @@
+@c -*-texinfo-*-
+@setfilename ../src/symbols
+
+@node Symbols, Control, Equivalence, Top
+@comment node-name, next, previous, up
+
+@chapter Symbols
+@cindex symbols
+@c TODO add xref to eq?, identifiers, etc
+ Two symbols are eq? iff they have the same external
+representation. Symbols are immutable, and the symbol type is
+encapsulated. The external representations of symbols are usually
+identifiers. However, symbols with other external representations may
+@c TODO add xref to string->symbol
+be created.
+
+@deffn Applicative symbol? (symbol? . objects)
+ The primitive type predicate for type symbol. @code{symbol?}
+returns true iff all the objects in @code{objects} are of type symbol.
+@end deffn
+
+@deffn Applicative symbol->string (symbol->string symbol)
+ Applicative @code{symbol->string} returns the name of @code{symbol}
+as a string. The string returned is immutable.
+@end deffn
+
+@deffn Applicative string->symbol (string->symbol string)
+ Applicative @code{string->symbol} returns the symbol with name
+@code{string}. The symbol is always interned, which means, that it is
+always the case that:
+@example
+(eq? <symbol> (string->symbol (symbol->string <symbol>)))
+ @result{} #t
+@end example
+@c TODO add xrefs for external representation
+ @code{string->symbol} can create symbols whose external
+representation aren't identifiers. Right now klisp uses an output-only
+representation, but in the near future it will probably include some
+kind of escaping mechanism to allow arbitrary symbols to have readable
+external representations as in R7RS Scheme.
+@end deffn
diff --git a/src/Makefile b/src/Makefile
@@ -1,12 +1,30 @@
+# makefile for building klisp
+# SOURCE NOTE: this is mostly from lua
+
+# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
+
+# Your platform. See PLATS for possible values.
+PLAT= none
+
CC=gcc
+# TEMP for now put in debug symbols
+# TEMP for now only 32 bit binaries (see kobject.h)
CFLAGS=-O2 -g -std=c99 -Wall -m32 $(MYCFLAGS)
-RM=rm -f
-LIBS=-lm $(MYLIBS)
+AR= ar rcu
+RANLIB= ranlib
+RM= rm -f
+LIBS= -lm $(MYLIBS)
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
+# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+# TEMP only these two for now
+PLATS= generic mingw posix
+
+KRN_A= libklisp.a
CORE_O= kobject.o ktoken.o kpair.o kstring.o ksymbol.o kread.o \
kwrite.o kstate.o kmem.o kerror.o kauxlib.o kenvironment.o \
kcontinuation.o koperative.o kapplicative.o keval.o krepl.o \
@@ -17,144 +35,217 @@ CORE_O= kobject.o ktoken.o kpair.o kstring.o ksymbol.o kread.o \
kgenv_mut.o kgcombiners.o kgcontinuations.o kgencapsulations.o \
kgpromises.o kgkd_vars.o kgks_vars.o kgports.o kgchars.o kgnumbers.o \
kgstrings.o
+# TEMP: in klisp there is no distinction between core & lib
+LIB_O=
KRN_T= klisp
KRN_O= klisp.o
-ALL_T= $(KRN_T)
-ALL_O= $(CORE_O) $(KRN_O)
+ALL_O= $(CORE_O) $(LIB_O) $(KRN_O)
+ALL_T= $(KRN_A) $(KRN_T)
+ALL_A= $(KRN_A)
-default:
- $(MAKE) all MYCFLAGS= MYLIBS=""
+default: $(PLAT)
all: $(ALL_T)
o: $(ALL_O)
-$(KRN_T): $(ALL_O)
- $(CC) $(CFLAGS) -o $@ $(MYLDFLAGS) $(ALL_O) $(LIBS)
+a: $(ALL_A)
+
+$(KRN_A): $(CORE_O) $(LIB_O)
+ $(AR) $@ $?
+ $(RANLIB) $@
+
+$(KRN_T): $(KRN_O) $(KRN_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(KRN_O) $(KRN_A) $(LIBS)
clean:
$(RM) $(ALL_T) $(ALL_O)
+depend:
+ @$(CC) $(CFLAGS) -MM k*.c imath.c imrat.c
+
+echo:
+ @echo "PLAT = $(PLAT)"
+ @echo "CC = $(CC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "AR = $(AR)"
+ @echo "RANLIB = $(RANLIB)"
+ @echo "RM = $(RM)"
+ @echo "MYCFLAGS = $(MYCFLAGS)"
+ @echo "MYLDFLAGS = $(MYLDFLAGS)"
+ @echo "MYLIBS = $(MYLIBS)"
+
+# convenience targets for popular platforms
+
+none:
+ @echo "Please choose a platform:"
+ @echo " $(PLATS)"
+
+generic:
+ $(MAKE) all MYCFLAGS=
+
+mingw:
+ $(MAKE) "KRN_A=klisp01.dll" "KRN_T=klisp.exe" \
+ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
+ "MYCFLAGS=-DKLISP_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" klisp.exe
+#lisp_use_posix isn't used right now...
+posix:
+ $(MAKE) all MYCFLAGS=-DKLISP_USE_POSIX
+
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all default o clean
-klisp.o: klisp.c klisp.h kobject.h kread.h kwrite.h klimits.h kstate.h kmem.h \
- kerror.h kauxlib.h koperative.h kenvironment.h kcontinuation.h \
- kapplicative.h koperative.h keval.h krepl.h kground.h
-kobject.o: kobject.c kobject.h klimits.h klispconf.h
-ktoken.o: ktoken.c ktoken.h kobject.h kstate.h kpair.h kstring.h ksymbol.h \
- kerror.h klisp.h kinteger.h krational.h kreal.h kport.h
-kinteger.o: kinteger.c kinteger.h kobject.h kstate.h kmem.h klisp.h imath.h \
- kgc.h
-krational.o: krational.c krational.h kinteger.h kobject.h kstate.h kmem.h \
- klisp.h imrat.h kgc.h
-kreal.o: kreal.c kreal.h krational.h kinteger.h kobject.h kstate.h kmem.h \
- klisp.h imrat.h kgc.h kerror.h kpair.h
-kpair.o: kpair.c kpair.h kobject.h kstate.h kmem.h klisp.h kgc.h
-kstring.o: kstring.c kstring.h kobject.h kstate.h kmem.h klisp.h kgc.h
-ksymbol.o: ksymbol.c ksymbol.h kobject.h kstring.h kstate.h kmem.h \
- klisp.h kgc.h
-kread.o: kread.c kread.h kobject.h ktoken.h kpair.h kstate.h kerror.h klisp.h \
- kport.h ktable.h klispconf.h
-kwrite.o: kwrite.c kwrite.h kobject.h kpair.h kstring.h kstate.h kerror.h \
- klisp.h kport.h kinteger.h krational.h kreal.h ktable.h klispconf.h \
- kenvironment.h
-# XXX: now that all dealloc code is in gc, many of these are unnecessary
-kstate.o: kstate.c kstate.h klisp.h kobject.h kmem.h kstring.h klisp.h \
- kenvironment.h kpair.h keval.h koperative.h kground.h \
- krepl.h kcontinuation.h kapplicative.h kport.h ksymbol.h kport.h \
- kstring.h kinteger.h krational.h kgc.h klimits.h ktable.h klispconf.h \
- kenvironment.h
-kmem.o: kmem.c kmem.h klisp.h kerror.h klisp.h kstate.h kgc.h klispconf.h
-kerror.o: kerror.c kerror.h klisp.h kstate.h klisp.h kmem.h kstring.h kpair.h
-kauxlib.o: kauxlib.c kauxlib.h klisp.h kstate.h klisp.h
-kenvironment.o: kenvironment.c kenvironment.h kpair.h kobject.h kerror.h \
- kmem.h kstate.h klisp.h kgc.h ktable.h klispconf.h kapplicative.h
-kcontinuation.o: kcontinuation.c kcontinuation.h kmem.h kstate.h kobject.h \
- klisp.h kgc.h
-koperative.o: koperative.c koperative.h kmem.h kstate.h kobject.h \
- klisp.h kgc.h
-kapplicative.o: kapplicative.c kapplicative.h kmem.h kstate.h kobject.h \
- klisp.h kgc.h koperative.h
-kencapsulation.o: kencapsulation.c kencapsulation.h kmem.h kstate.h kobject.h \
- klisp.h kpair.h kgc.h
-kpromise.o: kpromise.c kpromise.h kmem.h kstate.h kobject.h \
- klisp.h kpair.h kgc.h
-kport.o: kport.c kport.h kmem.h kstate.h kobject.h klisp.h kerror.h kstring.h \
- kgc.h
-ktable.o: ktable.c ktable.h kobject.h kstate.h kmem.h klisp.h kgc.h \
- kapplicative.h kgeqp.h kstring.h kerror.h
-keval.o: keval.c keval.h kcontinuation.h kenvironment.h kstate.h kobject.h \
- kpair.h kerror.h klisp.h klispconf.h
-krepl.o: krepl.c krepl.h kcontinuation.h kstate.h kobject.h keval.h klisp.h \
- kread.h kwrite.h kenvironment.h ksymbol.h kport.h kpair.h ktable.h
-kground.o: kground.c kground.h kstate.h kobject.h klisp.h kenvironment.h \
- kapplicative.h koperative.h ksymbol.h kerror.h kghelpers.h \
- kgbooleans.h kgeqp.h kgequalp.h kgsymbols.h kgpairs_lists.h \
- kgpair_mut.h kgenvironments.h kgenv_mut.h kgcombiners.h \
- kgcontinuations.h kgencapsulations.h kgpromises.h kgkd_vars.h \
- kgks_vars.h kgports.h kgchars.h kgnumbers.h kgstrings.o \
- klispconf.h krepl.h keval.h ktable.h kstring.h
-kghelpers.o: kghelpers.c kghelpers.h kstate.h kstate.h klisp.h kpair.h \
- kapplicative.h koperative.h kerror.h kobject.h ksymbol.h \
- kcontinuation.h
-kgbooleans.o: kgbooleans.c kgbooleans.c kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h kcontinuation.h ksymbol.h
-kgeqp.o: kgeqp.c kgeqp.c kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h kcontinuation.h kapplicative.h \
- kinteger.h krational.h kreal.h
-kgequalp.o: kgequalp.c kgequalp.c kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h kcontinuation.h kgeqp.h kstring.h
-kgsymbols.o: kgsymbols.c kgsymbols.c kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h kcontinuation.h kstring.h
-kgcontrol.o: kgcontrol.c kgcontrol.c kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h kcontinuation.h kgcombiners.h
-kgpairs_lists.o: kgpairs_lists.c kgpairs_lists.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h kgequalp.h \
- kenvironment.h kgnumbers.h kinteger.h
-kgpair_mut.o: kgpair_mut.c kgpair_mut.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h kgeqp.h \
- kgnumbers.h
-kgenvironments.o: kgenvironments.c kgenvironments.h kghelpers.h kstate.h \
- klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \
- kenvironment.h kgenv_mut.h kgpair_mut.h kgcontrol.h
-kgenv_mut.o: kgenv_mut.c kgenv_mut.h kghelpers.h kstate.h \
- klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \
- kenvironment.h kgcontrol.h
-kgcombiners.o: kgcombiners.c kgenvironments.h kghelpers.h kstate.h \
- klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \
- kenvironment.h kapplicative.h koperative.h kgpair_mut.h kgnumbers.h \
- kgenv_mut.h
-kgcontinuations.o: kgcontinuations.c kgcontinuations.h kghelpers.h kstate.h \
- klisp.h kobject.h kerror.h kpair.h ksymbol.h kcontinuation.h \
- kenvironment.h kapplicative.h koperative.h
-kgencapsulations.o: kgencapsulations.c kgencapsulations.h kghelpers.h \
- kstate.h klisp.h kobject.h kerror.h kapplicative.h koperative.h \
- kencapsulation.h
-kgpromises.o: kgpromises.c kgpromises.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- kpair.h kpromise.h
-kgkd_vars.o: kgkd_vars.c kgkd_vars.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- kpair.h kenvironment.h kgcontinuations.h
-kgks_vars.o: kgks_vars.c kgks_vars.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- kpair.h kenvironment.h
-kgports.o: kgports.c kgports.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- kport.h ksymbol.h kread.h kwrite.h ktoken.h kgcontinuations.h \
- kpair.h kenvironment.h kgcontrol.h kgkd_vars.h
-kgchars.o: kgchars.c kgchars.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h
-kgnumbers.o: kgnumbers.c kgnumbers.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- ksymbol.h kinteger.h krational.h kreal.h kgkd_vars.h
-kgstrings.o: kgstrings.c kgstrings.h kghelpers.h kstate.h klisp.h \
- kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- kstring.h ksymbol.h kgnumbers.h
-imath.o: kobject.h kstate.h kmem.h kerror.h
-imrath.o: kobject.h kstate.h kmem.h kerror.h
-kgc.o: kgc.c kgc.h kobject.h kmem.h kstate.h kport.h imath.h imrat.h \
- ktable.h kstring.h kerror.h kinteger.h krational.h
+kapplicative.o: kapplicative.c kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kapplicative.h koperative.h kgc.h
+kauxlib.o: kauxlib.c klisp.h kobject.h klimits.h klispconf.h kstate.h \
+ ktoken.h kmem.h
+kcontinuation.o: kcontinuation.c kcontinuation.h kobject.h klimits.h \
+ klisp.h klispconf.h kstate.h ktoken.h kmem.h kgc.h
+kencapsulation.o: kencapsulation.c kobject.h klimits.h klisp.h \
+ klispconf.h kmem.h kstate.h ktoken.h kencapsulation.h kpair.h kgc.h
+kenvironment.o: kenvironment.c kenvironment.h kobject.h klimits.h klisp.h \
+ klispconf.h kstate.h ktoken.h kmem.h kpair.h kgc.h ksymbol.h kstring.h \
+ kerror.h ktable.h kapplicative.h koperative.h
+kerror.o: kerror.c klisp.h kobject.h klimits.h klispconf.h kpair.h \
+ kstate.h ktoken.h kmem.h kgc.h kstring.h
+keval.o: keval.c klisp.h kobject.h klimits.h klispconf.h kstate.h \
+ ktoken.h kmem.h kpair.h kgc.h kenvironment.h kcontinuation.h kerror.h
+kgbooleans.o: kgbooleans.c kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kpair.h kgc.h ksymbol.h kstring.h \
+ kcontinuation.h kerror.h kghelpers.h kapplicative.h koperative.h \
+ kenvironment.h
+kgc.o: kgc.c kgc.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kport.h imath.h imrat.h ktable.h kstring.h kerror.h
+kgchars.o: kgchars.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kapplicative.h koperative.h kcontinuation.h kerror.h \
+ kghelpers.h kpair.h kgc.h kenvironment.h ksymbol.h kstring.h kgchars.h
+kgcombiners.o: kgcombiners.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpair.h kgc.h kenvironment.h kcontinuation.h \
+ ksymbol.h kstring.h koperative.h kapplicative.h kerror.h kghelpers.h \
+ kgpair_mut.h kgenv_mut.h kgcontrol.h kgcombiners.h
+kgcontinuations.o: kgcontinuations.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpair.h kgc.h kenvironment.h kcontinuation.h \
+ kapplicative.h koperative.h ksymbol.h kstring.h kerror.h kghelpers.h \
+ kgcontinuations.h kgcontrol.h
+kgcontrol.o: kgcontrol.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kcontinuation.h kerror.h kghelpers.h \
+ kapplicative.h koperative.h kenvironment.h ksymbol.h kstring.h \
+ kgcontrol.h kgcombiners.h
+kgencapsulations.o: kgencapsulations.c kstate.h klimits.h klisp.h \
+ kobject.h klispconf.h ktoken.h kmem.h kencapsulation.h kapplicative.h \
+ koperative.h kerror.h kghelpers.h kpair.h kgc.h kcontinuation.h \
+ kenvironment.h ksymbol.h kstring.h kgencapsulations.h
+kgenv_mut.o: kgenv_mut.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kenvironment.h kcontinuation.h ksymbol.h \
+ kstring.h kerror.h kghelpers.h kapplicative.h koperative.h kgenv_mut.h \
+ kgcontrol.h
+kgenvironments.o: kgenvironments.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpair.h kgc.h kenvironment.h kcontinuation.h \
+ ksymbol.h kstring.h kerror.h kghelpers.h kapplicative.h koperative.h \
+ kgenvironments.h kgenv_mut.h kgpair_mut.h kgcontrol.h
+kgeqp.o: kgeqp.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kcontinuation.h kerror.h kghelpers.h \
+ kapplicative.h koperative.h kenvironment.h ksymbol.h kstring.h kgeqp.h \
+ kinteger.h imath.h krational.h imrat.h
+kgequalp.o: kgequalp.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kstring.h kcontinuation.h kerror.h \
+ kghelpers.h kapplicative.h koperative.h kenvironment.h ksymbol.h kgeqp.h \
+ kinteger.h imath.h krational.h imrat.h kgequalp.h
+kghelpers.o: kghelpers.c kghelpers.h kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kerror.h kpair.h kgc.h kapplicative.h \
+ koperative.h kcontinuation.h kenvironment.h ksymbol.h kstring.h
+kgkd_vars.o: kgkd_vars.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kcontinuation.h koperative.h \
+ kapplicative.h kenvironment.h kerror.h kghelpers.h ksymbol.h kstring.h \
+ kgcontinuations.h kgkd_vars.h
+kgks_vars.o: kgks_vars.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kpair.h kgc.h kcontinuation.h koperative.h \
+ kapplicative.h kenvironment.h kerror.h kghelpers.h ksymbol.h kstring.h \
+ kgks_vars.h
+kgnumbers.o: kgnumbers.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kapplicative.h koperative.h kcontinuation.h kerror.h \
+ ksymbol.h kstring.h kinteger.h imath.h krational.h imrat.h kreal.h \
+ kghelpers.h kpair.h kgc.h kenvironment.h kgnumbers.h kgkd_vars.h
+kgpair_mut.o: kgpair_mut.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpair.h kgc.h kcontinuation.h ksymbol.h \
+ kstring.h kerror.h kghelpers.h kapplicative.h koperative.h \
+ kenvironment.h kgpair_mut.h kgeqp.h kinteger.h imath.h krational.h \
+ imrat.h kgnumbers.h
+kgpairs_lists.o: kgpairs_lists.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpair.h kgc.h kstring.h kcontinuation.h \
+ kenvironment.h ksymbol.h kerror.h kghelpers.h kapplicative.h \
+ koperative.h kgequalp.h kgpairs_lists.h kgnumbers.h kinteger.h imath.h
+kgports.o: kgports.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kport.h kenvironment.h kapplicative.h koperative.h \
+ kcontinuation.h kpair.h kgc.h kerror.h ksymbol.h kstring.h kread.h \
+ kwrite.h kghelpers.h kgports.h kgcontinuations.h kgcontrol.h kgkd_vars.h
+kgpromises.o: kgpromises.c kstate.h klimits.h klisp.h kobject.h \
+ klispconf.h ktoken.h kmem.h kpromise.h kpair.h kgc.h kapplicative.h \
+ koperative.h kcontinuation.h kerror.h kghelpers.h kenvironment.h \
+ ksymbol.h kstring.h kgpromises.h
+kground.o: kground.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kground.h kghelpers.h kerror.h kpair.h kgc.h \
+ kapplicative.h koperative.h kcontinuation.h kenvironment.h ksymbol.h \
+ kstring.h kgbooleans.h kgeqp.h kinteger.h imath.h krational.h imrat.h \
+ kgequalp.h kgsymbols.h kgcontrol.h kgpairs_lists.h kgpair_mut.h \
+ kgenvironments.h kgenv_mut.h kgcombiners.h kgcontinuations.h \
+ kgencapsulations.h kgpromises.h kgkd_vars.h kgks_vars.h kgnumbers.h \
+ kgstrings.h kgchars.h kgports.h ktable.h keval.h krepl.h
+kgstrings.o: kgstrings.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kapplicative.h koperative.h kcontinuation.h kerror.h \
+ ksymbol.h kstring.h kghelpers.h kpair.h kgc.h kenvironment.h kgchars.h \
+ kgstrings.h kgnumbers.h
+kgsymbols.o: kgsymbols.c kstate.h klimits.h klisp.h kobject.h klispconf.h \
+ ktoken.h kmem.h kcontinuation.h kpair.h kgc.h kstring.h ksymbol.h \
+ kerror.h kghelpers.h kapplicative.h koperative.h kenvironment.h \
+ kgsymbols.h
+kinteger.o: kinteger.c kinteger.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h imath.h kgc.h
+klisp.o: klisp.c klimits.h klisp.h kobject.h klispconf.h kstate.h \
+ ktoken.h kmem.h kauxlib.h
+kmem.o: kmem.c klisp.h kobject.h klimits.h klispconf.h kstate.h ktoken.h \
+ kmem.h kerror.h kgc.h
+kobject.o: kobject.c kobject.h klimits.h klisp.h klispconf.h
+koperative.o: koperative.c koperative.h kobject.h klimits.h klisp.h \
+ klispconf.h kstate.h ktoken.h kmem.h kgc.h
+kpair.o: kpair.c kpair.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kgc.h
+kport.o: kport.c kport.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kerror.h kstring.h kgc.h
+kpromise.o: kpromise.c kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kpromise.h kpair.h kgc.h
+krational.o: krational.c krational.h kobject.h klimits.h klisp.h \
+ klispconf.h kstate.h ktoken.h kmem.h kinteger.h imath.h imrat.h kgc.h
+kread.o: kread.c kread.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kpair.h kgc.h kerror.h ktable.h kport.h
+kreal.o: kreal.c kreal.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kinteger.h imath.h krational.h imrat.h kgc.h kpair.h \
+ kerror.h
+krepl.o: krepl.c klisp.h kobject.h klimits.h klispconf.h kstate.h \
+ ktoken.h kmem.h kcontinuation.h kenvironment.h kerror.h kread.h kwrite.h \
+ kstring.h krepl.h ksymbol.h kport.h kpair.h kgc.h ktable.h
+kstate.o: kstate.c klisp.h kobject.h klimits.h klispconf.h kstate.h \
+ ktoken.h kmem.h kstring.h kpair.h kgc.h keval.h koperative.h \
+ kapplicative.h kcontinuation.h kenvironment.h kground.h krepl.h \
+ ksymbol.h kport.h ktable.h kgpairs_lists.h kghelpers.h kerror.h
+kstring.o: kstring.c kstring.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kgc.h
+ksymbol.o: ksymbol.c ksymbol.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kstring.h kgc.h
+ktable.o: ktable.c klisp.h kobject.h klimits.h klispconf.h kgc.h kstate.h \
+ ktoken.h kmem.h ktable.h kapplicative.h koperative.h kgeqp.h kinteger.h \
+ imath.h krational.h imrat.h kghelpers.h kerror.h kpair.h kcontinuation.h \
+ kenvironment.h ksymbol.h kstring.h
+ktoken.o: ktoken.c ktoken.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h kmem.h kinteger.h imath.h krational.h imrat.h kreal.h kpair.h \
+ kgc.h kstring.h ksymbol.h kerror.h kport.h
+kwrite.o: kwrite.c kwrite.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kinteger.h imath.h krational.h imrat.h kreal.h \
+ kpair.h kgc.h kstring.h ksymbol.h kerror.h ktable.h kport.h \
+ kenvironment.h
+imath.o: imath.c imath.h kobject.h klimits.h klisp.h klispconf.h kstate.h \
+ ktoken.h kmem.h kerror.h
+imrat.o: imrat.c imrat.h imath.h kobject.h klimits.h klisp.h klispconf.h \
+ kstate.h ktoken.h kmem.h kerror.h
diff --git a/src/kgbooleans.c b/src/kgbooleans.c
@@ -168,3 +168,24 @@ void Sandp_Sorp(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
/* 6.1.5 $or? */
/* uses Sandp_Sorp */
+
+/* init ground */
+void kinit_booleans_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.1.1 boolean? */
+ add_applicative(K, ground_env, "boolean?", typep, 2, symbol,
+ i2tv(K_TBOOLEAN));
+ /* 6.1.1 not? */
+ add_applicative(K, ground_env, "not?", notp, 0);
+ /* 6.1.2 and? */
+ add_applicative(K, ground_env, "and?", andp, 0);
+ /* 6.1.3 or? */
+ add_applicative(K, ground_env, "or?", orp, 0);
+ /* 6.1.4 $and? */
+ add_operative(K, ground_env, "$and?", Sandp_Sorp, 2, symbol, KFALSE);
+ /* 6.1.5 $or? */
+ add_operative(K, ground_env, "$or?", Sandp_Sorp, 2, symbol, KTRUE);
+}
diff --git a/src/kgbooleans.h b/src/kgbooleans.h
@@ -43,4 +43,7 @@ void Sandp_Sorp(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
/* Helper */
bool kbooleanp(TValue obj);
+/* init ground */
+void kinit_booleans_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgchars.c b/src/kgchars.c
@@ -127,3 +127,66 @@ bool kchar_ci_gtp(TValue ch1, TValue ch2)
bool kchar_ci_gep(TValue ch1, TValue ch2)
{ return tolower(chvalue(ch1)) >= tolower(chvalue(ch2)); }
+/* init ground */
+void kinit_chars_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /*
+ ** This section is still missing from the report. The bindings here are
+ ** taken from r5rs scheme and should not be considered standard. They are
+ ** provided in the meantime to allow programs to use character features
+ ** (ASCII only).
+ */
+
+ /* 14.1.1? char? */
+ add_applicative(K, ground_env, "char?", typep, 2, symbol,
+ i2tv(K_TCHAR));
+ /* 14.1.2? char-alphabetic?, char-numeric?, char-whitespace? */
+ /* unlike in r5rs these take an arbitrary number of chars
+ (even cyclical list) */
+ add_applicative(K, ground_env, "char-alphabetic?", ftyped_predp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_alphabeticp));
+ add_applicative(K, ground_env, "char-numeric?", ftyped_predp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_numericp));
+ add_applicative(K, ground_env, "char-whitespace?", ftyped_predp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_whitespacep));
+ /* 14.1.3? char-upper-case?, char-lower-case? */
+ /* unlike in r5rs these take an arbitrary number of chars
+ (even cyclical list) */
+ add_applicative(K, ground_env, "char-upper-case?", ftyped_predp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_upper_casep));
+ add_applicative(K, ground_env, "char-lower-case?", ftyped_predp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_lower_casep));
+ /* 14.1.4? char->integer, integer->char */
+ add_applicative(K, ground_env, "char->integer", kchar_to_integer, 0);
+ add_applicative(K, ground_env, "integer->char", kinteger_to_char, 0);
+ /* 14.1.4? char-upcase, char-downcase */
+ add_applicative(K, ground_env, "char-upcase", kchar_upcase, 0);
+ add_applicative(K, ground_env, "char-downcase", kchar_downcase, 0);
+ /* 14.2.1? char=? */
+ add_applicative(K, ground_env, "char=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_eqp));
+ /* 14.2.2? char<?, char<=?, char>?, char>=? */
+ add_applicative(K, ground_env, "char<?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ltp));
+ add_applicative(K, ground_env, "char<=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_lep));
+ add_applicative(K, ground_env, "char>?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_gtp));
+ add_applicative(K, ground_env, "char>=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_gep));
+ /* 14.2.3? char-ci=? */
+ add_applicative(K, ground_env, "char-ci=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ci_eqp));
+ /* 14.2.4? char-ci<?, char-ci<=?, char-ci>?, char-ci>=? */
+ add_applicative(K, ground_env, "char-ci<?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ci_ltp));
+ add_applicative(K, ground_env, "char-ci<=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ci_lep));
+ add_applicative(K, ground_env, "char-ci>?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ci_gtp));
+ add_applicative(K, ground_env, "char-ci>=?", ftyped_bpredp, 3,
+ symbol, p2tv(kcharp), p2tv(kchar_ci_gep));
+}
diff --git a/src/kgchars.h b/src/kgchars.h
@@ -76,4 +76,7 @@ bool kchar_ci_lep(TValue ch1, TValue ch2);
bool kchar_ci_gtp(TValue ch1, TValue ch2);
bool kchar_ci_gep(TValue ch1, TValue ch2);
+/* init ground */
+void kinit_chars_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgcombiners.c b/src/kgcombiners.c
@@ -601,3 +601,33 @@ void map(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
/* Helper for combiner? */
bool kcombinerp(TValue obj) { return ttiscombiner(obj); }
+
+/* init ground */
+void kinit_combiners_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.10.1 operative? */
+ add_applicative(K, ground_env, "operative?", typep, 2, symbol,
+ i2tv(K_TOPERATIVE));
+ /* 4.10.2 applicative? */
+ add_applicative(K, ground_env, "applicative?", typep, 2, symbol,
+ i2tv(K_TAPPLICATIVE));
+ /* 4.10.3 $vau */
+ /* 5.3.1 $vau */
+ add_operative(K, ground_env, "$vau", Svau, 0);
+ /* 4.10.4 wrap */
+ add_applicative(K, ground_env, "wrap", wrap, 0);
+ /* 4.10.5 unwrap */
+ add_applicative(K, ground_env, "unwrap", unwrap, 0);
+ /* 5.3.2 $lambda */
+ add_operative(K, ground_env, "$lambda", Slambda, 0);
+ /* 5.5.1 apply */
+ add_applicative(K, ground_env, "apply", apply, 0);
+ /* 5.9.1 map */
+ add_applicative(K, ground_env, "map", map, 0);
+ /* 6.2.1 combiner? */
+ add_applicative(K, ground_env, "combiner?", ftypep, 2, symbol,
+ p2tv(kcombinerp));
+}
diff --git a/src/kgcombiners.h b/src/kgcombiners.h
@@ -84,4 +84,7 @@ void do_map_encycle(klisp_State *K, TValue *xparams, TValue obj);
void do_map(klisp_State *K, TValue *xparams, TValue obj);
void do_map_cycle(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_combiners_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgcontinuations.c b/src/kgcontinuations.c
@@ -24,7 +24,6 @@
#include "kgcontinuations.h"
#include "kgcontrol.h" /* for seq helpers in $let/cc */
-
/* 7.1.1 continuation? */
/* uses typep */
@@ -321,3 +320,43 @@ void kgexit(klisp_State *K, TValue *xparams, TValue ptree,
/* should be probably handled in kcall_cont() */
kcall_cont(K, K->root_cont, KINERT);
}
+
+/* init ground */
+void kinit_continuations_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 7.1.1 continuation? */
+ add_applicative(K, ground_env, "continuation?", typep, 2, symbol,
+ i2tv(K_TCONTINUATION));
+ /* 7.2.2 call/cc */
+ add_applicative(K, ground_env, "call/cc", call_cc, 0);
+ /* 7.2.3 extend-continuation */
+ add_applicative(K, ground_env, "extend-continuation", extend_continuation,
+ 0);
+ /* 7.2.4 guard-continuation */
+ add_applicative(K, ground_env, "guard-continuation", guard_continuation,
+ 0);
+ /* 7.2.5 continuation->applicative */
+ add_applicative(K, ground_env, "continuation->applicative",
+ continuation_applicative, 0);
+ /* 7.2.6 root-continuation */
+ add_value(K, ground_env, "root-continuation",
+ K->root_cont);
+ /* 7.2.7 error-continuation */
+ add_value(K, ground_env, "error-continuation",
+ K->root_cont);
+ /* 7.3.1 apply-continuation */
+ add_applicative(K, ground_env, "apply-continuation", apply_continuation,
+ 0);
+ /* 7.3.2 $let/cc */
+ add_operative(K, ground_env, "$let/cc", Slet_cc,
+ 0);
+ /* 7.3.3 guard-dynamic-extent */
+ add_applicative(K, ground_env, "guard-dynamic-extent",
+ guard_dynamic_extent, 0);
+ /* 7.3.4 exit */
+ add_applicative(K, ground_env, "exit", kgexit,
+ 0);
+}
diff --git a/src/kgcontinuations.h b/src/kgcontinuations.h
@@ -64,4 +64,7 @@ void kgexit(klisp_State *K, TValue *xparams, TValue ptree,
void do_extended_cont(klisp_State *K, TValue *xparams, TValue obj);
void do_pass_value(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_continuations_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgcontrol.c b/src/kgcontrol.c
@@ -366,3 +366,22 @@ void for_each(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
/* this will be a nop */
kapply_cc(K, KINERT);
}
+
+/* init ground */
+void kinit_control_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.5.1 inert? */
+ add_applicative(K, ground_env, "inert?", typep, 2, symbol,
+ i2tv(K_TINERT));
+ /* 4.5.2 $if */
+ add_operative(K, ground_env, "$if", Sif, 0);
+ /* 5.1.1 $sequence */
+ add_operative(K, ground_env, "$sequence", Ssequence, 0);
+ /* 5.6.1 $cond */
+ add_operative(K, ground_env, "$cond", Scond, 0);
+ /* 6.9.1 for-each */
+ add_applicative(K, ground_env, "for-each", for_each, 0);
+}
diff --git a/src/kgcontrol.h b/src/kgcontrol.h
@@ -44,4 +44,7 @@ void do_cond(klisp_State *K, TValue *xparams, TValue obj);
void do_select_clause(klisp_State *K, TValue *xparams, TValue obj);
void do_for_each(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_control_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgencapsulations.c b/src/kgencapsulations.c
@@ -111,3 +111,14 @@ void make_encapsulation_type(klisp_State *K, TValue *xparams, TValue ptree,
krooted_tvs_pop(K);
kapply_cc(K, ls);
}
+
+/* init ground */
+void kinit_encapsulations_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 8.1.1 make-encapsulation-type */
+ add_applicative(K, ground_env, "make-encapsulation-type",
+ make_encapsulation_type, 0);
+}
diff --git a/src/kgencapsulations.h b/src/kgencapsulations.h
@@ -22,4 +22,7 @@
void make_encapsulation_type(klisp_State *K, TValue *xparams, TValue ptree,
TValue denv);
+/* init ground */
+void kinit_encapsulations_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgenv_mut.c b/src/kgenv_mut.c
@@ -287,3 +287,19 @@ void SimportB(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
krooted_tvs_pop(K);
ktail_eval(K, env_expr, denv);
}
+
+/* init ground */
+void kinit_env_mut_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.9.1 $define! */
+ add_operative(K, ground_env, "$define!", SdefineB, 1, symbol);
+ /* 6.8.1 $set! */
+ add_operative(K, ground_env, "$set!", SsetB, 1, symbol);
+ /* 6.8.2 $provide! */
+ add_operative(K, ground_env, "$provide!", SprovideB, 1, symbol);
+ /* 6.8.3 $import! */
+ add_operative(K, ground_env, "$import!", SimportB, 1, symbol);
+}
diff --git a/src/kgenv_mut.h b/src/kgenv_mut.h
@@ -250,4 +250,7 @@ void SprovideB(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
/* 6.8.3 $import! */
void SimportB(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
+/* init ground */
+void kinit_env_mut_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgenvironments.c b/src/kgenvironments.c
@@ -625,3 +625,46 @@ void Sbindings_to_environment(klisp_State *K, TValue *xparams, TValue ptree,
ktail_eval(K, expr, denv);
}
+
+/* init ground */
+void kinit_environments_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.8.1 environment? */
+ add_applicative(K, ground_env, "environment?", typep, 2, symbol,
+ i2tv(K_TENVIRONMENT));
+ /* 4.8.2 ignore? */
+ add_applicative(K, ground_env, "ignore?", typep, 2, symbol,
+ i2tv(K_TIGNORE));
+ /* 4.8.3 eval */
+ add_applicative(K, ground_env, "eval", eval, 0);
+ /* 4.8.4 make-environment */
+ add_applicative(K, ground_env, "make-environment", make_environment, 0);
+ /* 5.10.1 $let */
+ add_operative(K, ground_env, "$let", Slet, 1, symbol);
+ /* 6.7.1 $binds? */
+ add_operative(K, ground_env, "$binds?", Sbindsp, 0);
+ /* 6.7.2 get-current-environment */
+ add_applicative(K, ground_env, "get-current-environment",
+ get_current_environment, 0);
+ /* 6.7.3 make-kernel-standard-environment */
+ add_applicative(K, ground_env, "make-kernel-standard-environment",
+ make_kernel_standard_environment, 0);
+ /* 6.7.4 $let* */
+ add_operative(K, ground_env, "$let*", SletS, 1, symbol);
+ /* 6.7.5 $letrec */
+ add_operative(K, ground_env, "$letrec", Sletrec, 1, symbol);
+ /* 6.7.6 $letrec* */
+ add_operative(K, ground_env, "$letrec*", SletrecS, 1, symbol);
+ /* 6.7.7 $let-redirect */
+ add_operative(K, ground_env, "$let-redirect", Slet_redirect, 1, symbol);
+ /* 6.7.8 $let-safe */
+ add_operative(K, ground_env, "$let-safe", Slet_safe, 1, symbol);
+ /* 6.7.9 $remote-eval */
+ add_operative(K, ground_env, "$remote-eval", Sremote_eval, 0);
+ /* 6.7.10 $bindings->environment */
+ add_operative(K, ground_env, "$bindings->environment",
+ Sbindings_to_environment, 1, symbol);
+}
diff --git a/src/kgenvironments.h b/src/kgenvironments.h
@@ -85,4 +85,7 @@ void Sbindings_to_environment(klisp_State *K, TValue *xparams, TValue ptree,
void do_let(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_environments_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgeqp.c b/src/kgeqp.c
@@ -48,3 +48,13 @@ void eqp(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
kapply_cc(K, res);
}
+
+/* init ground */
+void kinit_eqp_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+ /* 4.2.1 eq? */
+ /* 6.5.1 eq? */
+ add_applicative(K, ground_env, "eq?", eqp, 0);
+}
diff --git a/src/kgeqp.h b/src/kgeqp.h
@@ -59,4 +59,7 @@ inline bool eq2p(klisp_State *K, TValue obj1, TValue obj2)
return res;
}
+/* init ground */
+void kinit_eqp_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgequalp.c b/src/kgequalp.c
@@ -12,7 +12,6 @@
#include "kstate.h"
#include "kobject.h"
-#include "kground.h"
#include "kpair.h"
#include "kstring.h" /* for kstring_equalp */
#include "kcontinuation.h"
@@ -212,3 +211,14 @@ bool equal2p(klisp_State *K, TValue obj1, TValue obj2)
return result;
}
+
+
+/* init ground */
+void kinit_equalp_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+ /* 4.3.1 equal? */
+ /* 6.6.1 equal? */
+ add_applicative(K, ground_env, "equal?", equalp, 0);
+}
diff --git a/src/kgequalp.h b/src/kgequalp.h
@@ -26,4 +26,7 @@ void equalp(klisp_State *K, TValue *xparas, TValue ptree, TValue denv);
/* compare two objects and check to see if they are "equal?". */
bool equal2p(klisp_State *K, TValue obj1, TValue obj2);
+/* init ground */
+void kinit_equalp_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kghelpers.h b/src/kghelpers.h
@@ -21,6 +21,8 @@
#include "kapplicative.h"
#include "koperative.h"
#include "kcontinuation.h"
+#include "kenvironment.h"
+#include "ksymbol.h"
/* to use in type checking binds when no check is needed */
#define anytype(obj_) (true)
@@ -426,4 +428,53 @@ inline int32_t kcheck32(klisp_State *K, char *msg, int64_t i)
int64_t kgcd32_64(int32_t a, int32_t b);
int64_t klcm32_64(int32_t a, int32_t b);
+
+/*
+** Macros for ground environment initialization
+*/
+
+/*
+** BEWARE: this is highly unhygienic, it assumes variables "symbol" and
+** "value", both of type TValue. symbol will be bound to a symbol named by
+** "n_" and can be referrenced in the var_args
+** GC: All of these should be called when GC is deactivated on startup
+*/
+
+/* TODO add si to the symbols */
+#if KTRACK_SI
+#define add_operative(K_, env_, n_, fn_, ...) \
+ { symbol = ksymbol_new(K_, n_, KNIL); \
+ value = kmake_operative(K_, fn_, __VA_ARGS__); \
+ TValue str = kstring_new_b_imm(K_, __FILE__); \
+ TValue si = kcons(K, str, kcons(K_, i2tv(__LINE__), \
+ i2tv(0))); \
+ kset_source_info(K_, value, si); \
+ kadd_binding(K_, env_, symbol, value); }
+
+#define add_applicative(K_, env_, n_, fn_, ...) \
+ { symbol = ksymbol_new(K_, n_, KNIL); \
+ value = kmake_applicative(K_, fn_, __VA_ARGS__); \
+ TValue str = kstring_new_b_imm(K_, __FILE__); \
+ TValue si = kcons(K, str, kcons(K_, i2tv(__LINE__), \
+ i2tv(0))); \
+ kset_source_info(K_, kunwrap(value), si); \
+ kset_source_info(K_, value, si); \
+ kadd_binding(K_, env_, symbol, value); }
+#else /* KTRACK_SI */
+#define add_operative(K_, env_, n_, fn_, ...) \
+ { symbol = ksymbol_new(K_, n_, KNIL); \
+ value = kmake_operative(K_, fn_, __VA_ARGS__); \
+ kadd_binding(K_, env_, symbol, value); }
+
+#define add_applicative(K_, env_, n_, fn_, ...) \
+ { symbol = ksymbol_new(K_, n_); \
+ value = kmake_applicative(K_, fn_, __VA_ARGS__); \
+ kadd_binding(K_, env_, symbol, value); }
+#endif /* KTRACK_SI */
+
+#define add_value(K_, env_, n_, v_) \
+ { value = v_; \
+ symbol = ksymbol_new(K_, n_, KNIL); \
+ kadd_binding(K_, env_, symbol, v_); }
+
#endif
diff --git a/src/kgkd_vars.c b/src/kgkd_vars.c
@@ -200,3 +200,13 @@ void make_keyed_dynamic_variable(klisp_State *K, TValue *xparams,
kapply_cc(K, ls);
}
+/* init ground */
+void kinit_kgkd_vars_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 10.1.1 make-keyed-dynamic-variable */
+ add_applicative(K, ground_env, "make-keyed-dynamic-variable",
+ make_keyed_dynamic_variable, 0);
+}
diff --git a/src/kgkd_vars.h b/src/kgkd_vars.h
@@ -30,4 +30,7 @@ void make_keyed_dynamic_variable(klisp_State *K, TValue *xparams,
void do_unbind(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_kgkd_vars_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgks_vars.c b/src/kgks_vars.c
@@ -76,3 +76,15 @@ void make_keyed_static_variable(klisp_State *K, TValue *xparams,
kapply_cc(K, ls);
}
+
+
+/* init ground */
+void kinit_kgks_vars_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 11.1.1 make-keyed-static-variable */
+ add_applicative(K, ground_env, "make-keyed-static-variable",
+ make_keyed_static_variable, 0);
+}
diff --git a/src/kgks_vars.h b/src/kgks_vars.h
@@ -22,4 +22,7 @@
void make_keyed_static_variable(klisp_State *K, TValue *xparams,
TValue ptree, TValue denv);
+/* init ground */
+void kinit_kgks_vars_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgnumbers.c b/src/kgnumbers.c
@@ -2213,3 +2213,140 @@ void kexpt(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
}
arith_kapply_cc(K, res);
}
+
+
+/* init ground */
+void kinit_numbers_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* No complex or bounded reals for now */
+ /* 12.5.1 number?, finite?, integer? */
+ add_applicative(K, ground_env, "number?", ftypep, 2, symbol,
+ p2tv(knumberp));
+ add_applicative(K, ground_env, "finite?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(kfinitep));
+ add_applicative(K, ground_env, "integer?", ftypep, 2, symbol,
+ p2tv(kintegerp));
+ /* 12.5.2 =? */
+ add_applicative(K, ground_env, "=?", ftyped_kbpredp, 3,
+ symbol, p2tv(knumber_wpvp), p2tv(knum_eqp));
+ /* 12.5.3 <?, <=?, >?, >=? */
+ add_applicative(K, ground_env, "<?", ftyped_kbpredp, 3,
+ symbol, p2tv(kreal_wpvp), p2tv(knum_ltp));
+ add_applicative(K, ground_env, "<=?", ftyped_kbpredp, 3,
+ symbol, p2tv(kreal_wpvp), p2tv(knum_lep));
+ add_applicative(K, ground_env, ">?", ftyped_kbpredp, 3,
+ symbol, p2tv(kreal_wpvp), p2tv(knum_gtp));
+ add_applicative(K, ground_env, ">=?", ftyped_kbpredp, 3,
+ symbol, p2tv(kreal_wpvp), p2tv(knum_gep));
+ /* 12.5.4 + */
+ add_applicative(K, ground_env, "+", kplus, 0);
+ /* 12.5.5 * */
+ add_applicative(K, ground_env, "*", ktimes, 0);
+ /* 12.5.6 - */
+ add_applicative(K, ground_env, "-", kminus, 0);
+ /* 12.5.7 zero? */
+ add_applicative(K, ground_env, "zero?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(kzerop));
+ /* 12.5.8 div, mod, div-and-mod */
+ add_applicative(K, ground_env, "div", kdiv_mod, 2, symbol,
+ i2tv(FDIV_DIV));
+ add_applicative(K, ground_env, "mod", kdiv_mod, 2, symbol,
+ i2tv(FDIV_MOD));
+ add_applicative(K, ground_env, "div-and-mod", kdiv_mod, 2, symbol,
+ i2tv(FDIV_DIV | FDIV_MOD));
+ /* 12.5.9 div0, mod0, div0-and-mod0 */
+ add_applicative(K, ground_env, "div0", kdiv_mod, 2, symbol,
+ i2tv(FDIV_ZERO | FDIV_DIV));
+ add_applicative(K, ground_env, "mod0", kdiv_mod, 2, symbol,
+ i2tv(FDIV_ZERO | FDIV_MOD));
+ add_applicative(K, ground_env, "div0-and-mod0", kdiv_mod, 2, symbol,
+ i2tv(FDIV_ZERO | FDIV_DIV | FDIV_MOD));
+ /* 12.5.10 positive?, negative? */
+ add_applicative(K, ground_env, "positive?", ftyped_predp, 3, symbol,
+ p2tv(krealp), p2tv(kpositivep));
+ add_applicative(K, ground_env, "negative?", ftyped_predp, 3, symbol,
+ p2tv(krealp), p2tv(knegativep));
+ /* 12.5.11 odd?, even? */
+ add_applicative(K, ground_env, "odd?", ftyped_predp, 3, symbol,
+ p2tv(kintegerp), p2tv(koddp));
+ add_applicative(K, ground_env, "even?", ftyped_predp, 3, symbol,
+ p2tv(kintegerp), p2tv(kevenp));
+ /* 12.5.12 abs */
+ add_applicative(K, ground_env, "abs", kabs, 0);
+ /* 12.5.13 min, max */
+ add_applicative(K, ground_env, "min", kmin_max, 2, symbol, b2tv(FMIN));
+ add_applicative(K, ground_env, "max", kmin_max, 2, symbol, b2tv(FMAX));
+ /* 12.5.14 gcd, lcm */
+ add_applicative(K, ground_env, "gcd", kgcd, 0);
+ add_applicative(K, ground_env, "lcm", klcm, 0);
+ /* 12.6.1 exact?, inexact?, robust?, undefined? */
+ add_applicative(K, ground_env, "exact?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(kexactp));
+ add_applicative(K, ground_env, "inexact?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(kinexactp));
+ add_applicative(K, ground_env, "robust?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(krobustp));
+ add_applicative(K, ground_env, "undefined?", ftyped_predp, 3, symbol,
+ p2tv(knumberp), p2tv(kundefinedp));
+ /* 12.6.2 get-real-internal-bounds, get-real-exact-bounds */
+ add_applicative(K, ground_env, "get-real-internal-bounds",
+ kget_real_internal_bounds, 0);
+ add_applicative(K, ground_env, "get-real-exact-bounds",
+ kget_real_exact_bounds, 0);
+ /* 12.6.3 get-real-internal-primary, get-real-exact-primary */
+ add_applicative(K, ground_env, "get-real-internal-primary",
+ kget_real_internal_primary, 0);
+ add_applicative(K, ground_env, "get-real-exact-primary",
+ kget_real_exact_primary, 0);
+ /* 12.6.4 make-inexact */
+ add_applicative(K, ground_env, "make-inexact", kmake_inexact, 0);
+ /* 12.6.5 real->inexact, real->exact */
+ add_applicative(K, ground_env, "real->inexact", kreal_to_inexact, 0);
+ add_applicative(K, ground_env, "real->exact", kreal_to_exact, 0);
+ /* 12.6.6 with-strict-arithmetic, get-strict-arithmetic? */
+ add_applicative(K, ground_env, "with-strict-arithmetic",
+ kwith_strict_arithmetic, 0);
+ add_applicative(K, ground_env, "get-strict-arithmetic?",
+ kget_strict_arithmeticp, 0);
+ /* 12.8.1 rational? */
+ add_applicative(K, ground_env, "rational?", ftypep, 2, symbol,
+ p2tv(krationalp));
+ /* 12.8.2 / */
+ add_applicative(K, ground_env, "/", kdivided, 0);
+ /* 12.8.3 numerator, denominator */
+ add_applicative(K, ground_env, "numerator", knumerator, 0);
+ add_applicative(K, ground_env, "denominator", kdenominator, 0);
+ /* 12.8.4 floor, ceiling, truncate, round */
+ add_applicative(K, ground_env, "floor", kreal_to_integer, 2,
+ symbol, i2tv((int32_t) K_FLOOR));
+ add_applicative(K, ground_env, "ceiling", kreal_to_integer, 2,
+ symbol, i2tv((int32_t) K_CEILING));
+ add_applicative(K, ground_env, "truncate", kreal_to_integer, 2,
+ symbol, i2tv((int32_t) K_TRUNCATE));
+ add_applicative(K, ground_env, "round", kreal_to_integer, 2,
+ symbol, i2tv((int32_t) K_ROUND_EVEN));
+ /* 12.8.5 rationalize, simplest-rational */
+ add_applicative(K, ground_env, "rationalize", krationalize, 0);
+ add_applicative(K, ground_env, "simplest-rational", ksimplest_rational, 0);
+ /* 12.9.1 real? */
+ add_applicative(K, ground_env, "real?", ftypep, 2, symbol,
+ p2tv(krealp));
+ /* 12.9.2 exp, log */
+ add_applicative(K, ground_env, "exp", kexp, 0);
+ add_applicative(K, ground_env, "log", klog, 0);
+ /* 12.9.3 sin, cos, tan */
+ add_applicative(K, ground_env, "sin", ktrig, 1, sin);
+ add_applicative(K, ground_env, "cos", ktrig, 1, cos);
+ add_applicative(K, ground_env, "tan", ktrig, 1, tan);
+ /* 12.9.4 asin, acos, atan */
+ add_applicative(K, ground_env, "asin", katrig, 1, asin);
+ add_applicative(K, ground_env, "acos", katrig, 1, acos);
+ add_applicative(K, ground_env, "atan", katan, 0);
+ /* 12.9.5 sqrt */
+ add_applicative(K, ground_env, "sqrt", ksqrt, 0);
+ /* 12.9.6 expt */
+ add_applicative(K, ground_env, "expt", kexpt, 0);
+}
diff --git a/src/kgnumbers.h b/src/kgnumbers.h
@@ -221,4 +221,7 @@ inline bool knum_same_signp(klisp_State *K, TValue n1, TValue n2)
return kpositivep(K, n1) == kpositivep(K, n2);
}
+/* init ground */
+void kinit_numbers_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgpair_mut.c b/src/kgpair_mut.c
@@ -490,3 +490,27 @@ void memqp(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
kapply_cc(K, res);
}
+
+/* init ground */
+void kinit_pair_mut_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.7.1 set-car!, set-cdr! */
+ add_applicative(K, ground_env, "set-car!", set_carB, 0);
+ add_applicative(K, ground_env, "set-cdr!", set_cdrB, 0);
+ /* 4.7.2 copy-es-immutable */
+ add_applicative(K, ground_env, "copy-es-immutable", copy_es, 2, symbol,
+ b2tv(false));
+ /* 5.8.1 encycle! */
+ add_applicative(K, ground_env, "encycle!", encycleB, 0);
+ /* 6.4.1 append! */
+ add_applicative(K, ground_env, "append!", appendB, 0);
+ /* 6.4.2 copy-es */
+ add_applicative(K, ground_env, "copy-es", copy_es, 2, symbol, b2tv(true));
+ /* 6.4.3 assq */
+ add_applicative(K, ground_env, "assq", assq, 0);
+ /* 6.4.3 memq? */
+ add_applicative(K, ground_env, "memq?", memqp, 0);
+}
diff --git a/src/kgpair_mut.h b/src/kgpair_mut.h
@@ -51,4 +51,7 @@ void assq(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
/* 6.4.3 memq? */
void memqp(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
+/* init ground */
+void kinit_pair_mut_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgpairs_lists.c b/src/kgpairs_lists.c
@@ -996,3 +996,109 @@ void reduce(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
}
kapply_cc(K, res);
}
+
+/* init ground */
+void kinit_pairs_lists_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.6.1 pair? */
+ add_applicative(K, ground_env, "pair?", typep, 2, symbol,
+ i2tv(K_TPAIR));
+ /* 4.6.2 null? */
+ add_applicative(K, ground_env, "null?", typep, 2, symbol,
+ i2tv(K_TNIL));
+ /* 4.6.3 cons */
+ add_applicative(K, ground_env, "cons", cons, 0);
+ /* 5.2.1 list */
+ add_applicative(K, ground_env, "list", list, 0);
+ /* 5.2.2 list* */
+ add_applicative(K, ground_env, "list*", listS, 0);
+ /* 5.4.1 car, cdr */
+ add_applicative(K, ground_env, "car", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(1, 0x0000));
+ add_applicative(K, ground_env, "cdr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(1, 0x0001));
+ /* 5.4.2 caar, cadr, ... cddddr */
+ add_applicative(K, ground_env, "caar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(2, 0x0000));
+ add_applicative(K, ground_env, "cadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(2, 0x0001));
+ add_applicative(K, ground_env, "cdar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(2, 0x0010));
+ add_applicative(K, ground_env, "cddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(2, 0x0011));
+ add_applicative(K, ground_env, "caaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0000));
+ add_applicative(K, ground_env, "caadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0001));
+ add_applicative(K, ground_env, "cadar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0010));
+ add_applicative(K, ground_env, "caddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0011));
+ add_applicative(K, ground_env, "cdaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0100));
+ add_applicative(K, ground_env, "cdadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0101));
+ add_applicative(K, ground_env, "cddar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0110));
+ add_applicative(K, ground_env, "cdddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(3, 0x0111));
+ add_applicative(K, ground_env, "caaaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0000));
+ add_applicative(K, ground_env, "caaadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0001));
+ add_applicative(K, ground_env, "caadar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0010));
+ add_applicative(K, ground_env, "caaddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0011));
+ add_applicative(K, ground_env, "cadaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0100));
+ add_applicative(K, ground_env, "cadadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0101));
+ add_applicative(K, ground_env, "caddar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0110));
+ add_applicative(K, ground_env, "cadddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x0111));
+ add_applicative(K, ground_env, "cdaaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1000));
+ add_applicative(K, ground_env, "cdaadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1001));
+ add_applicative(K, ground_env, "cdadar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1010));
+ add_applicative(K, ground_env, "cdaddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1011));
+ add_applicative(K, ground_env, "cddaar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1100));
+ add_applicative(K, ground_env, "cddadr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1101));
+ add_applicative(K, ground_env, "cdddar", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1110));
+ add_applicative(K, ground_env, "cddddr", c_ad_r, 2, symbol,
+ C_AD_R_PARAM(4, 0x1111));
+ /* 5.7.1 get-list-metrics */
+ add_applicative(K, ground_env, "get-list-metrics", get_list_metrics, 0);
+ /* 5.7.2 list-tail */
+ add_applicative(K, ground_env, "list-tail", list_tail, 0);
+ /* 6.3.1 length */
+ add_applicative(K, ground_env, "length", length, 0);
+ /* 6.3.2 list-ref */
+ add_applicative(K, ground_env, "list-ref", list_ref, 0);
+ /* 6.3.3 append */
+ add_applicative(K, ground_env, "append", append, 0);
+ /* 6.3.4 list-neighbors */
+ add_applicative(K, ground_env, "list-neighbors", list_neighbors, 0);
+ /* 6.3.5 filter */
+ add_applicative(K, ground_env, "filter", filter, 0);
+ /* 6.3.6 assoc */
+ add_applicative(K, ground_env, "assoc", assoc, 0);
+ /* 6.3.7 member? */
+ add_applicative(K, ground_env, "member?", memberp, 0);
+ /* 6.3.8 finite-list? */
+ add_applicative(K, ground_env, "finite-list?", finite_listp, 0);
+ /* 6.3.9 countable-list? */
+ add_applicative(K, ground_env, "countable-list?", countable_listp, 0);
+ /* 6.3.10 reduce */
+ add_applicative(K, ground_env, "reduce", reduce, 0);
+}
diff --git a/src/kgpairs_lists.h b/src/kgpairs_lists.h
@@ -97,4 +97,7 @@ void do_reduce_combine(klisp_State *K, TValue *xparams, TValue obj);
void do_reduce_cycle(klisp_State *K, TValue *xparams, TValue obj);
void do_reduce(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_pairs_lists_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgports.c b/src/kgports.c
@@ -341,6 +341,14 @@ TValue read_all_expr(klisp_State *K, TValue port)
return kcutoff_dummy1(K);
} else {
TValue new_pair = kimm_cons(K, obj, KNIL);
+#if KTRACK_SI
+ /* put the source info */
+ /* XXX: should first read all comments and whitespace,
+ then save the source info, then read the object and
+ lastly put the saved source info on the new pair...
+ For now this will do, but it's not technically correct */
+ kset_source_info(K, new_pair, ktry_get_si(K, obj));
+#endif
kset_cdr_unsafe(K, tail, new_pair);
tail = new_pair;
}
@@ -540,3 +548,87 @@ void display(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
kwrite_display_to_port(K, port, obj, true);
kapply_cc(K, KINERT);
}
+
+/* init ground */
+void kinit_ports_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 15.1.1 port? */
+ add_applicative(K, ground_env, "port?", typep, 2, symbol,
+ i2tv(K_TPORT));
+ /* 15.1.2 input-port?, output-port? */
+ add_applicative(K, ground_env, "input-port?", ftypep, 2, symbol,
+ p2tv(kis_input_port));
+ add_applicative(K, ground_env, "output-port?", ftypep, 2, symbol,
+ p2tv(kis_output_port));
+ /* 15.1.3 with-input-from-file, with-ouput-to-file */
+ add_applicative(K, ground_env, "with-input-from-file", with_file,
+ 3, symbol, b2tv(false), K->kd_in_port_key);
+ add_applicative(K, ground_env, "with-output-to-file", with_file,
+ 3, symbol, b2tv(true), K->kd_out_port_key);
+ /* 15.1.4 get-current-input-port, get-current-output-port */
+ add_applicative(K, ground_env, "get-current-input-port", get_current_port,
+ 2, symbol, K->kd_in_port_key);
+ add_applicative(K, ground_env, "get-current-output-port", get_current_port,
+ 2, symbol, K->kd_out_port_key);
+ /* 15.1.5 open-input-file, open-output-file */
+ add_applicative(K, ground_env, "open-input-file", open_file, 2, symbol,
+ b2tv(false));
+ add_applicative(K, ground_env, "open-output-file", open_file, 2, symbol,
+ b2tv(true));
+ /* 15.1.6 close-input-file, close-output-file */
+ /* ASK John: should this be called close-input-port & close-ouput-port
+ like in r5rs? that doesn't seem consistent with open thou */
+ add_applicative(K, ground_env, "close-input-file", close_file, 2, symbol,
+ b2tv(false));
+ add_applicative(K, ground_env, "close-output-file", close_file, 2, symbol,
+ b2tv(true));
+ /* 15.1.7 read */
+ add_applicative(K, ground_env, "read", read, 0);
+ /* 15.1.8 write */
+ add_applicative(K, ground_env, "write", write, 0);
+
+ /*
+ ** These are from scheme (r5rs)
+ */
+
+ /* 15.1.? eof-object? */
+ add_applicative(K, ground_env, "eof-object?", typep, 2, symbol,
+ i2tv(K_TEOF));
+ /* 15.1.? newline */
+ add_applicative(K, ground_env, "newline", newline, 0);
+ /* 15.1.? write-char */
+ add_applicative(K, ground_env, "write-char", write_char, 0);
+ /* 15.1.? read-char */
+ add_applicative(K, ground_env, "read-char", read_peek_char, 2, symbol,
+ b2tv(false));
+ /* 15.1.? peek-char */
+ add_applicative(K, ground_env, "peek-char", read_peek_char, 2, symbol,
+ b2tv(true));
+ /* 15.1.? char-ready? */
+ /* XXX: this always return #t, proper behaviour requires platform
+ specific code (probably select for posix, a thread for windows
+ (at least for files & consoles), I think pipes and sockets may
+ have something */
+ add_applicative(K, ground_env, "char-ready?", char_readyp, 0);
+ /* 15.2.1 call-with-input-file, call-with-output-file */
+ add_applicative(K, ground_env, "call-with-input-file", call_with_file,
+ 2, symbol, b2tv(false));
+ add_applicative(K, ground_env, "call-with-output-file", call_with_file,
+ 2, symbol, b2tv(true));
+ /* 15.2.2 load */
+ add_applicative(K, ground_env, "load", load, 0);
+ /* 15.2.3 get-module */
+ add_applicative(K, ground_env, "get-module", get_module, 0);
+ /* 15.2.? display */
+ add_applicative(K, ground_env, "display", display, 0);
+
+ /* MAYBE: That's all there is in the report combined with r5rs scheme,
+ but we will probably need: file-exists?, rename-file and remove-file.
+ It would also be good to be able to select between append, truncate and
+ error if a file exists, but that would need to be an option in all three
+ methods of opening. Also some directory checking, traversing etc */
+ /* BUT SEE r7rs draft for some of the above */
+}
diff --git a/src/kgports.h b/src/kgports.h
@@ -85,4 +85,7 @@ void display(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
void do_close_file_ret(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_ports_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgpromises.c b/src/kgpromises.c
@@ -105,3 +105,20 @@ void memoize(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
TValue new_prom = kmake_promise(K, exp, KNIL);
kapply_cc(K, new_prom);
}
+
+/* init ground */
+void kinit_promises_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 9.1.1 promise? */
+ add_applicative(K, ground_env, "promise?", typep, 2, symbol,
+ i2tv(K_TPROMISE));
+ /* 9.1.2 force */
+ add_applicative(K, ground_env, "force", force, 0);
+ /* 9.1.3 $lazy */
+ add_operative(K, ground_env, "$lazy", Slazy, 0);
+ /* 9.1.4 memoize */
+ add_applicative(K, ground_env, "memoize", memoize, 0);
+}
diff --git a/src/kgpromises.h b/src/kgpromises.h
@@ -32,4 +32,7 @@ void memoize(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
void do_handle_result(klisp_State *K, TValue *xparams, TValue obj);
+/* init ground */
+void kinit_promises_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kground.c b/src/kground.c
@@ -14,11 +14,6 @@
#include "kstate.h"
#include "kobject.h"
#include "kground.h"
-#include "kenvironment.h"
-#include "ksymbol.h"
-#include "koperative.h"
-#include "kapplicative.h"
-#include "kerror.h"
#include "kghelpers.h"
#include "kgbooleans.h"
@@ -47,51 +42,6 @@
#include "keval.h"
#include "krepl.h"
-
-/*
-** BEWARE: this is highly unhygienic, it assumes variables "symbol" and
-** "value", both of type TValue. symbol will be bound to a symbol named by
-** "n_" and can be referrenced in the var_args
-** GC: All of these should be called when GC is deactivated on startup
-*/
-
-/* TODO add si to the symbols */
-#if KTRACK_SI
-#define add_operative(K_, env_, n_, fn_, ...) \
- { symbol = ksymbol_new(K_, n_, KNIL); \
- value = kmake_operative(K_, fn_, __VA_ARGS__); \
- TValue str = kstring_new_b_imm(K_, __FILE__); \
- TValue si = kcons(K, str, kcons(K_, i2tv(__LINE__), \
- i2tv(0))); \
- kset_source_info(K_, value, si); \
- kadd_binding(K_, env_, symbol, value); }
-
-#define add_applicative(K_, env_, n_, fn_, ...) \
- { symbol = ksymbol_new(K_, n_, KNIL); \
- value = kmake_applicative(K_, fn_, __VA_ARGS__); \
- TValue str = kstring_new_b_imm(K_, __FILE__); \
- TValue si = kcons(K, str, kcons(K_, i2tv(__LINE__), \
- i2tv(0))); \
- kset_source_info(K_, kunwrap(value), si); \
- kset_source_info(K_, value, si); \
- kadd_binding(K_, env_, symbol, value); }
-#else /* KTRACK_SI */
-#define add_operative(K_, env_, n_, fn_, ...) \
- { symbol = ksymbol_new(K_, n_, KNIL); \
- value = kmake_operative(K_, fn_, __VA_ARGS__); \
- kadd_binding(K_, env_, symbol, value); }
-
-#define add_applicative(K_, env_, n_, fn_, ...) \
- { symbol = ksymbol_new(K_, n_); \
- value = kmake_applicative(K_, fn_, __VA_ARGS__); \
- kadd_binding(K_, env_, symbol, value); }
-#endif /* KTRACK_SI */
-
-#define add_value(K_, env_, n_, v_) \
- { value = v_; \
- symbol = ksymbol_new(K_, n_, KNIL); \
- kadd_binding(K_, env_, symbol, v_); }
-
/* for init_cont_names */
#define add_cont_name(K_, t_, c_, n_) \
{ TValue str = kstring_new_b_imm(K_, n_); \
@@ -158,1045 +108,33 @@ void kinit_cont_names(klisp_State *K)
*/
void kinit_ground_env(klisp_State *K)
{
- TValue ground_env = K->ground_env; /* this is already rooted */
- TValue symbol, value;
-
- /*
- ** This section will roughly follow the report and will reference the
- ** section in which each symbol is defined
- */
-
- /*
- **
- ** 4 Core types and primitive features
- **
- */
-
- /*
- ** 4.1 Booleans
- */
-
- /* 4.1.1 boolean? */
- add_applicative(K, ground_env, "boolean?", typep, 2, symbol,
- i2tv(K_TBOOLEAN));
-
- /*
- ** 4.2 Equivalence under mutation
- */
-
- /* 4.2.1 eq? */
- /* 6.5.1 eq? */
- add_applicative(K, ground_env, "eq?", eqp, 0);
-
- /*
- ** 4.3 Equivalence up to mutation
- */
-
- /* 4.3.1 equal? */
- /* 6.6.1 equal? */
- add_applicative(K, ground_env, "equal?", equalp, 0);
-
- /*
- ** 4.4 Symbols
- */
-
- /* 4.4.1 symbol? */
- add_applicative(K, ground_env, "symbol?", typep, 2, symbol,
- i2tv(K_TSYMBOL));
-
- /*
- ** 4.5 Control
- */
-
- /* 4.5.1 inert? */
- add_applicative(K, ground_env, "inert?", typep, 2, symbol,
- i2tv(K_TINERT));
-
- /* 4.5.2 $if */
- add_operative(K, ground_env, "$if", Sif, 0);
-
- /*
- ** 4.6 Pairs and lists
- */
-
- /* 4.6.1 pair? */
- add_applicative(K, ground_env, "pair?", typep, 2, symbol,
- i2tv(K_TPAIR));
-
- /* 4.6.2 null? */
- add_applicative(K, ground_env, "null?", typep, 2, symbol,
- i2tv(K_TNIL));
-
- /* 4.6.3 cons */
- add_applicative(K, ground_env, "cons", cons, 0);
-
- /*
- ** 4.7 Pair mutation
- */
-
- /* 4.7.1 set-car!, set-cdr! */
- add_applicative(K, ground_env, "set-car!", set_carB, 0);
- add_applicative(K, ground_env, "set-cdr!", set_cdrB, 0);
-
- /* 4.7.2 copy-es-immutable */
- add_applicative(K, ground_env, "copy-es-immutable", copy_es, 2, symbol,
- b2tv(false));
-
- /*
- ** 4.8 Environments
- */
-
- /* 4.8.1 environment? */
- add_applicative(K, ground_env, "environment?", typep, 2, symbol,
- i2tv(K_TENVIRONMENT));
-
- /* 4.8.2 ignore? */
- add_applicative(K, ground_env, "ignore?", typep, 2, symbol,
- i2tv(K_TIGNORE));
-
- /* 4.8.3 eval */
- add_applicative(K, ground_env, "eval", eval, 0);
-
- /* 4.8.4 make-environment */
- add_applicative(K, ground_env, "make-environment", make_environment, 0);
-
- /*
- ** 4.9 Environment mutation
- */
-
- /* 4.9.1 $define! */
- add_operative(K, ground_env, "$define!", SdefineB, 1, symbol);
-
- /*
- ** 4.10 Combiners
- */
-
- /* 4.10.1 operative? */
- add_applicative(K, ground_env, "operative?", typep, 2, symbol,
- i2tv(K_TOPERATIVE));
-
- /* 4.10.2 applicative? */
- add_applicative(K, ground_env, "applicative?", typep, 2, symbol,
- i2tv(K_TAPPLICATIVE));
-
- /* 4.10.3 $vau */
- /* 5.3.1 $vau */
- add_operative(K, ground_env, "$vau", Svau, 0);
-
- /* 4.10.4 wrap */
- add_applicative(K, ground_env, "wrap", wrap, 0);
-
- /* 4.10.5 unwrap */
- add_applicative(K, ground_env, "unwrap", unwrap, 0);
-
- /*
- **
- ** 5 Core library features (I)
- **
- */
-
- /*
- ** 5.1 Control
- */
-
- /* 5.1.1 $sequence */
- add_operative(K, ground_env, "$sequence", Ssequence, 0);
-
- /*
- ** 5.2 Pairs and lists
- */
-
- /* 5.2.1 list */
- add_applicative(K, ground_env, "list", list, 0);
-
- /* 5.2.2 list* */
- add_applicative(K, ground_env, "list*", listS, 0);
-
- /*
- ** 5.3 Combiners
- */
-
- /* 5.3.1 $vau */
- /* DONE: above, together with 4.10.4 */
-
- /* 5.3.2 $lambda */
- add_operative(K, ground_env, "$lambda", Slambda, 0);
-
- /*
- ** 5.4 Pairs and lists
- */
-
- /* 5.4.1 car, cdr */
- add_applicative(K, ground_env, "car", c_ad_r, 2, symbol,
- C_AD_R_PARAM(1, 0x0000));
- add_applicative(K, ground_env, "cdr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(1, 0x0001));
-
- /* 5.4.2 caar, cadr, ... cddddr */
- add_applicative(K, ground_env, "caar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(2, 0x0000));
- add_applicative(K, ground_env, "cadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(2, 0x0001));
- add_applicative(K, ground_env, "cdar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(2, 0x0010));
- add_applicative(K, ground_env, "cddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(2, 0x0011));
-
- add_applicative(K, ground_env, "caaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0000));
- add_applicative(K, ground_env, "caadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0001));
- add_applicative(K, ground_env, "cadar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0010));
- add_applicative(K, ground_env, "caddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0011));
- add_applicative(K, ground_env, "cdaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0100));
- add_applicative(K, ground_env, "cdadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0101));
- add_applicative(K, ground_env, "cddar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0110));
- add_applicative(K, ground_env, "cdddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(3, 0x0111));
-
- add_applicative(K, ground_env, "caaaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0000));
- add_applicative(K, ground_env, "caaadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0001));
- add_applicative(K, ground_env, "caadar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0010));
- add_applicative(K, ground_env, "caaddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0011));
- add_applicative(K, ground_env, "cadaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0100));
- add_applicative(K, ground_env, "cadadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0101));
- add_applicative(K, ground_env, "caddar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0110));
- add_applicative(K, ground_env, "cadddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x0111));
- add_applicative(K, ground_env, "cdaaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1000));
- add_applicative(K, ground_env, "cdaadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1001));
- add_applicative(K, ground_env, "cdadar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1010));
- add_applicative(K, ground_env, "cdaddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1011));
- add_applicative(K, ground_env, "cddaar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1100));
- add_applicative(K, ground_env, "cddadr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1101));
- add_applicative(K, ground_env, "cdddar", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1110));
- add_applicative(K, ground_env, "cddddr", c_ad_r, 2, symbol,
- C_AD_R_PARAM(4, 0x1111));
-
- /*
- ** 5.5 Combiners
- */
-
- /* 5.5.1 apply */
- add_applicative(K, ground_env, "apply", apply, 0);
-
- /*
- ** 5.6 Control
- */
-
- /* 5.6.1 $cond */
- add_operative(K, ground_env, "$cond", Scond, 0);
-
- /*
- ** 5.7 Pairs and lists
- */
-
- /* 5.7.1 get-list-metrics */
- add_applicative(K, ground_env, "get-list-metrics", get_list_metrics, 0);
-
- /* 5.7.2 list-tail */
- add_applicative(K, ground_env, "list-tail", list_tail, 0);
-
- /*
- ** 5.8 Pair mutation
- */
-
- /* 5.8.1 encycle! */
- add_applicative(K, ground_env, "encycle!", encycleB, 0);
-
- /*
- ** 5.9 Combiners
- */
-
- /* 5.9.1 map */
- add_applicative(K, ground_env, "map", map, 0);
-
- /*
- ** 5.10 Environments
- */
-
- /* 5.10.1 $let */
- add_operative(K, ground_env, "$let", Slet, 1, symbol);
-
- /*
- **
- ** 6 Core library features (II)
- **
- */
-
- /*
- ** 6.1 Booleans
- */
-
- /* 6.1.1 not? */
- add_applicative(K, ground_env, "not?", notp, 0);
-
- /* 6.1.2 and? */
- add_applicative(K, ground_env, "and?", andp, 0);
-
- /* 6.1.3 or? */
- add_applicative(K, ground_env, "or?", orp, 0);
-
- /* 6.1.4 $and? */
- add_operative(K, ground_env, "$and?", Sandp_Sorp, 2, symbol, KFALSE);
-
- /* 6.1.5 $or? */
- add_operative(K, ground_env, "$or?", Sandp_Sorp, 2, symbol, KTRUE);
-
- /*
- ** 6.2 Combiners
- */
-
- /* 6.2.1 combiner? */
- add_applicative(K, ground_env, "combiner?", ftypep, 2, symbol,
- p2tv(kcombinerp));
-
- /*
- ** 6.3 Pairs and lists
- */
-
- /* 6.3.1 length */
- add_applicative(K, ground_env, "length", length, 0);
-
- /* 6.3.2 list-ref */
- add_applicative(K, ground_env, "list-ref", list_ref, 0);
-
- /* 6.3.3 append */
- add_applicative(K, ground_env, "append", append, 0);
-
- /* 6.3.4 list-neighbors */
- add_applicative(K, ground_env, "list-neighbors", list_neighbors, 0);
-
- /* 6.3.5 filter */
- add_applicative(K, ground_env, "filter", filter, 0);
-
- /* 6.3.6 assoc */
- add_applicative(K, ground_env, "assoc", assoc, 0);
-
- /* 6.3.7 member? */
- add_applicative(K, ground_env, "member?", memberp, 0);
-
- /* 6.3.8 finite-list? */
- add_applicative(K, ground_env, "finite-list?", finite_listp, 0);
-
- /* 6.3.9 countable-list? */
- add_applicative(K, ground_env, "countable-list?", countable_listp, 0);
-
- /* 6.3.10 reduce */
- add_applicative(K, ground_env, "reduce", reduce, 0);
-
- /*
- ** 6.4 Pair mutation
- */
-
- /* 6.4.1 append! */
- add_applicative(K, ground_env, "append!", appendB, 0);
-
- /* 6.4.2 copy-es */
- add_applicative(K, ground_env, "copy-es", copy_es, 2, symbol, b2tv(true));
-
- /* 6.4.3 assq */
- add_applicative(K, ground_env, "assq", assq, 0);
-
- /* 6.4.3 memq? */
- add_applicative(K, ground_env, "memq?", memqp, 0);
-
- /*
- ** 6.5 Equivalance under mutation
- */
-
- /* 6.5.1 eq? */
- /* DONE: above, together with 4.2.1 */
-
- /*
- ** 6.6 Equivalance up to mutation
- */
-
- /* 6.6.1 equal? */
- /* DONE: above, together with 4.3.1 */
-
- /*
- ** 6.7 Environments
- */
-
- /* 6.7.1 $binds? */
- add_operative(K, ground_env, "$binds?", Sbindsp, 0);
-
- /* 6.7.2 get-current-environment */
- add_applicative(K, ground_env, "get-current-environment",
- get_current_environment, 0);
-
- /* 6.7.3 make-kernel-standard-environment */
- add_applicative(K, ground_env, "make-kernel-standard-environment",
- make_kernel_standard_environment, 0);
-
- /* 6.7.4 $let* */
- add_operative(K, ground_env, "$let*", SletS, 1, symbol);
-
- /* 6.7.5 $letrec */
- add_operative(K, ground_env, "$letrec", Sletrec, 1, symbol);
-
- /* 6.7.6 $letrec* */
- add_operative(K, ground_env, "$letrec*", SletrecS, 1, symbol);
-
- /* 6.7.7 $let-redirect */
- add_operative(K, ground_env, "$let-redirect", Slet_redirect, 1, symbol);
-
- /* 6.7.8 $let-safe */
- add_operative(K, ground_env, "$let-safe", Slet_safe, 1, symbol);
-
- /* 6.7.9 $remote-eval */
- add_operative(K, ground_env, "$remote-eval", Sremote_eval, 0);
-
- /* 6.7.10 $bindings->environment */
- add_operative(K, ground_env, "$bindings->environment",
- Sbindings_to_environment, 1, symbol);
-
- /*
- ** 6.8 Environment mutation
- */
-
- /* 6.8.1 $set! */
- add_operative(K, ground_env, "$set!", SsetB, 1, symbol);
-
- /* 6.8.2 $provide! */
- add_operative(K, ground_env, "$provide!", SprovideB, 1, symbol);
-
- /* 6.8.3 $import! */
- add_operative(K, ground_env, "$import!", SimportB, 1, symbol);
-
- /*
- ** 6.9 Control
- */
-
- /* 6.9.1 for-each */
- add_applicative(K, ground_env, "for-each", for_each, 0);
-
- /*
- **
- ** 7 Continuations
- **
- */
-
- /*
- ** 7.2 Primitive features
- */
-
- /* 7.1.1 continuation? */
- add_applicative(K, ground_env, "continuation?", typep, 2, symbol,
- i2tv(K_TCONTINUATION));
-
- /* 7.2.2 call/cc */
- add_applicative(K, ground_env, "call/cc", call_cc, 0);
-
- /* 7.2.3 extend-continuation */
- add_applicative(K, ground_env, "extend-continuation", extend_continuation, 0);
-
- /* 7.2.4 guard-continuation */
- add_applicative(K, ground_env, "guard-continuation", guard_continuation,
- 0);
-
- /* 7.2.5 continuation->applicative */
- add_applicative(K, ground_env, "continuation->applicative",
- continuation_applicative, 0);
-
- /* 7.2.6 root-continuation */
- add_value(K, ground_env, "root-continuation",
- K->root_cont);
-
- /* 7.2.7 error-continuation */
- add_value(K, ground_env, "error-continuation",
- K->root_cont);
-
- /*
- ** 7.3 Library features
- */
-
- /* 7.3.1 apply-continuation */
- add_applicative(K, ground_env, "apply-continuation", apply_continuation,
- 0);
-
- /* 7.3.2 $let/cc */
- add_operative(K, ground_env, "$let/cc", Slet_cc,
- 0);
-
- /* 7.3.3 guard-dynamic-extent */
- add_applicative(K, ground_env, "guard-dynamic-extent",
- guard_dynamic_extent, 0);
-
- /* 7.3.4 exit */
- add_applicative(K, ground_env, "exit", kgexit,
- 0);
-
-
- /*
- **
- ** 8 Encapsulations
- **
- */
-
- /*
- ** 8.1 Primitive features
- */
-
- /* 8.1.1 make-encapsulation-type */
- add_applicative(K, ground_env, "make-encapsulation-type",
- make_encapsulation_type, 0);
-
- /*
- **
- ** 9 Promises
- **
- */
-
- /*
- ** 9.1 Library features
- */
-
- /* 9.1.1 promise? */
- add_applicative(K, ground_env, "promise?", typep, 2, symbol,
- i2tv(K_TPROMISE));
-
- /* 9.1.2 force */
- add_applicative(K, ground_env, "force", force, 0);
-
- /* 9.1.3 $lazy */
- add_operative(K, ground_env, "$lazy", Slazy, 0);
-
- /* 9.1.4 memoize */
- add_applicative(K, ground_env, "memoize", memoize, 0);
-
- /*
- **
- ** 10 Keyed Dynamic Variables
- **
- */
-
- /*
- ** 10.1 Primitive features
- */
-
- /* 10.1.1 make-keyed-dynamic-variable */
- add_applicative(K, ground_env, "make-keyed-dynamic-variable",
- make_keyed_dynamic_variable, 0);
-
-
/*
- **
- ** 11 Keyed Static Variables
- **
- */
-
- /*
- ** 11.1 Primitive features
- */
-
- /* 11.1.1 make-keyed-static-variable */
- add_applicative(K, ground_env, "make-keyed-static-variable",
- make_keyed_static_variable, 0);
-
-
- /*
- **
- ** 12 Numbers
- **
- */
-
- /* Only integers, rationals and exact infinities for now */
-
- /*
- ** 12.5 Number features
- */
-
- /* 12.5.1 number?, finite?, integer? */
- add_applicative(K, ground_env, "number?", ftypep, 2, symbol,
- p2tv(knumberp));
- add_applicative(K, ground_env, "finite?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(kfinitep));
- add_applicative(K, ground_env, "integer?", ftypep, 2, symbol,
- p2tv(kintegerp));
-
- /* 12.5.2 =? */
- add_applicative(K, ground_env, "=?", ftyped_kbpredp, 3,
- symbol, p2tv(knumber_wpvp), p2tv(knum_eqp));
-
- /* 12.5.3 <?, <=?, >?, >=? */
- add_applicative(K, ground_env, "<?", ftyped_kbpredp, 3,
- symbol, p2tv(kreal_wpvp), p2tv(knum_ltp));
- add_applicative(K, ground_env, "<=?", ftyped_kbpredp, 3,
- symbol, p2tv(kreal_wpvp), p2tv(knum_lep));
- add_applicative(K, ground_env, ">?", ftyped_kbpredp, 3,
- symbol, p2tv(kreal_wpvp), p2tv(knum_gtp));
- add_applicative(K, ground_env, ">=?", ftyped_kbpredp, 3,
- symbol, p2tv(kreal_wpvp), p2tv(knum_gep));
-
- /* 12.5.4 + */
- add_applicative(K, ground_env, "+", kplus, 0);
-
- /* 12.5.5 * */
- add_applicative(K, ground_env, "*", ktimes, 0);
-
- /* 12.5.6 - */
- add_applicative(K, ground_env, "-", kminus, 0);
-
- /* 12.5.7 zero? */
- add_applicative(K, ground_env, "zero?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(kzerop));
-
- /* 12.5.8 div, mod, div-and-mod */
- add_applicative(K, ground_env, "div", kdiv_mod, 2, symbol,
- i2tv(FDIV_DIV));
- add_applicative(K, ground_env, "mod", kdiv_mod, 2, symbol,
- i2tv(FDIV_MOD));
- add_applicative(K, ground_env, "div-and-mod", kdiv_mod, 2, symbol,
- i2tv(FDIV_DIV | FDIV_MOD));
-
- /* 12.5.9 div0, mod0, div0-and-mod0 */
- add_applicative(K, ground_env, "div0", kdiv_mod, 2, symbol,
- i2tv(FDIV_ZERO | FDIV_DIV));
- add_applicative(K, ground_env, "mod0", kdiv_mod, 2, symbol,
- i2tv(FDIV_ZERO | FDIV_MOD));
- add_applicative(K, ground_env, "div0-and-mod0", kdiv_mod, 2, symbol,
- i2tv(FDIV_ZERO | FDIV_DIV | FDIV_MOD));
-
- /* 12.5.10 positive?, negative? */
- add_applicative(K, ground_env, "positive?", ftyped_predp, 3, symbol,
- p2tv(krealp), p2tv(kpositivep));
- add_applicative(K, ground_env, "negative?", ftyped_predp, 3, symbol,
- p2tv(krealp), p2tv(knegativep));
-
- /* 12.5.11 odd?, even? */
- add_applicative(K, ground_env, "odd?", ftyped_predp, 3, symbol,
- p2tv(kintegerp), p2tv(koddp));
- add_applicative(K, ground_env, "even?", ftyped_predp, 3, symbol,
- p2tv(kintegerp), p2tv(kevenp));
-
- /* 12.5.12 abs */
- add_applicative(K, ground_env, "abs", kabs, 0);
-
- /* 12.5.13 min, max */
- add_applicative(K, ground_env, "min", kmin_max, 2, symbol, b2tv(FMIN));
- add_applicative(K, ground_env, "max", kmin_max, 2, symbol, b2tv(FMAX));
-
- /* 12.5.14 gcd, lcm */
- add_applicative(K, ground_env, "gcd", kgcd, 0);
- add_applicative(K, ground_env, "lcm", klcm, 0);
-
- /*
- ** 12.8 Inexact features
- */
-
- /* 12.6.1 exact?, inexact?, robust?, undefined? */
- add_applicative(K, ground_env, "exact?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(kexactp));
- add_applicative(K, ground_env, "inexact?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(kinexactp));
- add_applicative(K, ground_env, "robust?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(krobustp));
- add_applicative(K, ground_env, "undefined?", ftyped_predp, 3, symbol,
- p2tv(knumberp), p2tv(kundefinedp));
-
- /* 12.6.2 get-real-internal-bounds, get-real-exact-bounds */
- add_applicative(K, ground_env, "get-real-internal-bounds",
- kget_real_internal_bounds, 0);
- add_applicative(K, ground_env, "get-real-exact-bounds",
- kget_real_exact_bounds, 0);
-
- /* 12.6.3 get-real-internal-primary, get-real-exact-primary */
- add_applicative(K, ground_env, "get-real-internal-primary",
- kget_real_internal_primary, 0);
- add_applicative(K, ground_env, "get-real-exact-primary",
- kget_real_exact_primary, 0);
-
- /* 12.6.4 make-inexact */
- add_applicative(K, ground_env, "make-inexact", kmake_inexact, 0);
-
- /* 12.6.5 real->inexact, real->exact */
- add_applicative(K, ground_env, "real->inexact", kreal_to_inexact, 0);
- add_applicative(K, ground_env, "real->exact", kreal_to_exact, 0);
-
- /* 12.6.6 with-strict-arithmetic, get-strict-arithmetic? */
- add_applicative(K, ground_env, "with-strict-arithmetic",
- kwith_strict_arithmetic, 0);
- add_applicative(K, ground_env, "get-strict-arithmetic?",
- kget_strict_arithmeticp, 0);
-
- /*
- ** 12.8 Rational features
- */
-
- /* 12.8.1 rational? */
- add_applicative(K, ground_env, "rational?", ftypep, 2, symbol,
- p2tv(krationalp));
-
- /* 12.8.2 / */
- add_applicative(K, ground_env, "/", kdivided, 0);
-
- /* 12.8.3 numerator, denominator */
- add_applicative(K, ground_env, "numerator", knumerator, 0);
- add_applicative(K, ground_env, "denominator", kdenominator, 0);
-
- /* 12.8.4 floor, ceiling, truncate, round */
- add_applicative(K, ground_env, "floor", kreal_to_integer, 2,
- symbol, i2tv((int32_t) K_FLOOR));
- add_applicative(K, ground_env, "ceiling", kreal_to_integer, 2,
- symbol, i2tv((int32_t) K_CEILING));
- add_applicative(K, ground_env, "truncate", kreal_to_integer, 2,
- symbol, i2tv((int32_t) K_TRUNCATE));
- add_applicative(K, ground_env, "round", kreal_to_integer, 2,
- symbol, i2tv((int32_t) K_ROUND_EVEN));
-
- /* 12.8.5 rationalize, simplest-rational */
- add_applicative(K, ground_env, "rationalize", krationalize, 0);
- add_applicative(K, ground_env, "simplest-rational", ksimplest_rational, 0);
-
- /*
- ** 12.9 Real features
- */
-
- /* 12.9.1 real? */
- add_applicative(K, ground_env, "real?", ftypep, 2, symbol,
- p2tv(krealp));
-
- /* 12.9.2 exp, log */
- add_applicative(K, ground_env, "exp", kexp, 0);
- add_applicative(K, ground_env, "log", klog, 0);
-
- /* 12.9.3 sin, cos, tan */
- add_applicative(K, ground_env, "sin", ktrig, 1, sin);
- add_applicative(K, ground_env, "cos", ktrig, 1, cos);
- add_applicative(K, ground_env, "tan", ktrig, 1, tan);
-
- /* 12.9.4 asin, acos, atan */
- add_applicative(K, ground_env, "asin", katrig, 1, asin);
- add_applicative(K, ground_env, "acos", katrig, 1, acos);
- add_applicative(K, ground_env, "atan", katan, 0);
-
- /* 12.9.5 sqrt */
- add_applicative(K, ground_env, "sqrt", ksqrt, 0);
-
- /* 12.9.6 expt */
- add_applicative(K, ground_env, "expt", kexpt, 0);
-
- /*
- **
- ** 13 Strings
- **
- */
-
- /*
- ** This section is still missing from the report. The bindings here are
- ** taken from r5rs scheme and should not be considered standard. They are
- ** provided in the meantime to allow programs to use string features
- ** (ASCII only).
- */
-
- /*
- ** 13.1 Primitive features
- */
-
- /* 13.1.1? string? */
- add_applicative(K, ground_env, "string?", typep, 2, symbol,
- i2tv(K_TSTRING));
-
- /* 13.1.2? make-string */
- add_applicative(K, ground_env, "make-string", make_string, 0);
-
- /* 13.1.3? string-length */
- add_applicative(K, ground_env, "string-length", string_length, 0);
-
- /* 13.1.4? string-ref */
- add_applicative(K, ground_env, "string-ref", string_ref, 0);
-
- /* 13.1.5? string-set! */
- add_applicative(K, ground_env, "string-set!", string_setS, 0);
-
- /*
- ** 13.2 Library features
- */
-
- /* 13.2.1? string */
- add_applicative(K, ground_env, "string", string, 0);
-
- /* 13.2.2? string=?, string-ci=? */
- add_applicative(K, ground_env, "string=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_eqp));
- add_applicative(K, ground_env, "string-ci=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ci_eqp));
-
- /* 13.2.3? string<?, string<=?, string>?, string>=? */
- add_applicative(K, ground_env, "string<?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ltp));
- add_applicative(K, ground_env, "string<=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_lep));
- add_applicative(K, ground_env, "string>?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_gtp));
- add_applicative(K, ground_env, "string>=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_gep));
-
- /* 13.2.4? string-ci<?, string-ci<=?, string-ci>?, string-ci>=? */
- add_applicative(K, ground_env, "string-ci<?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ci_ltp));
- add_applicative(K, ground_env, "string-ci<=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ci_lep));
- add_applicative(K, ground_env, "string-ci>?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ci_gtp));
- add_applicative(K, ground_env, "string-ci>=?", ftyped_bpredp, 3,
- symbol, p2tv(kstringp), p2tv(kstring_ci_gep));
-
- /* 13.2.5? substring */
- add_applicative(K, ground_env, "substring", substring, 0);
-
- /* 13.2.6? string-append */
- add_applicative(K, ground_env, "string-append", string_append, 0);
-
- /* 13.2.7? string->list, list->string */
- add_applicative(K, ground_env, "string->list", string_to_list, 0);
- add_applicative(K, ground_env, "list->string", list_to_string, 0);
-
- /* 13.2.8? string-copy */
- add_applicative(K, ground_env, "string-copy", string_copy, 0);
-
- /* 13.2.9? string->immutable-string */
- add_applicative(K, ground_env, "string->immutable-string",
- string_to_immutable_string, 0);
-
- /* TODO: add string-immutable? or general immutable? */
-
- /* 13.2.10? string-fill! */
- add_applicative(K, ground_env, "string-fill!", string_fillS, 0);
-
- /*
- ** 13.3 Symbol Features (this are from section symbol in r5rs)
- */
-
- /* 13.3.1? symbol->string */
- /* TEMP: for now all strings are mutable, this returns a new object
- each time */
- add_applicative(K, ground_env, "symbol->string", symbol_to_string, 0);
-
- /* 13.3.2? string->symbol */
- /* TEMP: for now this can create symbols with no external representation
- this includes all symbols with non identifiers characters.
- */
- /* NOTE:
- Symbols with uppercase alphabetic characters will write as lowercase and
- so, when read again will not compare as either eq? or equal?. This is ok
- because the report only says that read objects when written and read
- again must be equal? which happens here
- */
- add_applicative(K, ground_env, "string->symbol", string_to_symbol, 0);
-
-
- /*
- **
- ** 14 Characters
- **
- */
-
- /*
- ** This section is still missing from the report. The bindings here are
- ** taken from r5rs scheme and should not be considered standard. They are
- ** provided in the meantime to allow programs to use character features
- ** (ASCII only).
- */
-
- /*
- ** 14.1 Primitive features
- */
-
- /* 14.1.1? char? */
- add_applicative(K, ground_env, "char?", typep, 2, symbol,
- i2tv(K_TCHAR));
-
- /* 14.1.2? char-alphabetic?, char-numeric?, char-whitespace? */
- /* unlike in r5rs these take an arbitrary number of chars
- (even cyclical list) */
- add_applicative(K, ground_env, "char-alphabetic?", ftyped_predp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_alphabeticp));
- add_applicative(K, ground_env, "char-numeric?", ftyped_predp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_numericp));
- add_applicative(K, ground_env, "char-whitespace?", ftyped_predp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_whitespacep));
-
- /* 14.1.3? char-upper-case?, char-lower-case? */
- /* unlike in r5rs these take an arbitrary number of chars
- (even cyclical list) */
- add_applicative(K, ground_env, "char-upper-case?", ftyped_predp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_upper_casep));
- add_applicative(K, ground_env, "char-lower-case?", ftyped_predp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_lower_casep));
-
-
- /* 14.1.4? char->integer, integer->char */
- add_applicative(K, ground_env, "char->integer", kchar_to_integer, 0);
- add_applicative(K, ground_env, "integer->char", kinteger_to_char, 0);
-
- /* 14.1.4? char-upcase, char-downcase */
- add_applicative(K, ground_env, "char-upcase", kchar_upcase, 0);
- add_applicative(K, ground_env, "char-downcase", kchar_downcase, 0);
-
- /*
- ** 14.2 Library features
- */
-
- /* 14.2.1? char=? */
- add_applicative(K, ground_env, "char=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_eqp));
-
- /* 14.2.2? char<?, char<=?, char>?, char>=? */
- add_applicative(K, ground_env, "char<?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ltp));
- add_applicative(K, ground_env, "char<=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_lep));
- add_applicative(K, ground_env, "char>?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_gtp));
- add_applicative(K, ground_env, "char>=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_gep));
-
- /* 14.2.3? char-ci=? */
- add_applicative(K, ground_env, "char-ci=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ci_eqp));
-
- /* 14.2.4? char-ci<?, char-ci<=?, char-ci>?, char-ci>=? */
- add_applicative(K, ground_env, "char-ci<?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ci_ltp));
- add_applicative(K, ground_env, "char-ci<=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ci_lep));
- add_applicative(K, ground_env, "char-ci>?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ci_gtp));
- add_applicative(K, ground_env, "char-ci>=?", ftyped_bpredp, 3,
- symbol, p2tv(kcharp), p2tv(kchar_ci_gep));
-
- /*
- **
- ** 15 Ports
- **
- */
-
- /*
- ** 15.1 Primitive features
- */
-
- /* 15.1.1 port? */
- add_applicative(K, ground_env, "port?", typep, 2, symbol,
- i2tv(K_TPORT));
-
- /* 15.1.2 input-port?, output-port? */
- add_applicative(K, ground_env, "input-port?", ftypep, 2, symbol,
- p2tv(kis_input_port));
-
- add_applicative(K, ground_env, "output-port?", ftypep, 2, symbol,
- p2tv(kis_output_port));
-
- /* 15.1.3 with-input-from-file, with-ouput-to-file */
- add_applicative(K, ground_env, "with-input-from-file", with_file,
- 3, symbol, b2tv(false), K->kd_in_port_key);
- add_applicative(K, ground_env, "with-output-to-file", with_file,
- 3, symbol, b2tv(true), K->kd_out_port_key);
-
- /* 15.1.4 get-current-input-port, get-current-output-port */
- add_applicative(K, ground_env, "get-current-input-port", get_current_port,
- 2, symbol, K->kd_in_port_key);
- add_applicative(K, ground_env, "get-current-output-port", get_current_port,
- 2, symbol, K->kd_out_port_key);
-
- /* 15.1.5 open-input-file, open-output-file */
- add_applicative(K, ground_env, "open-input-file", open_file, 2, symbol,
- b2tv(false));
-
- add_applicative(K, ground_env, "open-output-file", open_file, 2, symbol,
- b2tv(true));
-
- /* 15.1.6 close-input-file, close-output-file */
- /* ASK John: should this be called close-input-port & close-ouput-port
- like in r5rs? that doesn't seem consistent with open thou */
- add_applicative(K, ground_env, "close-input-file", close_file, 2, symbol,
- b2tv(false));
-
- add_applicative(K, ground_env, "close-output-file", close_file, 2, symbol,
- b2tv(true));
-
- /* 15.1.7 read */
- add_applicative(K, ground_env, "read", read, 0);
-
- /* 15.1.8 write */
- add_applicative(K, ground_env, "write", write, 0);
-
- /*
- ** These are from scheme (r5rs)
- */
-
- /* 15.1.? eof-object? */
- add_applicative(K, ground_env, "eof-object?", typep, 2, symbol,
- i2tv(K_TEOF));
-
- /* 15.1.? newline */
- add_applicative(K, ground_env, "newline", newline, 0);
-
- /* 15.1.? write-char */
- add_applicative(K, ground_env, "write-char", write_char, 0);
-
- /* 15.1.? read-char */
- add_applicative(K, ground_env, "read-char", read_peek_char, 2, symbol,
- b2tv(false));
-
- /* 15.1.? peek-char */
- add_applicative(K, ground_env, "peek-char", read_peek_char, 2, symbol,
- b2tv(true));
-
- /* 15.1.? char-ready? */
- /* XXX: this always return #t, proper behaviour requires platform
- specific code (probably select for posix, a thread for windows
- (at least for files & consoles), I think pipes and sockets may
- have something */
- add_applicative(K, ground_env, "char-ready?", char_readyp, 0);
-
- /*
- ** 15.2 Library features
- */
-
- /* 15.2.1 call-with-input-file, call-with-output-file */
- add_applicative(K, ground_env, "call-with-input-file", call_with_file,
- 2, symbol, b2tv(false));
- add_applicative(K, ground_env, "call-with-output-file", call_with_file,
- 2, symbol, b2tv(true));
-
- /* 15.2.2 load */
- add_applicative(K, ground_env, "load", load, 0);
-
- /* 15.2.3 get-module */
- add_applicative(K, ground_env, "get-module", get_module, 0);
-
- /* 15.2.? display */
- add_applicative(K, ground_env, "display", display, 0);
-
- /* MAYBE: That's all there is in the report combined with r5rs scheme,
- but we will probably need: file-exists?, rename-file and remove-file.
- It would also be good to be able to select between append, truncate and
- error if a file exists, but that would need to be an option in all three
- methods of opening. Also some directory checking, traversing etc */
-
+ ** Initialize the combiners/vars for all supported modules
+ */
+ kinit_booleans_ground_env(K);
+ kinit_eqp_ground_env(K);
+ kinit_equalp_ground_env(K);
+ kinit_symbols_ground_env(K);
+ kinit_control_ground_env(K);
+ kinit_pairs_lists_ground_env(K);
+ kinit_pair_mut_ground_env(K);
+ kinit_environments_ground_env(K);
+ kinit_env_mut_ground_env(K);
+ kinit_combiners_ground_env(K);
+ kinit_continuations_ground_env(K);
+ kinit_encapsulations_ground_env(K);
+ kinit_promises_ground_env(K);
+ kinit_kgkd_vars_ground_env(K);
+ kinit_kgks_vars_ground_env(K);
+ kinit_numbers_ground_env(K);
+ kinit_strings_ground_env(K);
+ kinit_chars_ground_env(K);
+ kinit_ports_ground_env(K);
+
+ /*
+ ** Initialize the names of the continuation used in
+ ** the supported modules to aid in debugging/error msgs
+ */
+ /* MAYBE some/most/all of these could be done in each module */
kinit_cont_names(K);
-
- return;
}
diff --git a/src/kgstrings.c b/src/kgstrings.c
@@ -420,37 +420,70 @@ void string_fillS(klisp_State *K, TValue *xparams, TValue ptree, TValue denv)
kapply_cc(K, KINERT);
}
-
-/* 13.3.1? symbol->string */
-/* The strings in symbols are immutable so we can just return that */
-void symbol_to_string(klisp_State *K, TValue *xparams, TValue ptree,
- TValue denv)
+/* init ground */
+void kinit_strings_ground_env(klisp_State *K)
{
- UNUSED(xparams);
- UNUSED(denv);
- bind_1tp(K, ptree, "symbol", ttissymbol, sym);
- TValue str = ksymbol_str(sym);
- kapply_cc(K, str);
-}
-
-/* 13.3.2? string->symbol */
-/* TEMP: for now this can create symbols with no external representation
- this includes all symbols with non identifiers characters.
-*/
-/* NOTE:
- Symbols with uppercase alphabetic characters will write as lowercase and
- so, when read again will not compare as either eq? or equal?. This is ok
- because the report only says that read objects when written and read
- again must be equal? which happens here
-*/
-/* If the string is mutable it is copied */
-void string_to_symbol(klisp_State *K, TValue *xparams, TValue ptree,
- TValue denv)
-{
- UNUSED(xparams);
- UNUSED(denv);
- bind_1tp(K, ptree, "string", ttisstring, str);
- /* TODO si */
- TValue new_sym = ksymbol_new_check_i(K, str, KNIL);
- kapply_cc(K, new_sym);
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /*
+ ** This section is still missing from the report. The bindings here are
+ ** taken from r5rs scheme and should not be considered standard. They are
+ ** provided in the meantime to allow programs to use string features
+ ** (ASCII only).
+ */
+
+ /* 13.1.1? string? */
+ add_applicative(K, ground_env, "string?", typep, 2, symbol,
+ i2tv(K_TSTRING));
+ /* 13.1.2? make-string */
+ add_applicative(K, ground_env, "make-string", make_string, 0);
+ /* 13.1.3? string-length */
+ add_applicative(K, ground_env, "string-length", string_length, 0);
+ /* 13.1.4? string-ref */
+ add_applicative(K, ground_env, "string-ref", string_ref, 0);
+ /* 13.1.5? string-set! */
+ add_applicative(K, ground_env, "string-set!", string_setS, 0);
+ /* 13.2.1? string */
+ add_applicative(K, ground_env, "string", string, 0);
+ /* 13.2.2? string=?, string-ci=? */
+ add_applicative(K, ground_env, "string=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_eqp));
+ add_applicative(K, ground_env, "string-ci=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ci_eqp));
+ /* 13.2.3? string<?, string<=?, string>?, string>=? */
+ add_applicative(K, ground_env, "string<?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ltp));
+ add_applicative(K, ground_env, "string<=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_lep));
+ add_applicative(K, ground_env, "string>?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_gtp));
+ add_applicative(K, ground_env, "string>=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_gep));
+ /* 13.2.4? string-ci<?, string-ci<=?, string-ci>?, string-ci>=? */
+ add_applicative(K, ground_env, "string-ci<?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ci_ltp));
+ add_applicative(K, ground_env, "string-ci<=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ci_lep));
+ add_applicative(K, ground_env, "string-ci>?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ci_gtp));
+ add_applicative(K, ground_env, "string-ci>=?", ftyped_bpredp, 3,
+ symbol, p2tv(kstringp), p2tv(kstring_ci_gep));
+ /* 13.2.5? substring */
+ add_applicative(K, ground_env, "substring", substring, 0);
+ /* 13.2.6? string-append */
+ add_applicative(K, ground_env, "string-append", string_append, 0);
+ /* 13.2.7? string->list, list->string */
+ add_applicative(K, ground_env, "string->list", string_to_list, 0);
+ add_applicative(K, ground_env, "list->string", list_to_string, 0);
+ /* 13.2.8? string-copy */
+ add_applicative(K, ground_env, "string-copy", string_copy, 0);
+ /* 13.2.9? string->immutable-string */
+ add_applicative(K, ground_env, "string->immutable-string",
+ string_to_immutable_string, 0);
+
+ /* TODO: add string-immutable? or general immutable? */
+
+ /* 13.2.10? string-fill! */
+ add_applicative(K, ground_env, "string-fill!", string_fillS, 0);
}
diff --git a/src/kgstrings.h b/src/kgstrings.h
@@ -85,24 +85,10 @@ void string_to_immutable_string(klisp_State *K, TValue *xparams,
/* 13.2.10? string-fill! */
void string_fillS(klisp_State *K, TValue *xparams, TValue ptree, TValue denv);
-/* 13.3.1? symbol->string */
-void symbol_to_string(klisp_State *K, TValue *xparams, TValue ptree,
- TValue denv);
-
-/* 13.3.2? string->symbol */
-/* TEMP: for now this can create symbols with no external representation
- this includes all symbols with non identifiers characters.
-*/
-/* NOTE:
- Symbols with uppercase alphabetic characters will write as lowercase and
- so, when read again will not compare as either eq? or equal?. This is ok
- because the report only says that read objects when written and read
- again must be equal? which happens here
-*/
-void string_to_symbol(klisp_State *K, TValue *xparams, TValue ptree,
- TValue denv);
-
/* Helpers */
bool kstringp(TValue obj);
+/* init ground */
+void kinit_strings_ground_env(klisp_State *K);
+
#endif
diff --git a/src/kgsymbols.c b/src/kgsymbols.c
@@ -24,3 +24,65 @@
/* 4.4.1 symbol? */
/* uses typep */
+
+/* 13.3.1? symbol->string */
+/* The strings in symbols are immutable so we can just return that */
+void symbol_to_string(klisp_State *K, TValue *xparams, TValue ptree,
+ TValue denv)
+{
+ UNUSED(xparams);
+ UNUSED(denv);
+ bind_1tp(K, ptree, "symbol", ttissymbol, sym);
+ TValue str = ksymbol_str(sym);
+ kapply_cc(K, str);
+}
+
+/* 13.3.2? string->symbol */
+/* TEMP: for now this can create symbols with no external representation
+ this includes all symbols with non identifiers characters.
+*/
+/* NOTE:
+ Symbols with uppercase alphabetic characters will write as lowercase and
+ so, when read again will not compare as either eq? or equal?. This is ok
+ because the report only says that read objects when written and read
+ again must be equal? which happens here
+*/
+/* If the string is mutable it is copied */
+void string_to_symbol(klisp_State *K, TValue *xparams, TValue ptree,
+ TValue denv)
+{
+ UNUSED(xparams);
+ UNUSED(denv);
+ bind_1tp(K, ptree, "string", ttisstring, str);
+ /* TODO si */
+ TValue new_sym = ksymbol_new_check_i(K, str, KNIL);
+ kapply_cc(K, new_sym);
+}
+
+/* init ground */
+void kinit_symbols_ground_env(klisp_State *K)
+{
+ TValue ground_env = K->ground_env;
+ TValue symbol, value;
+
+ /* 4.4.1 symbol? */
+ add_applicative(K, ground_env, "symbol?", typep, 2, symbol,
+ i2tv(K_TSYMBOL));
+ /*
+ ** This section is still missing from the report. The bindings here are
+ ** taken from r5rs scheme and should not be considered standard.
+ */
+ /* ?.?.1? symbol->string */
+ add_applicative(K, ground_env, "symbol->string", symbol_to_string, 0);
+ /* ?.?.2? string->symbol */
+ /* TEMP: for now this can create symbols with no external representation
+ this includes all symbols with non identifiers characters.
+ */
+ /* NOTE:
+ Symbols with uppercase alphabetic characters will write as lowercase and
+ so, when read again will not compare as either eq? or equal?. This is ok
+ because the report only says that read objects when written and read
+ again must be equal? which happens here
+ */
+ add_applicative(K, ground_env, "string->symbol", string_to_symbol, 0);
+}
diff --git a/src/kgsymbols.h b/src/kgsymbols.h
@@ -21,4 +21,24 @@
/* 4.4.1 symbol? */
/* uses typep */
+/* ?.?.1? symbol->string */
+void symbol_to_string(klisp_State *K, TValue *xparams, TValue ptree,
+ TValue denv);
+
+/* ?.?.2? string->symbol */
+/* TEMP: for now this can create symbols with no external representation
+ this includes all symbols with non identifiers characters.
+*/
+/* NOTE:
+ Symbols with uppercase alphabetic characters will write as lowercase and
+ so, when read again will not compare as either eq? or equal?. This is ok
+ because the report only says that read objects when written and read
+ again must be equal? which happens here
+*/
+void string_to_symbol(klisp_State *K, TValue *xparams, TValue ptree,
+ TValue denv);
+
+/* init ground */
+void kinit_symbols_ground_env(klisp_State *K);
+
#endif
diff --git a/src/klisp.h b/src/klisp.h
@@ -41,6 +41,7 @@ void klisp_close (klisp_State *K);
* Copyright (C) 2011 Andres Navarro. All rights reserved.
* Lua parts: Copyright (C) 1994-2010 Lua.org, PUC-Rio. All rights reserved.
* IMath Parts: Copyright (C) 2002-2007 Michael J. Fromberger.
+* srfi-78: Copyright (C) 2005-2006 Sebastian Egner.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
diff --git a/src/klispconf.h b/src/klispconf.h
@@ -53,3 +53,30 @@
** change this value dynamically.
*/
#define KLISPI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
+
+/*
+@@ KLISP_API is a mark for all core API functions.
+@@ KLISPLIB_API is a mark for all standard library functions.
+** CHANGE them if you need to define those functions in some special way.
+** For instance, if you want to create one Windows DLL with the core and
+** the libraries, you may want to use the following definition (define
+** KLISP_BUILD_AS_DLL to get it).
+*/
+#if defined(KLISP_BUILD_AS_DLL)
+
+#if defined(KLISP_CORE) || defined(KLISP_LIB)
+#define KLISP_API __declspec(dllexport)
+#else
+#define KLISP_API __declspec(dllimport)
+#endif
+
+#else
+
+#define KLISP_API extern
+
+#endif
+
+/* more often than not the libs go together with the core */
+#define KLISPLIB_API KLISP_API
+
+/* TODO: add klisp_core/lib defines... see lua */
diff --git a/src/kport.c b/src/kport.c
@@ -15,7 +15,7 @@
#include "kstring.h"
#include "kgc.h"
-/* XXX: per the c spec, this truncates the file if it extists! */
+/* XXX: per the c spec, this truncates the file if it exists! */
/* Ask John: what would be best? Probably should also include delete,
file-exists? and a mechanism to truncate or append to a file, or
throw error if it exists.
diff --git a/src/tests/booleans.k b/src/tests/booleans.k
@@ -0,0 +1,123 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; boolean?
+($check-predicate (applicative? boolean?))
+($check-predicate (boolean?))
+($check-predicate (boolean? #t))
+($check-predicate (boolean? #f))
+($check-predicate (boolean? #t #t #f #f))
+($check-predicate (boolean? #f . #0=(#t . #0#)))
+
+($check-not-predicate (boolean? ((unwrap list) . symbol)))
+($check-not-predicate (boolean? ()))
+($check-not-predicate (boolean? (cons () ())))
+($check-not-predicate (boolean? #ignore))
+($check-not-predicate (boolean? (make-environment)))
+($check-not-predicate (boolean? #inert))
+($check-not-predicate (boolean? $vau))
+($check-not-predicate (boolean? wrap))
+($check-not-predicate (boolean? (call/cc ($lambda (c) c))))
+($check-not-predicate (boolean? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (boolean? (memoize #inert)))
+($check-not-predicate (boolean? 1))
+($check-not-predicate (boolean? -1/2))
+($check-not-predicate (boolean? 1.0))
+($check-not-predicate (boolean? #e+infinity))
+($check-not-predicate (boolean? #i+infinity))
+($check-not-predicate (boolean? #undefined))
+($check-not-predicate (boolean? #real))
+($check-not-predicate (boolean? "string"))
+($check-not-predicate (boolean? #\a))
+($check-not-predicate (boolean? (get-current-input-port)))
+
+;; basic eq?-ness and not?
+($check-predicate (applicative? not?))
+
+($check eq? #t #t)
+($check eq? #f #f)
+($check not-eq? #t #f)
+($check not-eq? #f #t)
+($check eq? (not? #t) #f)
+($check eq? (not? #f) #t)
+
+;; basic equal?-ness and not?
+($check equal? #t #t)
+($check equal? #f #f)
+($check not-equal? #t #f)
+($check not-equal? #f #t)
+($check equal? (not? #t) #f)
+($check equal? (not? #f) #t)
+
+;; and? & or?
+($check-predicate (applicative? and?))
+($check-predicate (and?))
+($check-predicate (and? #t))
+($check-predicate (and? #t #t))
+($check-predicate (and? #t #t #t))
+($check-predicate (and? #t . #0=(#t . #0#)))
+($check-not-predicate (and? #f))
+($check-not-predicate (and? #t #t #f))
+
+($check-predicate (applicative? or?))
+($check-predicate (or? #t))
+($check-predicate (or? #f #t))
+($check-predicate (or? #f #f #t))
+($check-predicate (or? #f . #0=(#t . #0#)))
+($check-not-predicate (or?))
+($check-not-predicate (or? #f))
+($check-not-predicate (or? #f #f #f))
+
+;; $and? & $or?
+;; TODO check tail call
+($check-predicate (operative? $and?))
+($check-predicate ($and?))
+($check-predicate ($and? #t))
+($check-predicate ($and? (eq? #t #t) #t)) ;; test some evaluation too!
+($check-predicate ($and? #t (eq? #f #f) #t))
+($check-not-predicate ($and? #t . #0=((eq? #t #f) . #0#)))
+($check-not-predicate ($and? #f))
+($check-not-predicate ($and? #t #t #f))
+($check-not-predicate ($and? #f (/ 1 0))) ;; test conditional evaluation
+
+($check-predicate (operative? $or?))
+($check-predicate ($or? #t))
+($check-predicate ($or? #f (eq? #t #t) #t)) ;; test some evaluation too!
+($check-predicate ($or? #f #f #t))
+($check-predicate ($or? #t (/ 1 0)))
+($check-predicate ($or? #f . #0=(#t . #0#)))
+($check-not-predicate ($or? #f))
+($check-not-predicate ($or?))
+
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; boolean?
+($check-error (boolean? #t . #f))
+
+;; not?
+($check-error (not?))
+($check-error (not? 1))
+($check-error (not? #inert))
+($check-error (not? #t #f))
+
+;; and? & or?
+($check-error (and? #t #f 0))
+($check-error (or? #f #t 0))
+($check-error (and? #t . #f))
+
+;; $and? & $or?
+($check-error ($and? #t 0 #t))
+($check-error ($or? #f 0 #f))
+
+;; check boolean in last operand
+($check-error ($and? #t 0))
+($check-error ($or? #f 0))
+
diff --git a/src/tests/check.k b/src/tests/check.k
@@ -0,0 +1,408 @@
+;;; Simple test framework based on srfi-78
+;;;
+;;; See Copyright Notice in klisp.h
+;;;
+;;; SOURCE NOTE: Based on the reference implementation by Sebastian Egner
+;;;
+;;; TEMP: No eager comprehension for now
+;;; XXX: modes are encapsulated values instead of symbols, it could also
+;;; be done with a $check-set-mode! operative, or with keyword objects
+;;; it they were implemented.
+;;;
+;;;
+
+;; TODO refactor out some of the code in $check, $check-error, and the -ec
+;; variants, there is too much duplication and the applicatives are a bit
+;; too long.
+($provide!
+ ($check $check-error check-report check-reset! check-set-mode!
+ check-passed? check-mode-off check-mode-summary
+ check-mode-report-failed check-mode-report)
+ ;; PRIVATE
+
+ ;; STATE
+
+ ;; internal count
+ ($define! passed 0)
+ ($define! failed 0)
+ ($define! first-failed #inert) ;; form: (error? . extra-data)
+ ;; no error: (#f exp actual expected)
+ ;; error: (#t string exp error)
+ ;; failed = 0 => first-failed = #inert
+
+ ;; initial state: report-failed (states are off summary report-failed and
+ ;; report)
+ ($define! report-on? #t) ; #t except in all states except: off
+ ($define! report-fail? #t) ; #t in states: report-failed and report
+ ($define! report-pass? #f) ; #t in state: report
+
+ ;; encapsulation for mode parameter
+ ($define! (enc-mode mode? get-mode-params) (make-encapsulation-type))
+ ;; /STATE
+
+ ;; little helper for error catching
+ ;; This evaluates expression in the dynamic environment
+ ;; If no error occurs it returs #t
+ ;; If an there is an error, the handler applicative is called
+ ;; in the dynamic environment with the object passed to the error
+ ;; continuation as sole argument
+ ($define! $without-error?
+ ($vau (exp handler) denv
+ (guard-dynamic-extent
+ ()
+ ($lambda ()
+ (eval exp denv)
+ #t)
+ (list (list error-continuation
+ ($lambda (error-obj divert)
+ (apply (eval handler denv)
+ (list error-obj) denv)
+ (apply divert #f)))))))
+
+ ;; ;; another way to do the same: return a pair of (error? result/error-obj)
+ ;; ;; but it is difficult to use because it starts nesting (see $check)
+ ;; ($define! $try
+ ;; ($vau (exp) denv
+ ;; (guard-dynamic-extent
+ ;; ()
+ ;; ($lambda ()
+ ;; (list #t (eval exp denv))
+ ;; (list (list error-continuation
+ ;; ($lambda (error-obj divert)
+ ;; (apply divert (list #f error-obj)))))))))
+
+
+
+ ($define! check-passed!
+ ($let ((env (get-current-environment)))
+ ($lambda ()
+ ($set! env passed (+ passed 1)))))
+
+ ($define! check-failed/expected!
+ ($let ((env (get-current-environment)))
+ ($lambda ls
+ ($if (zero? failed)
+ ($set! env first-failed (cons #f ls))
+ #inert)
+ ($set! env failed (+ failed 1)))))
+
+ ($define! check-failed/error!
+ ($let ((env (get-current-environment)))
+ ($lambda ls
+ ($if (zero? failed)
+ ($set! env first-failed (cons #t ls))
+ #inert)
+ ($set! env failed (+ failed 1)))))
+
+ ($define! describe-passed
+ ($lambda (exp actual)
+ (show-exp exp)
+ (show-res actual)
+ (show-passed 1)))
+
+ ($define! describe-failed
+ ($lambda (exp actual expected)
+ (show-exp exp)
+ (show-res actual)
+ (show-failed expected)))
+
+ ($define! describe-error
+ ($lambda (str exp err-obj)
+ (display str)
+ (show-exp exp)
+ (show-error err-obj)))
+
+ ($define! describe-first-failed
+ ($lambda ()
+ ($if (not? (zero? failed))
+ ($let (((error? . extra-data) first-failed))
+ (apply ($if error?
+ describe-error
+ describe-failed)
+ extra-data))
+ #inert)))
+
+ ;; show applicatives
+ ($define! show-exp
+ ($lambda (exp)
+ (write exp)
+ (display " => ")))
+
+ ($define! show-res
+ ($lambda (res)
+ (write res)))
+
+ ($define! show-passed
+ ($lambda (cases)
+ (display "; *** passed ")
+ ($if (not? (=? cases 1))
+ ($sequence (display "(")
+ (display cases)
+ (display " cases)"))
+ #inert)
+ (display "***")
+ (newline)))
+
+ ($define! show-failed
+ ($lambda (expected)
+ (display "; *** failed ***")
+ (newline)
+ (display " ; expected result: ")
+ (write expected)
+ (newline)))
+
+ ($define! show-error
+ ($lambda (err-obj)
+ (display "; *** error ***")
+ (newline)
+ (display "; error object: ")
+ (write err-obj)
+ (newline)))
+ ;; /PRIVATE
+
+ ;; PUBLIC
+
+ ;; general check facility. It always take an equality predicate
+ ;; needs to be operative to save the original expression
+ ($define! $check
+ ($let ((handler (wrap ($vau (error-obj) denv
+ ($set! denv error-obj error-obj)))))
+ ($vau (test? exp expected) denv
+ ($cond ((not? report-on?) #inert)
+ ((not? ($without-error? ($define! test? (eval test? denv))
+ handler))
+ ($let ((error-ls
+ (list "error evaling test? applicative: " test?
+ error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)))
+ ((not? ($without-error? ($define! expected (eval expected denv))
+ handler))
+ ($let ((error-ls
+ (list "error evaling expected value: " expected
+ error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)))
+ ((not? ($without-error? ($define! res (eval exp denv)) handler))
+ ($let ((error-ls
+ (list "error evaling expression: " exp error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)))
+ ((not? ($without-error? ($define! test-result
+ (apply test? (list res expected)))
+ handler)) ;; no dyn env here
+ ($let ((error-ls
+ (list "error evaling (test? exp expected): "
+ (list test? exp expected) error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)))
+ (test-result
+ (check-passed!)
+ ($if report-pass? (describe-passed exp res) #inert))
+ (#t ; test-result = #f
+ (check-failed/expected! exp res expected)
+ ($if report-fail? (describe-failed exp res expected)
+ #inert))))))
+
+;; XXX /work in progress
+
+ ;; helpers
+ ($define! $check-ec-helper
+ ($vau (test?-exp exp expected-exp escape/c) denv
+ ;; TODO, add argument-list for errors
+ ($cond ((not? ($without-error? ($define! test? (eval test? denv))
+ handler))
+ ($let ((error-ls
+ (list "error evaling test? applicative: " test?
+ error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)
+ (apply-continuation escape/c #inert)))
+ ((not? ($without-error? ($define! expected (eval expected denv))
+ handler))
+ ($let ((error-ls
+ (list "error evaling expected value: " expected
+ error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)
+ (apply-continuation escape/c #inert)
+ ))
+ ((not? ($without-error? ($define! res (eval exp denv)) handler))
+ ($let ((error-ls
+ (list "error evaling expression: " exp error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)
+ (apply-continuation escape/c #inert)))
+ ((not? ($without-error? ($define! test-result
+ (apply test? (list res expected)))
+ handler)) ;; no dyn env here
+ ($let ((error-ls
+ (list "error evaling (test? exp expected): "
+ (list test? exp expected) error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)
+ (apply-continuation escape/c #inert)))
+ (test-result
+ ; (check-passed!) passed only after all passed
+ ; ($if report-pass? (describe-passed exp res) #inert))
+ #inert
+ (#t ; test-result = #f
+ (check-failed/expected! exp res expected)
+ ($if report-fail? (describe-failed exp res expected) #inert)
+ (apply-continuation escape/c #inert))))))
+
+ ($define! $check-ec
+ ($let ((handler (wrap ($vau (error-obj) denv
+ ($set! denv error-obj error-obj)))))
+ ($vau (gens test? exp expected . maybe-arg-list) denv
+ ;; TODO add check
+ ($define! arg-list ($if (null? maybe-arg-list)
+ ()
+ (car maybe-arg-list)))
+ ($cond ((not? report-on?) #inert)
+ ((not? ($without-error? ($define! gen (eval (cons $nested-ec
+ gens)
+ denv)) handler))
+ ($let ((error-ls
+ (list "error evaling qualifiers: " gens error-obj)))
+ (apply check-failed/error! error-ls)
+ ($if report-fail?
+ (apply describe-error error-ls)
+ #inert)))
+ (($let/cc escape/c
+ ;; TODO add some security to the continuation
+ ;; (like make it one-shot and/or avoid reentry)
+ (eval (list do-ec (list gen)
+ (list check-ec-helper
+ test?-exp exp expected-exp
+ escape/c)))
+ #t)
+ ;; ... TODO passed with n cases
+ (check-passed!)
+ ($if report-pass? (describe-passed exp res) #inert)
+ )
+ (#t ;; TODO didn't pass...
+ #inert
+ )))))
+
+;; XXX /work in progress
+
+ ;; Check that the given expression throws an error
+ ;; needs to be operative to save the original expression
+ ;; (not in the srfi, probably because of poor specification of error
+ ;; signaling in R5RS
+ ;; but very useful for checking proper argument checking)
+ ($define! $check-error
+ ($let ((handler (wrap ($vau (error-obj) denv
+ ($set! denv error-obj error-obj)))))
+ ($vau (exp) denv
+ ($cond ((not? report-on?) #inert)
+ (($without-error? ($define! result
+ (eval exp denv)) handler)
+ ($let ((error-ls
+ (list exp result "<ERROR>")))
+ (apply check-failed/expected! error-ls)
+ ($if report-fail?
+ (apply describe-failed error-ls)
+ #inert)))
+ (#t ;; didn't throw error
+ (check-passed!)
+ ($if report-pass?
+ (describe-passed exp error-obj)
+ #inert))))))
+
+ ($define! check-report
+ ($lambda ()
+ ($if report-on?
+ ($sequence
+ (display "Tests Passed: ")
+ (write passed)
+ (newline)
+ (display "Tests Failed: ")
+ (write failed)
+ (newline)
+ (display "Tests Total: ")
+ (write (+ failed passed))
+ (newline)
+ (describe-first-failed))
+ #inert))) ;; state: off don't show anything
+
+
+ ;; the modes are an encapsulated object each of
+ ;; '(off summary report-failed report)
+ ;; is an ecapsulated list of their effect on state variables
+ ;; (report-on? report-error? report-pass?)
+ ($define! check-mode-off (enc-mode (list #f #f #f)))
+ ($define! check-mode-summary (enc-mode (list #t #f #f)))
+ ($define! check-mode-report-failed (enc-mode (list #t #t #f)))
+ ($define! check-mode-report (enc-mode (list #t #t #t)))
+
+ ($define! check-set-mode!
+ ($let ((env (get-current-environment)))
+ ($lambda (mode)
+ ($if (mode? mode)
+ ($set! env
+ (report-on? report-error? report-pass?)
+ (get-mode-params mode))
+ (#t (error "$check-set-mode: invalid mode"))))))
+
+ ($define! check-reset!
+ ($let ((env (get-current-environment)))
+ ($lambda ()
+ ($set! env passed 0)
+ ($set! env failed 0)
+ ($set! env first-failed #inert))))
+
+ ($define! check-passed?
+ ($lambda (expected)
+ (and? (zero? failed)
+ (=? passed expected)))))
+;; /PUBLIC
+
+
+;; I drawed freely from the reference implementation so here is the
+;; copyright notice:
+
+;;
+;; Permission is hereby granted, free of charge, to any person obtaining
+;; a copy of this software and associated documentation files (the
+;; ``Software''), to deal in the Software without restriction, including
+;; without limitation the rights to use, copy, modify, merge, publish,
+;; distribute, sublicense, and/or sell copies of the Software, and to
+;; permit persons to whom the Software is furnished to do so, subject to
+;; the following conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+;;
+;; -----------------------------------------------------------------------
+;;
+;; Lightweight testing (reference implementation)
+;; ==============================================
+;;
+;; Sebastian.Egner@philips.com
+
diff --git a/src/tests/combiners.k b/src/tests/combiners.k
@@ -0,0 +1,320 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; operative?, applicative? & combiner?
+($check-predicate (applicative? operative?))
+($check-predicate (applicative? applicative?))
+($check-predicate (applicative? combiner?))
+
+($check-predicate (operative?))
+($check-predicate (operative? $if $vau $lambda))
+($check-predicate (operative? $cond . #0=($sequence . #0#)))
+
+($check-predicate (applicative?))
+($check-predicate (applicative? applicative? operative? combiner?))
+($check-predicate (applicative? wrap . #0=(unwrap . #0#)))
+
+($check-predicate (combiner?))
+($check-predicate (combiner? $if $vau $lambda))
+($check-predicate (combiner? $cond . #0=($sequence . #0#)))
+($check-predicate (combiner?))
+($check-predicate (combiner? applicative? operative? combiner?))
+($check-predicate (combiner? wrap . #0=(unwrap . #0#)))
+
+($check-not-predicate (operative? #t))
+($check-not-predicate (operative? #f))
+($check-not-predicate (operative? ((unwrap list) . symbol)))
+($check-not-predicate (operative? ()))
+($check-not-predicate (operative? (cons () ())))
+($check-not-predicate (operative? #ignore))
+($check-not-predicate (operative? (make-environment)))
+($check-not-predicate (operative? #inert))
+($check-not-predicate (operative? wrap))
+($check-not-predicate (operative? (call/cc ($lambda (c) c))))
+($check-not-predicate (operative? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (operative? (memoize #inert)))
+($check-not-predicate (operative? 1))
+;($check-not-predicate (operative? 1.0))
+($check-not-predicate (operative? #e+infinity))
+;($check-not-predicate (operative? #i+infinity))
+;($check-not-predicate (operative? #undefined))
+;($check-not-predicate (operative? #real-with-no-primary-value))
+($check-not-predicate (operative? "string"))
+($check-not-predicate (operative? #\a))
+($check-not-predicate (operative? (get-current-input-port)))
+
+($check-not-predicate (applicative? #t))
+($check-not-predicate (applicative? #f))
+($check-not-predicate (applicative? ((unwrap list) . symbol)))
+($check-not-predicate (applicative? ()))
+($check-not-predicate (applicative? (cons () ())))
+($check-not-predicate (applicative? #ignore))
+($check-not-predicate (applicative? (make-environment)))
+($check-not-predicate (applicative? #inert))
+($check-not-predicate (applicative? $vau))
+($check-not-predicate (applicative? (call/cc ($lambda (c) c))))
+($check-not-predicate (applicative? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (applicative? (memoize #inert)))
+($check-not-predicate (applicative? 1))
+;($check-not-predicate (applicative? 1.0))
+($check-not-predicate (applicative? #e+infinity))
+;($check-not-predicate (applicative? #i+infinity))
+;($check-not-predicate (applicative? #undefined))
+;($check-not-predicate (applicative? #real-with-no-primary-value))
+($check-not-predicate (applicative? "string"))
+($check-not-predicate (applicative? #\a))
+($check-not-predicate (applicative? (get-current-input-port)))
+
+($check-not-predicate (combiner? #t))
+($check-not-predicate (combiner? #f))
+($check-not-predicate (combiner? ((unwrap list) . symbol)))
+($check-not-predicate (combiner? ()))
+($check-not-predicate (combiner? (cons () ())))
+($check-not-predicate (combiner? #ignore))
+($check-not-predicate (combiner? (make-environment)))
+($check-not-predicate (combiner? #inert))
+($check-not-predicate (combiner? (call/cc ($lambda (c) c))))
+($check-not-predicate (combiner? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (combiner? (memoize #inert)))
+($check-not-predicate (combiner? 1))
+;($check-not-predicate (combiner? 1.0))
+($check-not-predicate (combiner? #e+infinity))
+;($check-not-predicate (combiner? #i+infinity))
+;($check-not-predicate (combiner? #undefined))
+;($check-not-predicate (combiner? #real-with-no-primary-value))
+($check-not-predicate (combiner? "string"))
+($check-not-predicate (combiner? #\a))
+($check-not-predicate (combiner? (get-current-input-port)))
+
+;; $vau
+($check-predicate (operative? ($vau #ignore #ignore #inert)))
+($check eq? (($vau #ignore #ignore)) #inert)
+($check eq? (($vau #ignore #ignore 1)) 1)
+($check equal? (($vau ls #ignore ls) 1 2) (list 1 2))
+($check equal? (($vau #ignore env env)) (get-current-environment))
+($check equal? (($vau (x y) #ignore (list y x)) 1 2) (list 2 1))
+;; parameter trees (generalized parameter lists)
+($check equal? (($vau ((x . y) (z)) #ignore (list z y x)) (1 . 2) (3)) (list 3 2 1))
+($check equal? (($vau ((x y z)) #ignore (list z y x)) (1 2 3)) (list 3 2 1))
+($check equal? (($vau ((x y . z)) #ignore (finite-list? z))
+ #0=(1 2 3 . #0#)) #f)
+
+;; test static scope of $vau, define an "inverted" $if and use it in the body
+($let (($if ($vau (test a b) denv
+ (eval (list $if test b a)
+ denv))))
+ ($check eq?
+ (($vau () #ignore
+ ($if #t 1 2)))
+ 2))
+
+;; shared structure in ptree (but no shared symbols and no cycles)
+($check equal?
+ (($vau ((x . #0=(#ignore)) (y . #0#)) #ignore (list x y)) (1 4) (2 5))
+ (list 1 2))
+
+;; wrap
+($check-predicate (applicative? wrap))
+($check-predicate (applicative? (wrap ($vau #ignore #ignore #inert))))
+($check-predicate (applicative? (wrap (wrap ($vau #ignore #ignore #inert)))))
+($check-predicate (applicative? (wrap $if)))
+
+;; unwrap
+($check-predicate (applicative? unwrap))
+($check-predicate (operative?
+ (unwrap (wrap ($vau #ignore #ignore #inert)))))
+($check-predicate (applicative?
+ (unwrap (wrap (wrap ($vau #ignore #ignore #inert))))))
+($check-predicate (operative?
+ (unwrap list)))
+($check-predicate (applicative?
+ (unwrap (wrap list))))
+
+;; $lambda
+($check-predicate (applicative? ($lambda #ignore #inert)))
+($check eq? (($lambda #ignore)) #inert)
+($check eq? (($lambda #ignore 1)) 1)
+($check equal? (($lambda ls ls) 1 2) (list 1 2))
+($check equal? (($lambda (x y) (list y x)) 1 2) (list 2 1))
+;; arguments should be eval'ed in the current environment
+($check eq?
+ (($lambda (x) x) (get-current-environment))
+ (get-current-environment))
+;; parameter trees (generalized parameter lists)
+($check equal? (($lambda ((x . y) (z)) (list z y x))
+ (cons 1 2) (list 3)) (list 3 2 1))
+($check equal? (($lambda ((x y z)) (list z y x)) (list 1 2 3)) (list 3 2 1))
+($check equal? (($lambda ((x y . z)) (finite-list? z))
+ (list . #0=(1 2 3 . #0#))) #f)
+
+;; test static scope of $lambda, define an "inverted" $if and use it in the body
+($let (($if ($vau (test a b) denv
+ (eval (list $if test b a)
+ denv))))
+ ($check eq?
+ (($lambda ()
+ ($if #t 1 2)))
+ 2))
+;; shared structure in ptree (but no shared symbols and no cycles)
+($check equal?
+ (($lambda ((x . #0=(#ignore)) (y . #0#)) (list x y))
+ (list 1 4) (list 2 5))
+ (list 1 2))
+
+;; apply
+($check-predicate (applicative? apply))
+($check equal? (apply cons (list 1 2)) (cons 1 2))
+;; the underlying operative of list always returns its operand tree
+;; so this is correct in kernel
+($check eq? (apply list 3) 3)
+;; the two argument case uses an empty environment
+($check eq? (apply (wrap ($vau #ignore env ($binds? env $vau)))
+ #inert)
+ #f)
+
+($let ((empty-env (make-environment)))
+ ($check eq?
+ (apply (wrap ($vau #ignore env env)) #inert empty-env)
+ empty-env))
+
+;; map
+($check-predicate (applicative? map))
+($check equal? (map + (list 1 2 3 4)) (list 1 2 3 4))
+($check equal? (map cons (list 1 2 3 4) (list 10 20 30 40))
+ (list (cons 1 10) (cons 2 20) (cons 3 30) (cons 4 40)))
+
+($let ((p (cons () ())))
+ ($check eq?
+ ($sequence (map (wrap ($vau #ignore env
+ (set-car! p env)))
+ (list 1))
+ (car p))
+ (get-current-environment)))
+
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($sequence (map ($lambda (x)
+ (set-car! p (+ (car p) x)))
+ (list 1 2 3 4))
+ (car p))
+ 10))
+
+
+($check equal?
+ (map ($lambda (x)
+ (- 0 x))
+ (list 1 . #0=(2 3 4 . #0#)))
+ (list -1 . #1=(-2 -3 -4 . #1#)))
+
+($check equal?
+ (map ($lambda ls
+ (finite-list? ls))
+ . #0=((list 1 2 3 4)
+ (list 10 20 30 40)
+ . #0#))
+ (list #f #f #f #f))
+
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; operative?, applicative? & combiner?
+($check-error (operative? $vau . $cond))
+($check-error (applicative? wrap . unwrap))
+($check-error (combiner? $vau . wrap))
+
+;; $vau
+($check-error ($vau))
+($check-error ($vau #ignore))
+($check-error ($vau #ignore #ignore . #inert))
+
+;; repeated symbols aren't allowed
+($check-error ($vau (x x) #ignore x))
+;; same symbol in ptree and env aren't allowed either
+($check-error ($vau (x) x x))
+;; this counts as repeating symbols
+($check-error ($vau ((x . #0=(z)) (y . #0#)) #ignore (list x y z)))
+;; cycles aren't allowed either (containing symbols or not)
+($check-error ($vau (x . #0=(#ignore . #0#)) #ignore x))
+
+($check-error ($vau #ignore #t #inert))
+($check-error ($vau #f #ignore #inert))
+($check-error ($vau #inert #inert #inert))
+
+;; wrap
+($check-error (wrap))
+($check-error (wrap $vau $vau))
+($check-error (wrap . #0=($vau . #0#)))
+
+($check-error (wrap 1))
+($check-error (wrap #t))
+($check-error (wrap #inert))
+($check-error (wrap #ignore))
+($check-error (wrap ()))
+($check-error ($let/cc cont (wrap cont)))
+($check-error (wrap (memoize #inert)))
+
+;; unwrap
+($check-error (unwrap))
+($check-error (unwrap list list))
+($check-error (unwrap . #0=(list . #0#)))
+
+($check-error (unwrap 1))
+($check-error (unwrap #t))
+($check-error (unwrap #inert))
+($check-error (unwrap #ignore))
+($check-error ($let/cc cont (unwrap cont)))
+($check-error (unwrap (memoize #inert)))
+
+;; $lambda
+($check-error ($lambda))
+($check-error ($lambda #ignore . #inert))
+
+;; repeated symbols aren't allowed
+($check-error ($lambda (x x) x))
+;; this counts as repeating symbols
+($check-error ($lambda ((x . #0=(z)) (y . #0#)) (list x y z)))
+;; cycles aren't allowed either (containing symbols or not)
+($check-error ($lambda (x . #0=(#ignore . #0#)) x))
+
+($check-error ($lambda #t #inert))
+($check-error ($lambda #f #inert))
+($check-error ($lambda #inert #inert))
+
+;; apply
+($check-error (apply))
+($check-error (apply list))
+($check-error (apply list 1 (get-current-environment #inert)))
+($check-error (apply . #0=(list 1 (get-current-environment) . #0#)))
+
+($check-error (apply (unwrap list) 1))
+($check-error (apply #ignore 1))
+($check-error (apply 1 1))
+($check-error (apply list 1 #inert))
+($check-error (apply list 1 1))
+($check-error (apply cons (list 1)))
+
+;; map
+($check-error (map))
+;; the list can't be empty
+($check-error (map list))
+
+($check-error (map list (list 1 2) (list 1 2 3)))
+($check-error (map list (list . #0=(1 2 . #0#)) (list 1 2 3)))
+
+($check-error (map list #inert))
+($check-error (map #inert (list 1 2)))
+($check-error (map ((unwrap list) #inert) (list 1 2)))
+
+($check-error (map list (list 1 2) #inert))
+($check-error (map cons (list 1 2)))
diff --git a/src/tests/control.k b/src/tests/control.k
@@ -0,0 +1,199 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; inert?
+($check-predicate (applicative? inert?))
+($check-predicate (inert?))
+($check-predicate (inert? #inert))
+($check-predicate (inert? #inert #inert #inert))
+($check-predicate (inert? #inert . #0=(#inert . #0#)))
+
+($check-not-predicate (inert? ((unwrap list) . symbol)))
+($check-not-predicate (inert? ()))
+($check-not-predicate (inert? (cons () ())))
+($check-not-predicate (inert? #ignore))
+($check-not-predicate (inert? (make-environment)))
+($check-not-predicate (inert? #t))
+($check-not-predicate (inert? #f))
+($check-not-predicate (inert? $vau))
+($check-not-predicate (inert? wrap))
+($check-not-predicate (inert? (call/cc ($lambda (c) c))))
+($check-not-predicate (inert? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (inert? (memoize #inert)))
+($check-not-predicate (inert? 1))
+;($check-not-predicate (inert? 1.0))
+($check-not-predicate (inert? #e+infinity))
+;($check-not-predicate (inert? #i+infinity))
+;($check-not-predicate (inert? #undefined))
+;($check-not-predicate (inert? #real-with-no-primary-value))
+($check-not-predicate (inert? "string"))
+($check-not-predicate (inert? #\a))
+($check-not-predicate (inert? (get-current-input-port)))
+
+;; basic eq?-ness
+($check eq? #inert #inert)
+
+;; basic equal?-ness and not?
+($check equal? #inert #inert)
+
+;; $if
+($check-predicate (operative? $if))
+($check eq? ($if #t #t #f) #t)
+($check eq? ($if #f #t #f) #f)
+($check eq? ($if #t (get-current-environment) #f) (get-current-environment))
+($check eq? ($if #f #t (get-current-environment)) (get-current-environment))
+($let ((p (cons () ())))
+ ($check eq? ($if (($vau #ignore env
+ (set-car! p env)
+ #t)) (car p) #f)
+ (get-current-environment)))
+
+;; $sequence
+($check-predicate (operative? $sequence))
+($check eq? ($sequence) #inert)
+($check eq? ($sequence 1) 1)
+($check eq? ($sequence 1 2 3) 3)
+($check eq? ($sequence (get-current-environment)) (get-current-environment))
+($check eq? ($sequence #inert #inert (get-current-environment))
+ (get-current-environment))
+
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($let/cc cont
+ ($sequence . #0=(($if (=? (car p) 3)
+ (apply-continuation cont #t)
+ (set-car! p (+ (car p) 1)))
+ . #0#)))
+ #t))
+
+;; $cond
+($check-predicate (operative? $cond))
+($check eq? ($cond) #inert)
+($check eq? ($cond (#f 1) (#f 2) (#f 3)) #inert)
+($check eq? ($cond (#t 1) (#t 2) (#t 3)) 1)
+
+($check eq? ($cond (#t (get-current-environment))) (get-current-environment))
+($let ((p (cons () ())))
+ ($check eq?
+ ($cond (#f)
+ (($sequence (set-car! p (get-current-environment))
+ #t)
+ (car p))
+ (#f))
+ (get-current-environment)))
+($check eq? ($cond . #0=((#f) (#t 1) . #0#)) 1)
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($cond . #0=(((=? (car p) 3) 3)
+ (($sequence (set-car! p (+ (car p) 1))
+ #f)
+ 0)
+ (#f)
+ . #0#))
+ 3))
+
+
+;; for-each
+($check-predicate (applicative? for-each))
+($check eq? (for-each + (list 1 2 3 4)) #inert)
+($check eq? (for-each cons (list 1 2 3 4) (list 10 20 30 40)) #inert)
+($let ((p (cons () ())))
+ ($check eq?
+ ($sequence (for-each (wrap ($vau #ignore env
+ (set-car! p env)))
+ (list 1))
+ (car p))
+ (get-current-environment)))
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($sequence (for-each ($lambda (x)
+ (set-car! p (+ (car p) x)))
+ (list 1 2 3 4))
+ (car p))
+ 10))
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($sequence (for-each ($lambda (x y )
+ (set-car! p (+ (car p) x y)))
+ (list 1 2 3 4)
+ (list 10 20 30 40))
+ (car p))
+ 110))
+
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($let/cc cont
+ (for-each ($lambda (x)
+ ($if (=? (car p) 10)
+ (apply-continuation cont 10)
+ (set-car! p (+ (car p) 1))))
+ (list 1 . #0=(2 3 4 . #0#))))
+ #inert))
+
+($let ((p (cons 0 ())))
+ ($check eq?
+ ($sequence (for-each ($lambda ls
+ (set-car! p (finite-list? ls)))
+ . #0=((list 1 2 3 4)
+ (list 10 20 30 40)
+ . #0#))
+ (car p))
+ #f))
+
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; inert?
+($check-error (inert? #inert . #inert))
+($check-error (inert? #t . #inert))
+
+;; $if
+($check-error ($if))
+($check-error ($if #t))
+
+;; this short form isn't allowed in Kernel
+($check-error ($if #f #t))
+($check-error ($if #t #t))
+
+($check-error ($if #t #t #t #t))
+($check-error ($if . #0=(#t . #0#)))
+
+($check-error ($if 0 #t #f))
+($check-error ($if () #t #f))
+($check-error ($if #inert #t #f))
+($check-error ($if #ignore #t #f))
+($check-error ($if (cons #t #f) #t #f))
+($check-error ($if (cons #t #f) #t #f))
+
+;; $sequence
+($check-error ($sequence . #inert))
+($check-error ($sequence #inert #inert . #inert))
+
+;; $cond
+($check-error ($cond . #inert))
+($check-error ($cond (#t #t) . #inert))
+($check-error ($cond #inert))
+($check-error ($cond (1 1) (#t #t)))
+
+;; for-each
+
+($check-error (for-each))
+;; the list can't be empty
+($check-error (for-each list))
+
+($check-error (for-each list (list 1 2) (list 1 2 3)))
+($check-error (for-each list (list . #0=(1 2 . #0#)) (list 1 2 3)))
+
+($check-error (for-each list #inert))
+($check-error (for-each #inert (list 1 2)))
+($check-error (for-each ((unwrap list) #inert) (list 1 2)))
+
+($check-error (for-each list (list 1 2) #inert))
+($check-error (for-each cons (list 1 2)))
diff --git a/src/tests/environment-mutation.k b/src/tests/environment-mutation.k
@@ -0,0 +1,8 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; environmen mutation
+;; ....
diff --git a/src/tests/environments.k b/src/tests/environments.k
@@ -0,0 +1,9 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; environment
+($check-predicate (applicative? environment?))
+;; ....
diff --git a/src/tests/eq-equal.k b/src/tests/eq-equal.k
@@ -0,0 +1,170 @@
+;;;
+;;; Basic Functionality
+;;;
+
+($check-predicate (applicative? eq?))
+($check-predicate (applicative? equal?))
+
+; no arguments
+($check-predicate (eq?))
+
+($check-predicate (equal?))
+
+; 1 arguments
+($check-predicate (eq? ((unwrap list) . symbol)))
+($check-predicate (eq? ()))
+($check-predicate (eq? (cons () ())))
+($check-predicate (eq? #ignore))
+($check-predicate (eq? (make-environment)))
+($check-predicate (eq? #inert))
+($check-predicate (eq? $vau))
+($check-predicate (eq? wrap))
+($check-predicate (eq? (call/cc ($lambda (c) c))))
+($check-predicate (eq? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-predicate (eq? (memoize #inert)))
+($check-predicate (eq? 1))
+($check-predicate (eq? -1/2))
+($check-predicate (eq? 1.0))
+($check-predicate (eq? #e+infinity))
+($check-predicate (eq? #i+infinity))
+($check-predicate (eq? #undefined))
+($check-predicate (eq? #real))
+($check-predicate (eq? "string"))
+($check-predicate (eq? #\a))
+($check-predicate (eq? (get-current-input-port)))
+
+
+($check-predicate (equal? ((unwrap list) . symbol)))
+($check-predicate (equal? ()))
+($check-predicate (equal? (cons () ())))
+($check-predicate (equal? #ignore))
+($check-predicate (equal? (make-environment)))
+($check-predicate (equal? #inert))
+($check-predicate (equal? $vau))
+($check-predicate (equal? wrap))
+($check-predicate (equal? (call/cc ($lambda (c) c))))
+($check-predicate (equal? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-predicate (equal? (memoize #inert)))
+($check-predicate (equal? 1))
+($check-predicate (equal? -1/2))
+($check-predicate (equal? 1.0))
+($check-predicate (equal? #e+infinity))
+($check-predicate (equal? #i+infinity))
+($check-predicate (equal? #undefined))
+($check-predicate (equal? #real))
+($check-predicate (equal? "string"))
+($check-predicate (equal? #\a))
+($check-predicate (equal? (get-current-input-port)))
+
+; 2 arguments
+($check-predicate (eq? ((unwrap list) . symbol) ((unwrap list) . symbol)))
+($check-predicate (eq? () ()))
+($let ((p (cons () ())))
+ ($check-predicate (eq? p p)))
+($check-not-predicate (eq? (cons () ()) (cons () ())))
+($check-predicate (eq? #ignore #ignore))
+($let ((e (make-environment)))
+ ($check-predicate (eq? e e)))
+($check-not-predicate (eq? (make-environment) (make-environment)))
+($check-predicate (eq? #inert #inert))
+($check-predicate (eq? $vau $vau))
+($check-predicate (eq? wrap wrap))
+($let/cc c
+ ($check-predicate (eq? c c)))
+($let* (((enc . #ignore)
+ (make-encapsulation-type))
+ (e (enc #inert)))
+ ($check-predicate (eq? e e))
+ ($check-not-predicate (eq? e (enc #inert))))
+($let ((p (memoize #inert)))
+ ($check-predicate (eq? p p))
+ ($check-not-predicate (eq? p #inert)))
+($check-predicate (eq? 1 1))
+($check-predicate (eq? -1/2 -1/2))
+($check-predicate (eq? 1.0 1.0))
+($check-not-predicate (eq? 1 1.0))
+($check-not-predicate (eq? 1/2 0.5))
+($check-predicate (eq? #e+infinity #e+infinity))
+($check-predicate (eq? #i+infinity #i+infinity))
+($check-not-predicate (eq? #e+infinity #i+infinity))
+($check-predicate (eq? #undefined #undefined))
+($check-predicate (eq? #real #real))
+($check-not-predicate (eq? #undefined #real))
+($let ((s "string"))
+ ($check-predicate (eq? s s)))
+($check-not-predicate (eq? (string #\c) (string #\c)))
+($check-predicate (eq? #\a #\a))
+($check-predicate (eq? (get-current-input-port) (get-current-input-port)))
+
+($check-predicate (equal? ((unwrap list) . symbol) ((unwrap list) . symbol)))
+($check-predicate (equal? () ()))
+($check-predicate (equal? (cons () ()) (cons () ())))
+($let ((p1 (list 1 2 1 2))
+ (p2 (list 1 2)))
+ (encycle! p1 2 2)
+ (encycle! p2 0 2)
+ ($check-predicate (equal? p1 p2)))
+($check-predicate (equal? #ignore #ignore))
+($let ((e (make-environment)))
+ ($check-predicate (equal? e e)))
+($check-not-predicate (equal? (make-environment) (make-environment)))
+($check-predicate (equal? #inert #inert))
+($check-predicate (equal? $vau $vau))
+($check-predicate (equal? wrap wrap))
+($let/cc c
+ ($check-predicate (equal? c c)))
+($let* (((enc . #ignore)
+ (make-encapsulation-type))
+ (e (enc #inert)))
+ ($check-predicate (equal? e e))
+ ($check-not-predicate (equal? e (enc #inert))))
+($let ((p (memoize #inert)))
+ ($check-predicate (equal? p p))
+ ($check-not-predicate (equal? p #inert)))
+($check-predicate (equal? 1 1))
+($check-predicate (equal? -1/2 -1/2))
+($check-predicate (equal? 1.0 1.0))
+($check-not-predicate (equal? 1 1.0))
+($check-not-predicate (equal? 1/2 0.5))
+($check-predicate (equal? #e+infinity #e+infinity))
+($check-predicate (equal? #i+infinity #i+infinity))
+($check-not-predicate (equal? #e+infinity #i+infinity))
+($check-predicate (equal? #undefined #undefined))
+($check-predicate (equal? #real #real))
+($check-not-predicate (equal? #undefined #real))
+($let ((s "string"))
+ ($check-predicate (equal? s s)))
+($check-predicate (equal? "string" "string"))
+($check-predicate (equal? (string #\c) (string #\c)))
+($check-predicate (equal? #\a #\a))
+($check-predicate (equal? (get-current-input-port) (get-current-input-port)))
+
+; 3 or more arguments
+($check-predicate (eq? 1 1 1))
+($check-not-predicate (eq? #t #t #f))
+($check-predicate (eq? #t #t . #0=(#t . #0#)))
+($check-not-predicate (eq? #t #t . #0=(#inert . #0#)))
+
+($check-predicate (equal? 1 1 1))
+($check-not-predicate (equal? #t #t #f))
+($check-predicate (equal? #t #t . #0=(#t . #0#)))
+($check-not-predicate (equal? #t #t . #0=(#inert . #0#)))
+
+($let ((p1 (list 1 2 1 2))
+ (p2 (list 1 2)))
+ (encycle! p1 2 2)
+ (encycle! p2 0 2)
+ ($check-predicate (equal? p1 p2 . #0=(p2 p1 . #0#))))
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; boolean?
+($check-error (eq? #t . #f))
+
+($check-error (equal? #t . #f))
diff --git a/src/tests/pair-mutation.k b/src/tests/pair-mutation.k
@@ -0,0 +1,204 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; set-car! & set-cdr!
+($let ((pair (cons () ())))
+ ($check-predicate (inert? (set-car! pair 1)))
+ ($check-predicate (inert? (set-cdr! pair 2)))
+ ($check equal? (car pair) 1)
+ ($check equal? (cdr pair) 2)
+ (set-car! pair pair)
+ (set-cdr! pair pair)
+ ($check eq? (car pair) pair)
+ ($check eq? (cdr pair) pair))
+
+;; copy-es-immutable
+($let* ((orig (list (cons 1 2) (cons 3 4)))
+ (copy (copy-es-immutable orig))
+ (copy2 (copy-es-immutable copy)))
+ ($check equal? orig copy)
+ ($check-predicate (mutable-pair? orig))
+ ($check-predicate (immutable-pair? copy))
+ ($check equal? orig copy2)
+ ($check-predicate (immutable-pair? copy2)))
+
+;; encycle!
+($check equal? ($let ((l 1)) (encycle! l 0 0) l)
+ 1)
+($check equal? ($let ((l (list 1 2 3 4 5))) (encycle! l 4 0) l)
+ (list 1 2 3 4 5))
+($check equal? ($let ((l (list 1 2 3 4 5))) (encycle! l 2 3) l)
+ (list 1 2 . #0=(3 4 5 . #0#)))
+($check equal? ($let ((l (list* 1 2 3 4 5))) (encycle! l 0 3) l)
+ (list . #0=(1 2 3 . #0#)))
+
+;; append!
+($let ()
+ ($define! l1 (list 1 2))
+ ($define! l2 (list 3 4))
+ ($define! l3 (list 5 6))
+
+ ($check equal? ($sequence (append! l1 ()) l1) (list 1 2))
+ ($check equal? ($sequence (append! l1 () ()) l1) (list 1 2))
+ ($check equal? ($sequence (append! l1 l2) l1) (list 1 2 3 4))
+ ($check equal? ($sequence (append! l1 () () l3 ()) l1) (list 1 2 3 4 5 6))
+
+ ($define! l1 (list 1 2))
+ ($define! l2 (list 3 4))
+ ($define! l3 (list . #0=(5 6 . #0#)))
+
+ (append! l1 l2 l3)
+ ($check equal? l1 (list 1 2 3 4 . #2=(5 6 . #2#)))
+ ($check eq? (cddddr l1) l3)
+
+ ($define! l1 (list 1 2))
+ ($define! l2 (list 3 4))
+ ($define! l3 (list 5 6))
+
+ ($check equal?
+ ($sequence (append! l1 . #3=(l2 l3 . #3#)) l1)
+ (list 1 2 . #4=(3 4 5 6 . #4#)))
+
+ ($define! l1 (list 1 2))
+ ($define! l2 (list 3 4))
+ ($define! l3 (list 5 6))
+
+ ($check equal?
+ ($sequence (append! l1 l2 l3 . #5=(() () . #5#)) l1)
+ (list 1 2 3 4 5 6))
+
+ ($define! l1 (list 1 2))
+ ($define! l2 (list 3 4))
+ ($define! l3 (list 5 6))
+
+ ($check equal?
+ ($sequence (append! l1 () . #6=(() l2 () l3 () . #6#)) l1)
+ (list 1 2 . #7=(3 4 5 6 . #7#))))
+
+;; copy-es
+($let* ((orig (list (cons 1 2) (cons 3 4)))
+ (copy (copy-es orig)))
+ ($check equal? orig copy)
+ ($check-predicate (mutable-pair? orig))
+ ($check-predicate (mutable-pair? copy))
+ ($check not-eq? orig copy))
+
+;; assq
+($check equal? (assq #inert ()) ())
+($check equal? (assq 3 (list (list 1 10) (list 2 20))) ())
+($check equal? (assq 1 (list (list 1 10) (list 2 20))) (list 1 10))
+($check equal?
+ (assq 1 (list . #0=((list 1 10) (list 2 20) (list 1 15) . #0#)))
+ (list 1 10))
+($check equal?
+ (assq 4 (list . #0=((list 1 10) (list 2 20) (list 1 15) . #0#)))
+ ())
+($check equal?
+ (assq (list 1) (list (list (list 1) 1) (list (list 2) 2)))
+ ())
+
+;; memq
+($check-predicate (memq? 1 (list 1 2)))
+($check-predicate (memq? 2 (list 1 2)))
+($check-not-predicate (memq? 1 ()))
+($check-not-predicate (memq? 3 (list 1 2)))
+($check-not-predicate (memq? (list 1) (list (list 1) 2)))
+($check-not-predicate (memq? (list 2) (list 1 (list 2))))
+($check-predicate
+ (memq? 3 (list . #0=(1 2 3 . #0#))))
+($check-not-predicate
+ (memq? 4 (list . #0=(1 2 1 . #0#))))
+
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; set-car! & set-cdr!
+($check-error (set-car!))
+($check-error (set-car! (cons () ())))
+($check-error (set-car! (cons () ()) #inert #inert))
+
+($check-error (set-car! () #inert))
+($check-error (set-car! 1 #inert))
+($check-error (set-car! (get-current-environment) #inert))
+($check-error (set-car! ($lambda #ignore) #inert))
+($check-error (set-car! ($vau #ignore #ignore) #inert))
+
+($check-error (set-cdr!))
+($check-error (set-cdr! (cons () ())))
+($check-error (set-cdr! (cons () ()) #inert #inert))
+
+($check-error (set-cdr! () #inert))
+($check-error (set-cdr! 1 #inert))
+($check-error (set-cdr! (get-current-environment) #inert))
+($check-error (set-cdr! ($lambda #ignore) #inert))
+($check-error (set-cdr! ($vau #ignore #ignore) #inert))
+
+($let ((imm-pair (copy-es-immutable (cons () ()))))
+ ($check-error (set-car! imm-pair #inert))
+ ($check-error (set-cdr! imm-pair #inert))
+ ($check-predicate (null? (car imm-pair)))
+ ($check-predicate (null? (cdr imm-pair))))
+
+;; copy-es-immutable
+($check-error (copy-es-immutable))
+($check-error (copy-es-immutable (cons () ()) (cons () ())))
+
+;; encycle!
+($check-error (encycle!))
+($check-error (encycle! (list 1 2 3)))
+($check-error (encycle! (list 1 2 3) 1))
+($check-error (encycle! (list 1 2 3) 1 2 3))
+
+($check-error (encycle! (list 1 2 3) 2 2))
+($check-error (encycle! (list 1 2 3) -1 2))
+($check-error (encycle! (list 1 2 3) 0 -2))
+($check-error (encycle! (list 1 2 3) 0 #e+infinity))
+
+;; append!
+;; ASK does the report assert that the lists remains unmodified??
+;; probably should for robust implementations
+
+($check-error (append!))
+($check-error (append! ()))
+($check-error (append! (list . #0=(1 2 . #0#)) ()))
+($check-error (append! (list 1 2) 3 (list 4 5)))
+($check-error (append! (list 1 2) 3 ()))
+
+($check-error (append! ((unwrap list) . (1 2 . #0=(3)))
+ ((unwrap list) . (4 5 . #0#))
+ ()))
+
+;; ASK if this is valid or not
+;; ($check-error (append! ((unwrap list) . (1 2 . #0=(3)))
+;; ((unwrap list) . (4 5 . #0#))))
+
+
+;; copy-es
+($check-error (copy-es))
+($check-error (copy-es (cons () ()) (cons () ())))
+
+;; assq
+($check-error (assq))
+($check-error (assq 2))
+($check-error (assq 2 (list (list 1 1) (list 2 2)) ()))
+($check-error (assq . #0=(2 (list (list 1 1) (list 2 2)) . #0#)))
+
+($check-error (assq 2 (list* (list 1 1) 2)))
+($check-error (assq 2 (list* (list 1 1) (list 2 2) #inert)))
+($check-error (assq 4 (list (list 1 1) (list 2 2) #inert (list 4 4))))
+($check-error (assq 2 (list (list 1 1) (list 2 2) #inert (list 4 4))))
+
+;; memq
+($check-error (memq?))
+($check-error (memq? 2))
+($check-error (memq? 2 (list 1 2) ()))
+($check-error (memq? . #0=(2 (list 1 2) . #0#)))
+
+($check-error (memq? 2 (list* 1 2)))
+($check-error (memq? 2 (list* 1 2 3)))
+
diff --git a/src/tests/pairs-and-lists.k b/src/tests/pairs-and-lists.k
@@ -0,0 +1,447 @@
+;; check.k & test-helpers.k should be loaded
+
+;; TODO use mutable-pair to verify that cons, list append etc construct with
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; null? & pair?
+($check-predicate (null?))
+($check-predicate (null? ()))
+($check-predicate (null? () () ()))
+($check-predicate (null? () . #0=(() . #0#)))
+
+($check-predicate (pair?))
+($check-predicate (pair? (cons () ())))
+($check-predicate (pair? (cons () ()) (copy-es-immutable (cons () ())) (cons () ())))
+($check-predicate (pair? (cons () ()) . #0=((copy-es-immutable (cons () ())) . #0#)))
+
+($check-not-predicate (null? #t))
+($check-not-predicate (null? ((unwrap list) . symbol)))
+($check-not-predicate (null? (cons () ())))
+($check-not-predicate (null? #ignore))
+($check-not-predicate (null? (make-environment)))
+($check-not-predicate (null? #inert))
+($check-not-predicate (null? $vau))
+($check-not-predicate (null? wrap))
+($check-not-predicate (null? (call/cc ($lambda (c) c))))
+($check-not-predicate (null? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (null? (memoize #inert)))
+($check-not-predicate (null? 1))
+;($check-not-predicate (null? 1.0))
+($check-not-predicate (null? #e+infinity))
+;($check-not-predicate (null? #i+infinity))
+;($check-not-predicate (null? #undefined))
+;($check-not-predicate (null? #real-with-no-primary-value))
+($check-not-predicate (null? "string"))
+($check-not-predicate (null? #\a))
+($check-not-predicate (null? (get-current-input-port)))
+
+($check-not-predicate (pair? #t))
+($check-not-predicate (pair? ((unwrap list) . symbol)))
+($check-not-predicate (pair? ()))
+($check-not-predicate (pair? #ignore))
+($check-not-predicate (pair? (make-environment)))
+($check-not-predicate (pair? #inert))
+($check-not-predicate (pair? $vau))
+($check-not-predicate (pair? wrap))
+($check-not-predicate (pair? (call/cc ($lambda (c) c))))
+($check-not-predicate (pair? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (pair? (memoize #inert)))
+($check-not-predicate (pair? 1))
+;($check-not-predicate (pair? 1.0))
+($check-not-predicate (pair? #e+infinity))
+;($check-not-predicate (pair? #i+infinity))
+;($check-not-predicate (pair? #undefined))
+;($check-not-predicate (pair? #real-with-no-primary-value))
+($check-not-predicate (pair? "string"))
+($check-not-predicate (pair? #\a))
+($check-not-predicate (pair? (get-current-input-port)))
+
+;; basic eq?-ness
+($check eq? () ())
+($let ((p (cons () ())))
+ ($check eq? p p))
+($check not-eq? (cons () ()) (cons () ()))
+($check not-eq? (cons () ()) ())
+
+;; basic equal?-ness
+($check equal? (cons () ()) (cons () ()))
+($check equal? () ())
+($check not-equal? (cons () ()) (cons (cons () ()) ()))
+($check not-equal? (cons () ()) ())
+
+;; list & list*
+($check equal? (list) ())
+($check equal? (list 1 2 3) (cons 1 (cons 2 (cons 3 ()))))
+($check equal? ((unwrap list) 1 2 . 3) (list* 1 2 3))
+($check equal? ((unwrap list) . #inert) (list* #inert))
+($check equal? (list* #inert) #inert)
+($check equal? (list* 1 2 3) (cons 1 (cons 2 3)))
+($check equal? (list 1 . #0=(2 3 . #0#)) ((unwrap list) 1 . #0#))
+
+;; car, cdr & co
+($check equal? (car (cons 1 2)) 1)
+($check equal? (cdr (cons 1 2)) 2)
+
+($let* ((tree2 (cons 1 2))
+ (tree4 (cons tree2 (cons 3 4)))
+ (tree8 (cons tree4 (cons (cons 5 6) (cons 7 8))))
+ (tree16 (cons tree8 (cons (cons (cons 9 10) (cons 11 12))
+ (cons (cons 13 14) (cons 15 16))))))
+ ($check eq? (car tree2) 1)
+ ($check eq? (cdr tree2) 2)
+
+ ($check eq? (caar tree4) 1)
+ ($check eq? (cdar tree4) 2)
+ ($check eq? (cadr tree4) 3)
+ ($check eq? (cddr tree4) 4)
+
+ ($check eq? (caaar tree8) 1)
+ ($check eq? (cdaar tree8) 2)
+ ($check eq? (cadar tree8) 3)
+ ($check eq? (cddar tree8) 4)
+ ($check eq? (caadr tree8) 5)
+ ($check eq? (cdadr tree8) 6)
+ ($check eq? (caddr tree8) 7)
+ ($check eq? (cdddr tree8) 8)
+
+ ($check eq? (caaaar tree16) 1)
+ ($check eq? (cdaaar tree16) 2)
+ ($check eq? (cadaar tree16) 3)
+ ($check eq? (cddaar tree16) 4)
+ ($check eq? (caadar tree16) 5)
+ ($check eq? (cdadar tree16) 6)
+ ($check eq? (caddar tree16) 7)
+ ($check eq? (cdddar tree16) 8)
+ ($check eq? (caaadr tree16) 9)
+ ($check eq? (cdaadr tree16) 10)
+ ($check eq? (cadadr tree16) 11)
+ ($check eq? (cddadr tree16) 12)
+ ($check eq? (caaddr tree16) 13)
+ ($check eq? (cdaddr tree16) 14)
+ ($check eq? (cadddr tree16) 15)
+ ($check eq? (cddddr tree16) 16))
+
+;; get-list-metrics
+($check equal? (get-list-metrics ()) (list 0 1 0 0))
+($check equal? (get-list-metrics #inert) (list 0 0 0 0))
+($check equal? (get-list-metrics (list 1)) (list 1 1 1 0))
+($check equal? (get-list-metrics (list* 1 2)) (list 1 0 1 0))
+($check equal? (get-list-metrics (list 1 2 . #0=(3 4 5 . #0#))) (list 5 0 2 3))
+($check equal? (get-list-metrics (list . #0=(1 2 . #0#))) (list 2 0 0 2))
+
+;; list-tail
+($check equal? (list-tail (list 1 2 3 4 5) 0) (list 1 2 3 4 5))
+($check equal? (list-tail (list 1 2 3 4 5) 1) (list 2 3 4 5))
+($check equal? (list-tail (list* 1 2 3) 2) 3)
+($check equal? (list-tail (list . #0=(1 2 3 4 5 . #0#)) 10) (list . #0#))
+
+;; length
+($check =? (length ()) 0)
+($check =? (length "string") 0) ; in Kernel improper lists have length too
+($check =? (length (list 1 2 3 4 5)) 5)
+($check =? (length (list* 1 2 3 4 5 "string")) 5)
+($check =? (length (list 1 2 . #0=(3 4 5 . #0#))) #e+infinity)
+
+;; list-ref
+($check =? (list-ref (list 1 2 3 4 5) 0) 1)
+($check =? (list-ref (list 1 2 3 4 5) 1) 2)
+;; see ground/pairs-and-lists.scm for rationale on allowing
+;; improper lists as argument to list-ref
+($check =? (list-ref (list* 1 2 3 4) 2) 3)
+($check =? (list-ref (list . #0=(1 2 3 4 5 . #0#)) 10) 1)
+
+;; append
+($check equal? (append) ())
+($check equal? (append ()) ())
+($check equal? (append () ()) ())
+($check equal? (append (list 1 2 3) (list 4 5) (list 6)) (list 1 2 3 4 5 6))
+($check equal? (append (list 1 2) (list 3 4 5 6) ()) (list 1 2 3 4 5 6))
+($check equal? (append () (list 1) (list 2 3 4)) (list 1 2 3 4))
+($check equal? (append (list 1 2) (list 3 4) 5) (list* 1 2 3 4 5))
+($let ((l1 (list 1 2)) (l2 (list 3 4))) ; the last list isn't copied
+ ($check eq? (cddr (append l1 l2)) l2))
+($let ((l1 (list 1 2)) (l2 (list 3 4))) ; here the last list is copied
+ ($check not-eq? (cddr (append l1 l2 ())) l2))
+($check equal?
+ (append (list 1 2) (list 3 4) . #0=((list 5 6) . #0#))
+ (list 1 2 3 4 . #1=(5 6 . #1#)))
+($check equal?
+ (append () () . #0=(() (list 1 2) () . #0#))
+ (list . #1=(1 2 . #1#)))
+($check equal?
+ (append (list 1 2) (list 3 4) . #0=(() () . #0#))
+ (list 1 2 3 4))
+
+;; list-neighbors
+($check equal? (list-neighbors ()) ())
+($check equal? (list-neighbors (list 1)) ())
+($check equal? (list-neighbors (list 1 2)) (list (list 1 2)))
+($check equal?
+ (list-neighbors (list 1 2 3 4))
+ (list (list 1 2) (list 2 3) (list 3 4)))
+($check equal?
+ (list-neighbors (list . #0=(1 2 3 4 . #0#)))
+ (list . #1=((list 1 2) (list 2 3) (list 3 4) (list 4 1) . #1#)))
+($check equal?
+ (list-neighbors (list 1 2 . #0=(3 4 . #0#)))
+ (list (list 1 2) (list 2 3) . #1=((list 3 4) (list 4 3) . #1#)))
+
+;; filter
+($check equal? (filter number? ()) ())
+($check equal? (filter number? (list #t #f #t)) ())
+($check equal? (filter number? (list 1 2 3)) (list 1 2 3))
+($check equal? (filter number? (list 1 #t 2 #f)) (list 1 2))
+($check equal?
+ (filter number? (list 1 #t . #0=(2 #f . #0#)))
+ (list 1 . #1=(2 . #1#)))
+($check equal?
+ (filter number? (list #t 1 #f . #0=(#t #f . #0#)))
+ (list 1))
+($check equal?
+ (filter number? (list #t #f . #0=(#t #f . #0#)))
+ ())
+
+($check equal? ; filter should use an empty environment
+ (filter (wrap ($vau #ignore denv ($binds? denv $if)))
+ (list 1 2 3))
+ ())
+
+;; assoc
+($check equal? (assoc #inert ()) ())
+($check equal? (assoc 3 (list (list 1 10) (list 2 20))) ())
+($check equal? (assoc 1 (list (list 1 10) (list 2 20))) (list 1 10))
+($check equal?
+ (assoc 1 (list . #0=((list 1 10) (list 2 20) (list 1 15) . #0#)))
+ (list 1 10))
+($check equal?
+ (assoc 4 (list . #0=((list 1 10) (list 2 20) (list 1 15) . #0#)))
+ ())
+($check equal?
+ (assoc (list 1) (list (list (list 1) 1) (list (list 2) 2)))
+ (list (list 1) 1))
+
+;; member?
+($check-predicate (member? 1 (list 1 2)))
+($check-predicate (member? 2 (list 1 2)))
+($check-not-predicate (member? 1 ()))
+($check-not-predicate (member? 3 (list 1 2)))
+($check-predicate (member? (list 1) (list (list 1) 2)))
+($check-predicate (member? (list 2) (list 1 (list 2))))
+($check-predicate
+ (member? (list 1 3) (list . #0=(1 2 (list 1 3) . #0#))))
+($check-not-predicate
+ (member? 4 (list . #0=(1 2 1 . #0#))))
+
+;; finite-list?
+($check-predicate (finite-list? ()))
+($check-predicate (finite-list? (list 1)))
+($check-predicate (finite-list? (list 1 2)))
+($check-predicate (finite-list? (list 1 2) (list 1 2 3) ()))
+($check-predicate (finite-list? (list 1 2) . #0=((list 1 2 3) () . #0#)))
+($check-not-predicate (finite-list? 1))
+($check-not-predicate (finite-list? () (list 1 2 . #0=(3 . #0#))))
+($check-not-predicate (finite-list? () 1))
+($check-not-predicate (finite-list? (list 1 2) . #0=(1 () . #0#)))
+
+;; countable-list?
+($check-predicate (countable-list? ()))
+($check-predicate (countable-list? (list 1 2)))
+($check-predicate (countable-list? (list 1 . #0=(2 . #0#))))
+($check-predicate (countable-list? (list 1 2) (list 1 . #0=(2 . #0#)) ()))
+($check-predicate (countable-list?
+ () . #0=((list 1 . #1=(2 . #1#)) () . #0#)))
+
+($check-not-predicate (countable-list? 1))
+($check-not-predicate (countable-list? () 1))
+($check-not-predicate (countable-list? (list 1 2) . #0=(#inert () . #0#)))
+($check-not-predicate (countable-list?
+ () . #0=((list 1 . #1=(2 . #1#)) 3 . #0#)))
+
+;; reduce
+($let ((ac-+ ($lambda ls (reduce ls + 0)))
+ (c-+
+;; the idea of the cycle treatment is to carry a flag indicating
+;; if all elements so far in the cycle were actually zero, if so
+;; the sum of the cycle is zero otherwise it can be undefined or
+;; (* +infinity (acyclic-sum)) which in the integer case is +infinity
+;; or -infinity
+ ($let ((precycle ($lambda (x)
+ (cons x (zero? x))))
+ (incycle ($lambda ((x . x-zero?) (y . y-zero?))
+ (cons (+ x y)
+ (and? x-zero? y-zero?))))
+ (postcycle ($lambda ((result . all-zero?))
+ ($if all-zero?
+ 0
+ (* #e+infinity result)))))
+ ($lambda ls
+ (reduce ls + 0 precycle incycle postcycle)))))
+ ($check equal? (ac-+) 0)
+ ($check equal? (ac-+ 1) 1)
+ ($check equal? (ac-+ 1 2) 3)
+ ($check equal? (ac-+ 1 2 3) 6)
+
+ ($check equal? (c-+) 0)
+ ($check equal? (c-+ 1) 1)
+ ($check equal? (c-+ 1 2) 3)
+ ($check equal? (c-+ 1 2 . #0=(0 0 . #0#)) 3)
+ ($check equal? (c-+ 1 2 . #2=(-3 -4 . #2#)) #e-infinity))
+
+
+;;;
+;;; Error Checking and Robustness
+;;;
+
+;; null? & pair?
+($check-error (null? () . #inert))
+($check-error (pair? (cons () ()) . #inert))
+
+;; list & list*
+($check-error (list #inert . 1))
+($check-error (list* . 1))
+($check-error (list*))
+($check-error (list* 1 #0=(2 3 . #0#)))
+
+;; car, cdr & co
+($check-error (car))
+($check-error (cdr))
+($check-error (car ()))
+($check-error (cdr ()))
+($check-error (car 1))
+($check-error (cdr 1))
+($check-error (car (cons 1 2) (cons 3 4)))
+($check-error (cdr (cons 1 2) (cons 3 4)))
+
+($let* ((tree2 (cons 1 2))
+ (tree4 (cons tree2 (cons 3 4)))
+ (tree8 (cons tree4 (cons (cons 5 6) (cons 7 8)))))
+ ($check-error (caar tree2))
+ ($check-error (cdar tree2))
+ ($check-error (cadr tree2))
+ ($check-error (cddr tree2))
+
+ ($check-error (caaar tree4))
+ ($check-error (cdaar tree4))
+ ($check-error (cadar tree4))
+ ($check-error (cddar tree4))
+ ($check-error (caadr tree4))
+ ($check-error (cdadr tree4))
+ ($check-error (caddr tree4))
+ ($check-error (cdddr tree4))
+
+ ($check-error (caaaar tree8))
+ ($check-error (cdaaar tree8))
+ ($check-error (cadaar tree8))
+ ($check-error (cddaar tree8))
+ ($check-error (caadar tree8))
+ ($check-error (cdadar tree8))
+ ($check-error (caddar tree8))
+ ($check-error (cdddar tree8))
+ ($check-error (caaadr tree8))
+ ($check-error (cdaadr tree8))
+ ($check-error (cadadr tree8))
+ ($check-error (cddadr tree8))
+ ($check-error (caaddr tree8))
+ ($check-error (cdaddr tree8))
+ ($check-error (cadddr tree8))
+ ($check-error (cddddr tree8)))
+
+;; get-list-metrics
+($check-error (get-list-metrics))
+($check-error (get-list-metrics () ()))
+
+;; list-tail
+($check-error (list-tail))
+($check-error (list-tail (list 1 2 3)))
+($check-error (list-tail (list 1 2 3) 3 4))
+($check-error (list-tail (list 1 2 3) 4))
+($check-error (list-tail (list 1 2 3) #e+infinity))
+;($check-error (list-tail (list 1 2 3) 3.4))
+($check-error (list-tail (list 1 2 3) -1))
+($check-error (list-tail (list 1 2 3) #f))
+
+;; length
+($check-error (length))
+($check-error (length () ()))
+($check-error (length . #0=(() . #0#)))
+
+;; list-ref
+($check-error (list-ref))
+($check-error (list-ref (list 1 2 3)))
+($check-error (list-ref (list 1 2 3) 3 4))
+($check-error (list-ref (list 1 2 3) 4))
+($check-error (list-ref (list 1 2 3) #e+infinity))
+;($check-error (list-ref (list 1 2 3) 3.4))
+($check-error (list-ref (list 1 2 3) -1))
+($check-error (list-ref (list 1 2 3) #f))
+
+;; append
+($check-error (append (list 1 2) (list . #0=(3 4 . #0#)) (list 5 6)))
+($check-error (append (list . #0=(1 2 . #0#)) ()))
+($check-error (append (list 1 2) 3 (list 4 5)))
+($check-error (append (list 1 2) 3 ()))
+
+;; list-neighbors
+($check-error (list-neighbors))
+($check-error (list-neighbors (list 1 2) (list 3 4)))
+($check-error (list-neighbors 1))
+($check-error (list-neighbors (list* 1 2 3 4)))
+
+;; filter
+($check-error (filter))
+($check-error (filter number?))
+($check-error (filter (list 1)))
+($check-error (filter number? #inert))
+($check-error (filter number? (list* 1 2 3)))
+($check-error (filter number? (list 1 2 3) #inert))
+($check-error (filter (unwrap number?) (list 1 2 3)))
+($check-error (filter + (list 1 2 3)))
+($check-error (filter car (list 1 2 3)))
+
+;; asooc
+($check-error (assoc))
+($check-error (assoc 2))
+($check-error (assoc 2 (list (list 1 1) (list 2 2)) ()))
+($check-error (assoc . #0=(2 (list (list 1 1) (list 2 2)) . #0#)))
+
+($check-error (assoc 2 (list* (list 1 1) 2)))
+($check-error (assoc 2 (list* (list 1 1) (list 2 2) #inert)))
+($check-error (assoc 4 (list (list 1 1) (list 2 2) #inert (list 4 4))))
+($check-error (assoc 2 (list (list 1 1) (list 2 2) #inert (list 4 4))))
+
+;; member?
+($check-error (member?))
+($check-error (member? 2))
+($check-error (member? 2 (list 1 2) ()))
+($check-error (member? . #0=(2 (list 1 2) . #0#)))
+
+($check-error (member? 2 (list* 1 2)))
+($check-error (member? 2 (list* 1 2 3)))
+
+;; finite-list?
+($check-error (countable-list? (cons () ()) . #inert))
+
+;; countable-list?
+($check-error (countable-list? (list . #0=(1 . #0#)) . #inert))
+
+;; reduce
+($check-error (reduce))
+($check-error (reduce (list 1 2)))
+($check-error (reduce (list 1 2) +))
+($check-error (reduce #inert + 0))
+($check-error (reduce (list 1 2) #inert 0))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0))
+
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 +))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 + +))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 + + + +))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 + + #inert))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 + #inert +))
+($check-error (reduce (list 1 2 #0=(3 . #0#)) + 0 #inert + +))
diff --git a/src/tests/symbols.k b/src/tests/symbols.k
@@ -0,0 +1,38 @@
+;; check.k & test-helpers.k should be loaded
+
+;;;
+;;; Basic Functionality
+;;;
+
+;; symbol?
+($check-predicate (applicative? symbol?))
+
+($let (($qs ($vau (s) #ignore s)))
+ ($let ((s1 ($qs s1))
+ (s2 ($qs s2))
+ (s3 ($qs s3)))
+ ($check-predicate (symbol?))
+ ($check-predicate (symbol? s1))
+ ($check-predicate (symbol? s1 s2 s3))
+ ($check-predicate (symbol? s1 . #0=(s2 . #0#)))))
+
+($check-not-predicate (symbol? ()))
+($check-not-predicate (symbol? (cons () ())))
+($check-not-predicate (symbol? #ignore))
+($check-not-predicate (symbol? (make-environment)))
+($check-not-predicate (symbol? #inert))
+($check-not-predicate (symbol? wrap))
+($check-not-predicate (symbol? (call/cc ($lambda (c) c))))
+($check-not-predicate (symbol? ($let (((enc . #ignore)
+ (make-encapsulation-type)))
+ (enc #inert))))
+($check-not-predicate (symbol? (memoize #inert)))
+($check-not-predicate (symbol? 1))
+;($check-not-predicate (symbol? 1.0))
+($check-not-predicate (symbol? #e+infinity))
+;($check-not-predicate (symbol? #i+infinity))
+;($check-not-predicate (symbol? #undefined))
+;($check-not-predicate (symbol? #real-with-no-primary-value))
+($check-not-predicate (symbol? "string"))
+($check-not-predicate (symbol? #\a))
+($check-not-predicate (symbol? (get-current-input-port)))
diff --git a/src/tests/test-all.k b/src/tests/test-all.k
@@ -0,0 +1,18 @@
+(load "tests/check.k")
+(load "tests/test-helpers.k")
+
+;(check-set-mode! check-mode-report)
+
+;; TODO add applicative?/operative? check in pairs and lists and pair-mutation
+
+(load "tests/booleans.k")
+(load "tests/eq-equal.k")
+(load "tests/symbols.k")
+(load "tests/control.k")
+(load "tests/pairs-and-lists.k")
+(load "tests/pair-mutation.k")
+(load "tests/environments.k")
+(load "tests/environment-mutation.k")
+(load "tests/combiners.k")
+
+(check-report)
+\ No newline at end of file
diff --git a/src/tests/test-helpers.k b/src/tests/test-helpers.k
@@ -0,0 +1,27 @@
+;;;
+;;; Some helpers used in many modules
+;;; (check.k should be loaded)
+;;;
+
+($define! not-eq? ($lambda (x y) (not? (eq? x y))))
+($define! not-equal? ($lambda (x y) (not? (equal? x y))))
+($define! $check-predicate ($vau (x) denv (eval (list $check eq? x #t) denv)))
+($define! $check-not-predicate ($vau (x) denv (eval (list $check eq? x #f) denv)))
+
+($define! mutable-pair?
+ ($lambda (obj)
+ ($and? (pair? obj)
+ (guard-dynamic-extent
+ ()
+ ($lambda ()
+ (set-car! obj (car obj))
+ #t)
+ ;; As per the report (section 4.7.1) setting the car of an
+ ;; immutable pair (even if the value is the same) should
+ ;; signal an error.
+ (list (list error-continuation
+ ($lambda (#ignore divert)
+ (apply divert #f))))))))
+
+($define! immutable-pair?
+ ($lambda (obj) ($and? (pair? obj) (not? (mutable-pair? obj)))))
+\ No newline at end of file