klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 6b41fabf449cad75d83e9c360e63c753445750a9
parent 8b7448513049c48bad659906b321f76376ab192c
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sun,  5 Jun 2011 01:51:31 -0300

Merged split ground

Diffstat:
M.hgignore | 1+
MCOPYRIGHT | 1+
Amanual/html/A-Sample-Applicative-Description.html | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Acknowledgements.html | 44++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Booleans.html | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Caveats.html | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Characters.html | 41+++++++++++++++++++++++++++++++++++++++++
Amanual/html/Combiners.html | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Continuations.html | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Control.html | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Conventions.html | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Encapsulations.html | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Environments.html | 330+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Equivalence.html | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Error-Messages.html | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Evaluation-Notation.html | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Format-of-Descriptions.html | 47+++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Index.html | 275+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Introduction.html | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Kernel-History.html | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Keyed-Variables.html | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/License.html | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Numbers.html | 41+++++++++++++++++++++++++++++++++++++++++
Amanual/html/Pairs-and-lists.html | 466+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Ports.html | 325+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Printing-Notation.html | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Promises.html | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Some-Terms.html | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/Strings.html | 41+++++++++++++++++++++++++++++++++++++++++
Amanual/html/Symbols.html | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/html/index.html | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/klisp.info | 2038+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/Makefile | 28++++++++++++++++++++++++++++
Amanual/src/booleans.texi | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/characters.texi | 8++++++++
Amanual/src/combiners.texi | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/continuations.texi | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/control.texi | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/encapsulations.texi | 43+++++++++++++++++++++++++++++++++++++++++++
Amanual/src/environments.texi | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/equivalence.texi | 27+++++++++++++++++++++++++++
Amanual/src/index.texi | 10++++++++++
Amanual/src/intro.texi | 336+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/keyed_vars.texi | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/klisp.texi | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/numbers.texi | 8++++++++
Amanual/src/pairs_lists.texi | 415+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/ports.texi | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/promises.texi | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amanual/src/strings.texi | 8++++++++
Amanual/src/symbols.texi | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/Makefile | 343++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/kgbooleans.c | 21+++++++++++++++++++++
Msrc/kgbooleans.h | 3+++
Msrc/kgchars.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgchars.h | 3+++
Msrc/kgcombiners.c | 30++++++++++++++++++++++++++++++
Msrc/kgcombiners.h | 3+++
Msrc/kgcontinuations.c | 41++++++++++++++++++++++++++++++++++++++++-
Msrc/kgcontinuations.h | 3+++
Msrc/kgcontrol.c | 19+++++++++++++++++++
Msrc/kgcontrol.h | 3+++
Msrc/kgencapsulations.c | 11+++++++++++
Msrc/kgencapsulations.h | 3+++
Msrc/kgenv_mut.c | 16++++++++++++++++
Msrc/kgenv_mut.h | 3+++
Msrc/kgenvironments.c | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/kgenvironments.h | 3+++
Msrc/kgeqp.c | 10++++++++++
Msrc/kgeqp.h | 3+++
Msrc/kgequalp.c | 12+++++++++++-
Msrc/kgequalp.h | 3+++
Msrc/kghelpers.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgkd_vars.c | 10++++++++++
Msrc/kgkd_vars.h | 3+++
Msrc/kgks_vars.c | 12++++++++++++
Msrc/kgks_vars.h | 3+++
Msrc/kgnumbers.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgnumbers.h | 3+++
Msrc/kgpair_mut.c | 24++++++++++++++++++++++++
Msrc/kgpair_mut.h | 3+++
Msrc/kgpairs_lists.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgpairs_lists.h | 3+++
Msrc/kgports.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgports.h | 3+++
Msrc/kgpromises.c | 17+++++++++++++++++
Msrc/kgpromises.h | 3+++
Msrc/kground.c | 1116++-----------------------------------------------------------------------------
Msrc/kgstrings.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/kgstrings.h | 20+++-----------------
Msrc/kgsymbols.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kgsymbols.h | 20++++++++++++++++++++
Msrc/klisp.h | 1+
Msrc/klispconf.h | 27+++++++++++++++++++++++++++
Msrc/kport.c | 2+-
Asrc/tests/booleans.k | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/check.k | 408+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/combiners.k | 320+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/control.k | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/environment-mutation.k | 8++++++++
Asrc/tests/environments.k | 9+++++++++
Asrc/tests/eq-equal.k | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/pair-mutation.k | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/pairs-and-lists.k | 447+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/symbols.k | 38++++++++++++++++++++++++++++++++++++++
Asrc/tests/test-all.k | 19+++++++++++++++++++
Asrc/tests/test-helpers.k | 28++++++++++++++++++++++++++++
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:&nbsp;<a rel="previous" accesskey="p" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>, +Up:&nbsp;<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"> +&mdash; 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) + &rArr; 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:&nbsp;<a rel="previous" accesskey="p" href="Conventions.html#Conventions">Conventions</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Equivalence.html#Equivalence">Equivalence</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Operative: <b>$and?</b> (<var>$and? . &lt;list&gt;</var>)<var><a name="index-g_t_0024and_003f-17"></a></var><br> +<blockquote><p> The <code>$and?</code> operative performs a &ldquo;short-circuit and&rdquo; 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>&lt;list&gt;</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>&lt;list&gt;</code> is acyclic, and the last operand is +<!-- TODO cross ref tail-contect --> +evaluated, it is evaluated as a tail context. If <code>&lt;list&gt;</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"> +&mdash; Operative: <b>$or?</b> (<var>$or? . &lt;list&gt;</var>)<var><a name="index-g_t_0024or_003f-18"></a></var><br> +<blockquote><p> The <code>$or?</code> operative performs a &ldquo;short-circuit or&rdquo; 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>&lt;list&gt;</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>&lt;list&gt;</code> is acyclic, and the last operand is +<!-- TODO cross ref tail-context --> +evaluated, it is evaluated as a tail context. If <code>&lt;list&gt;</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:&nbsp;<a rel="next" accesskey="n" href="Kernel-History.html#Kernel-History">Kernel History</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>, +Up:&nbsp;<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"> &ndash;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:&nbsp;<a rel="next" accesskey="n" href="Ports.html#Ports">Ports</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Strings.html#Strings">Strings</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Continuations.html#Continuations">Continuations</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Environments.html#Environments">Environments</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Operative: <b>$vau</b> (<var>$vau &lt;formals&gt; &lt;eformal&gt; . &lt;objects&gt;</var>)<var><a name="index-g_t_0024vau-119"></a></var><br> +<blockquote><!-- TODO add xref to formal parameter tree --> + <p><code>&lt;formals&gt;</code> should be a formal parameter tree; <code>&lt;eformal&gt;</code> +should be either a symbol or <code>#ignore</code>. If <code>&lt;formals&gt;</code> does +not have the correct form for a formal parameter tree, or if +<code>&lt;eformal&gt;</code> is a symbol that also occurs in <code>&lt;formals&gt;</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>&lt;formals&gt;</code> and <code>&lt;objects&gt;</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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Operative: <b>$lambda</b> (<var>$lambda &lt;formals&gt; . &lt;objects&gt;</var>)<var><a name="index-g_t_0024lambda-122"></a></var><br> +<blockquote><p> <code>&lt;formals&gt;</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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Encapsulations.html#Encapsulations">Encapsulations</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Combiners.html#Combiners">Combiners</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Applicative: <b>continuation-&gt;applicative</b> (<var>continuation-&gt;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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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-&gt;applicative</code>, and then +applies it as usual. + + <p>That is: + <pre class="example"> (apply-continuation continuation object) == + (apply (continuation-&gt;applicative continuation) object) +</pre> + </blockquote></div> + +<div class="defun"> +&mdash; Operative: <b>(</b><var>$let/cc &lt;symbol&gt; . &lt;objects&gt;</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>&lt;symbol&gt;</code> to the continuation to which +the result of the call to <code>$let/cc</code> should normally return; then, +the subexpressions of <code>&lt;objects&gt;</code> are evaluated in <code>e</code> from +left to right, with the last (if any) evaluated as a tail context, or +if <code>&lt;objects&gt;</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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Symbols.html#Symbols">Symbols</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; Operative: <b>$if</b> (<var>$if &lt;test&gt; &lt;consequent&gt; &lt;alternative&gt;</var>)<var><a name="index-g_t_0024if-29"></a></var><br> +<blockquote><p> The <code>$if</code> operative first evaluates <code>&lt;test&gt;</code> in the +dynamic environment. If the result is not of type boolean, an error +is signaled. If the result is true, <code>&lt;consequent&gt;</code> is then +<!-- TODO add xref to tail context --> +evaluated in the dynamic environment as a tail context. Otherwise, +<code>&lt;alternative&gt;</code> is evaluated in the dynamic environment as a tail +context. +</p></blockquote></div> + +<div class="defun"> +&mdash; Operative: <b>$sequence</b> (<var>$sequence . &lt;objects&gt;</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>&lt;objects&gt;</code> in the dynamic environment, one at a time from left +to right. If <code>&lt;objects&gt;</code> is a cyclic list, element evaluation +continues indefinitely, with elements in the cycle being evaluated +repeatedly. If <code>&lt;objects&gt;</code> is a nonempty finite list, its last +<!-- TODO add xref for tail context. --> +element is evaluated as a tail context. If <code>&lt;objects&gt;</code> is the +empty list, the result is inert. +</p></blockquote></div> + +<div class="defun"> +&mdash; Operative: <b>$cond</b> (<var>$cond . &lt;clauses&gt;</var>)<var><a name="index-g_t_0024cond-31"></a></var><br> +<blockquote><p><code>&lt;clauses&gt;</code> should be a list of clause expressions, each of the +form <code>(&lt;test&gt; . &lt;body&gt;)</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 (&lt;test&gt; . &lt;body&gt;) . &lt;clauses&gt;) == + ($if &lt;test&gt; ($sequence . &lt;body&gt;) ($cond . &lt;clauses&gt;)) +</pre> + </blockquote></div> + +<div class="defun"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Acknowledgements.html#Acknowledgements">Acknowledgements</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Kernel-History.html#Kernel-History">Kernel History</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Promises.html#Promises">Promises</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Continuations.html#Continuations">Continuations</a>, +Up:&nbsp;<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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Combiners.html#Combiners">Combiners</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Pairs-and-lists.html#Pairs-and-lists">Pairs and lists</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Operative: <b>$define!</b> (<var>$define! &lt;definiend&gt; &lt;expression&gt;</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>&lt;definiend&gt;</code> should be a formal parameter tree, as described +below; otherwise, an error is signaled. + + <p>The <code>$define!</code> operative evaluates <code>&lt;expression&gt;</code> in the +dynamic environment and matches <code>&lt;definiend&gt;</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>&lt;definiend&gt;</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"> +&mdash; Operative: <b>$let</b> (<var>$let &lt;bindings&gt; . &lt;objects&gt;</var>)<var><a name="index-g_t_0024let-100"></a></var><br> +<blockquote><!-- TODO add xref to formal parameter tree --> + <p><code>&lt;bindings&gt;</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"> +&mdash; Operative: <b>$binds?</b> (<var>$binds? &lt;exp&gt; . &lt;symbols&gt;</var>)<var><a name="index-g_t_0024binds_003f-101"></a></var><br> +<blockquote><p> Operative <code>$binds</code> evaluates <code>&lt;exp&gt;</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>&lt;symbols&gt;</code>, are visibly bound in <code>env</code>. +</p></blockquote></div> + +<div class="defun"> +&mdash; 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"> +&mdash; 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"> +&mdash; Operative: <b>$let*</b> (<var>$let* &lt;bindings&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024let_002a-104"></a></var><br> +<blockquote><!-- TODO add xref to formal ptree --> + <p><code>&lt;bindings&gt;</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>&lt;body&gt;</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"> +&mdash; Operative: <b>$letrec</b> (<var>$letrec &lt;bindings&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024letrec-105"></a></var><br> +<blockquote><!-- add xref for $let --> + <p><code>&lt;bindings&gt;</code> and <code>&lt;body&gt;</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"> +&mdash; Operative: <b>$letrec*</b> (<var>$letrec* &lt;bindings&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024letrec_002a-106"></a></var><br> +<blockquote><!-- TODO add xref to $let* --> + <p><code>&lt;bindings&gt;</code> and <code>&lt;body&gt;</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"> +&mdash; Operative: <b>$let-redirect</b> (<var>$let-redirect &lt;exp&gt; &lt;bindings&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024let_002dredirect-107"></a></var><br> +<blockquote><!-- TODO add xref to $let --> + <p><code>&lt;bindings&gt;</code> and <code>&lt;body&gt;</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"> +&mdash; Operative: <b>$let-safe</b> (<var>$let-safe &lt;bindings&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024let_002dsafe-108"></a></var><br> +<blockquote><!-- TODO add xref to $let --> + <p><code>&lt;bindings&gt;</code> and <code>&lt;body&gt;</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"> +&mdash; Operative: <b>$remote-eval</b> (<var>$remote-eval &lt;exp1&gt; &lt;exp2&gt;</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>&lt;exp2&gt;</code> in the dynamic +environment, then evaluates <code>&lt;exp1&gt;</code> as a tail context in the +environment that must result from the first evaluation. +</p></blockquote></div> + +<div class="defun"> +&mdash; Operative: <b>(</b><var>$bindings-environment . &lt;bindings&gt;</var>)<var><a name="index-g_t_0028-110"></a></var><br> +<blockquote><!-- TODO add xref to $let --> + <p><code>&lt;bindings&gt;</code> should be as described for <code>$let</code>. + + <p>The following equivalence holds: + + <pre class="example"> ($bindings-&gt;environment . bindings) == + ($let-redirect (make-environment) bindings (get-current-environment)) +</pre> + </blockquote></div> + +<div class="defun"> +&mdash; Operative: <b>$set!</b> (<var>$set! &lt;exp1&gt; &lt;formals&gt; &lt;exp2&gt;</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>&lt;formals&gt;</code> should be as described for the <code>$define!</code> +operative. The <code>$set!</code> operative evaluates <code>&lt;exp1&gt;</code> and +<code>&lt;exp2&gt;</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>&lt;formals&gt;</code> to <code>obj</code> +in environment <code>env</code>. Thus, the symbols of <code>&lt;formals&gt;</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"> +&mdash; Operative: <b>$provide!</b> (<var>$provide! &lt;symbols&gt; . &lt;body&gt;</var>)<var><a name="index-g_t_0024provide_0021-112"></a></var><br> +<blockquote><p> <code>&lt;symbols&gt;</code> must be a finite list of symbols, containing no +duplicates. <code>&lt;body&gt;</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>&lt;body&gt;</code> +in <code>e</code>, from left to right, discarding all of the results; and +exports all of the bindings of symbols in <code>&lt;symbols&gt;</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"> +&mdash; Operative: <b>$import!</b> (<var>$import! &lt;exp&gt; . &lt;symbols&gt;</var>)<var><a name="index-g_t_0024import_0021-113"></a></var><br> +<blockquote><p> <code>&lt;symbols&gt;</code> must be a list of symbols. + + <p>The <code>$import!</code> operative evaluates <code>&lt;exp&gt;</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>&lt;symbols&gt;</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:&nbsp;<a rel="next" accesskey="n" href="Symbols.html#Symbols">Symbols</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Booleans.html#Booleans">Booleans</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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> +&ldquo;look&rdquo; 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:&nbsp;<a rel="next" accesskey="n" href="Format-of-Descriptions.html#Format-of-Descriptions">Format of Descriptions</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Printing-Notation.html#Printing-Notation">Printing Notation</a>, +Up:&nbsp;<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 +&lsquo;<samp><span class="samp">error--&gt;</span></samp>&rsquo;. + +<pre class="example"> (+ 23 #t) + error--&gt; 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:&nbsp;<a rel="next" accesskey="n" href="Printing-Notation.html#Printing-Notation">Printing Notation</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Some-Terms.html#Some-Terms">Some Terms</a>, +Up:&nbsp;<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 &lsquo;<samp><span class="samp">&rArr;</span></samp>&rsquo;: + +<pre class="example"> (car (cons 1 2)) + &rArr; 1 +</pre> + <p class="noindent">You can read this as &ldquo;<code>(car (cons 1 2))</code> evaluates to 1&rdquo;. + + <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 &lsquo;<samp><span class="samp">==</span></samp>&rsquo;. 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:&nbsp;<a rel="previous" accesskey="p" href="Error-Messages.html#Error-Messages">Error Messages</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="../index.html#dir">(dir)</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Ports.html#Ports">Ports</a>, +Up:&nbsp;<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-&gt;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-&gt;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-&gt;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:&nbsp;<a rel="next" accesskey="n" href="Booleans.html#Booleans">Booleans</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="License.html#License">License</a>, +Up:&nbsp;<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 &amp; 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:&nbsp;<a rel="next" accesskey="n" href="Conventions.html#Conventions">Conventions</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Caveats.html#Caveats">Caveats</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Numbers.html#Numbers">Numbers</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Promises.html#Promises">Promises</a>, +Up:&nbsp;<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 &amp; 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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Introduction.html#Introduction">Introduction</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="index.html#Top">Top</a>, +Up:&nbsp;<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 &amp; IMath, are also distributed +under the MIT license. + + <ul> +<li>klisp Parts: Copyright &copy; 2011 Andres Navarro. +<li>Lua Parts: Copyright &copy; 1994-2010 Lua.org, PUC-Rio. +<li>IMath Parts: Copyright &copy; 2002-2007 Michael J. Fromberger. +<li>srfi-78: Copyright &copy; 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:&nbsp;<a rel="next" accesskey="n" href="Strings.html#Strings">Strings</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Environments.html#Environments">Environments</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Control.html#Control">Control</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; Applicative: <b>set-car!</b> (<var>set-car! pair object</var>)<var><a name="index-set_002dcar_0021-40"></a></var><br> +&mdash; 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"> +&mdash; 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 +&ldquo;-es-&rdquo; in the name is short for &ldquo;evaluation structure&rdquo;. + + <!-- 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 &ldquo;as is&rdquo; in the result. klisp doesn't copy immutable pairs, but +that behaviour should not be depended upon. +</p></blockquote></div> + +<div class="defun"> +&mdash; 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"> +&mdash; 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"> +&mdash; Applicative: <b>car</b> (<var>car pair</var>)<var><a name="index-car-45"></a></var><br> +&mdash; 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"> +&mdash; Applicative: <b>caar</b> (<var>caar pair</var>)<var><a name="index-caar-47"></a></var><br> +&mdash; Applicative: <b>cadr</b> (<var>cadr pair</var>)<var><a name="index-cadr-48"></a></var><br> +&mdash; Applicative: <b>cdar</b> (<var>cdar pair</var>)<var><a name="index-cdar-49"></a></var><br> +&mdash; Applicative: <b>cddr</b> (<var>cddr pair</var>)<var><a name="index-cddr-50"></a></var><br> +&mdash; Applicative: <b>caaar</b> (<var>caaar pair</var>)<var><a name="index-caaar-51"></a></var><br> +&mdash; Applicative: <b>caadr</b> (<var>caadr pair</var>)<var><a name="index-caadr-52"></a></var><br> +&mdash; Applicative: <b>cadar</b> (<var>cadar pair</var>)<var><a name="index-cadar-53"></a></var><br> +&mdash; Applicative: <b>caddr</b> (<var>caddr pair</var>)<var><a name="index-caddr-54"></a></var><br> +&mdash; Applicative: <b>cdaar</b> (<var>cdaar pair</var>)<var><a name="index-cdaar-55"></a></var><br> +&mdash; Applicative: <b>cdadr</b> (<var>cdadr pair</var>)<var><a name="index-cdadr-56"></a></var><br> +&mdash; Applicative: <b>cddar</b> (<var>cddar pair</var>)<var><a name="index-cddar-57"></a></var><br> +&mdash; Applicative: <b>cdddr</b> (<var>cdddr pair</var>)<var><a name="index-cdddr-58"></a></var><br> +&mdash; Applicative: <b>caaaar</b> (<var>caaaar pair</var>)<var><a name="index-caaaar-59"></a></var><br> +&mdash; Applicative: <b>caaadr</b> (<var>caaadr pair</var>)<var><a name="index-caaadr-60"></a></var><br> +&mdash; Applicative: <b>caadar</b> (<var>caadar pair</var>)<var><a name="index-caadar-61"></a></var><br> +&mdash; Applicative: <b>caaddr</b> (<var>caaddr pair</var>)<var><a name="index-caaddr-62"></a></var><br> +&mdash; Applicative: <b>cadaar</b> (<var>cadaar pair</var>)<var><a name="index-cadaar-63"></a></var><br> +&mdash; Applicative: <b>cadadr</b> (<var>cadadr pair</var>)<var><a name="index-cadadr-64"></a></var><br> +&mdash; Applicative: <b>caddar</b> (<var>caddar pair</var>)<var><a name="index-caddar-65"></a></var><br> +&mdash; Applicative: <b>cadddr</b> (<var>cadddr pair</var>)<var><a name="index-cadddr-66"></a></var><br> +&mdash; Applicative: <b>cdaaar</b> (<var>cdaaar pair</var>)<var><a name="index-cdaaar-67"></a></var><br> +&mdash; Applicative: <b>cdaadr</b> (<var>cdaadr pair</var>)<var><a name="index-cdaadr-68"></a></var><br> +&mdash; Applicative: <b>cdadar</b> (<var>cdadar pair</var>)<var><a name="index-cdadar-69"></a></var><br> +&mdash; Applicative: <b>cdaddr</b> (<var>cdaddr pair</var>)<var><a name="index-cdaddr-70"></a></var><br> +&mdash; Applicative: <b>cddaar</b> (<var>cddaar pair</var>)<var><a name="index-cddaar-71"></a></var><br> +&mdash; Applicative: <b>cddadr</b> (<var>cddadr pair</var>)<var><a name="index-cddadr-72"></a></var><br> +&mdash; Applicative: <b>cdddar</b> (<var>cdddar pair</var>)<var><a name="index-cdddar-73"></a></var><br> +&mdash; 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 &ldquo;a’s&rdquo; and &ldquo;d’s&rdquo; in the same order as they would appear if all +the individual &ldquo;car’s&rdquo; and &ldquo;cdr’s&rdquo; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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 &gt; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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)) &rArr; ((1 2) (2 3) (3 4)) +</pre> + </blockquote></div> + +<div class="defun"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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 &gt;= 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Index.html#Index">Index</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Characters.html#Characters">Characters</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; Applicative: <b>input-port?</b> (<var>input-port? . objects</var>)<var><a name="index-input_002dport_003f-155"></a></var><br> +&mdash; 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"> +&mdash; 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> +&mdash; 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 &amp; output-port +keyed dynamic variables respectively with the opened port &amp; 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"> +&mdash; get-current-input-port: <b>(</b><var>get-current-input-port</var>)<var><a name="index-g_t_0028-159"></a></var><br> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; close-input-file: <b>(</b><var>close-input-file input-port</var>)<var><a name="index-g_t_0028-163"></a></var><br> +&mdash; 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 &amp; close-output-port. +</p></blockquote></div> + +<div class="defun"> +&mdash; 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 &amp; 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"> +&mdash; 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"> +&mdash; 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> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Error-Messages.html#Error-Messages">Error Messages</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a>, +Up:&nbsp;<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 +&lsquo;<samp><span class="samp">-|</span></samp>&rsquo;. 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 + &rArr; #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:&nbsp;<a rel="next" accesskey="n" href="Keyed-Variables.html#Keyed-Variables">Keyed Variables</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Encapsulations.html#Encapsulations">Encapsulations</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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"> +&mdash; 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:&nbsp;<a rel="next" accesskey="n" href="Evaluation-Notation.html#Evaluation-Notation">Evaluation Notation</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Conventions.html#Conventions">Conventions</a>, +Up:&nbsp;<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 &ldquo;the Kernel reader&rdquo; and &ldquo;the Kernel +printer&rdquo; 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 &ldquo;the programmer&rdquo; or +&ldquo;the user&rdquo;. + + <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:&nbsp;<a rel="next" accesskey="n" href="Characters.html#Characters">Characters</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Numbers.html#Numbers">Numbers</a>, +Up:&nbsp;<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:&nbsp;<a rel="next" accesskey="n" href="Control.html#Control">Control</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="Equivalence.html#Equivalence">Equivalence</a>, +Up:&nbsp;<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"> +&mdash; 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"> +&mdash; Applicative: <b>symbol-&gt;string</b> (<var>symbol-&gt;string symbol</var>)<var><a name="index-symbol_002d_003estring-24"></a></var><br> +<blockquote><p> Applicative <code>symbol-&gt;string</code> returns the name of <code>symbol</code> +as a string. The string returned is immutable. +</p></blockquote></div> + +<div class="defun"> +&mdash; Applicative: <b>string-&gt;symbol</b> (<var>string-&gt;symbol string</var>)<var><a name="index-string_002d_003esymbol-25"></a></var><br> +<blockquote><p> Applicative <code>string-&gt;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? &lt;symbol&gt; (string-&gt;symbol (symbol-&gt;string &lt;symbol&gt;))) + &rArr; #t +</pre> + <!-- TODO add xrefs for external representation --> + <p><code>string-&gt;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:&nbsp;<a rel="next" accesskey="n" href="License.html#License">License</a>, +Previous:&nbsp;<a rel="previous" accesskey="p" href="../index.html#dir">(dir)</a>, +Up:&nbsp;<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 &amp; 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 &amp; 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