From bd034b6eb04bd59bf70bcd73f04378dbad822fdb Mon Sep 17 00:00:00 2001
From: Gareth Rees
Date: Wed, 14 Nov 2012 14:13:19 +0000
Subject: [PATCH] Update html.
Copied from Perforce
Change: 180468
ServerID: perforce.ravenbrook.com
---
mps/manual/html/_downloads/scheme-advanced.c | 244 +++++++++++++++++--
mps/manual/html/_downloads/scheme-malloc.c | 237 ++++++++++++++++--
mps/manual/html/_downloads/scheme.c | 237 ++++++++++++++++--
mps/manual/html/_sources/guide/debug.txt | 2 +
mps/manual/html/_sources/guide/perf.txt | 95 ++++++--
mps/manual/html/_sources/mmref/lang.txt | 8 +-
mps/manual/html/_sources/topic/arena.txt | 8 +
mps/manual/html/_sources/topic/low.txt | 14 --
mps/manual/html/glossary/f.html | 2 +-
mps/manual/html/guide/debug.html | 2 +-
mps/manual/html/guide/perf.html | 231 +++++++++++++++---
mps/manual/html/mmref/lang.html | 8 +-
mps/manual/html/objects.inv | Bin 21262 -> 21276 bytes
mps/manual/html/pool/index.html | 8 +-
mps/manual/html/pool/intro.html | 2 +-
mps/manual/html/searchindex.js | 2 +-
mps/manual/html/todo.html | 2 +-
mps/manual/html/topic/arena.html | 8 +
mps/manual/html/topic/critical.html | 2 +-
mps/manual/html/topic/format.html | 2 +-
mps/manual/html/topic/low.html | 110 ---------
21 files changed, 966 insertions(+), 258 deletions(-)
delete mode 100644 mps/manual/html/_sources/topic/low.txt
delete mode 100644 mps/manual/html/topic/low.html
diff --git a/mps/manual/html/_downloads/scheme-advanced.c b/mps/manual/html/_downloads/scheme-advanced.c
index 868250af370..4e9860a806c 100644
--- a/mps/manual/html/_downloads/scheme-advanced.c
+++ b/mps/manual/html/_downloads/scheme-advanced.c
@@ -1,6 +1,6 @@
/* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM
*
- * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme-advanced.c#17 $
+ * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme-advanced.c#21 $
* Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license.
*
* This is a toy interpreter for a subset of the Scheme programming
@@ -29,7 +29,7 @@
*
* SCHEME TO DO LIST
* - unbounded integers, other number types.
- * - do, named let.
+ * - named let.
* - quasiquote: vectors; nested; dotted.
* - Lots of library.
* - \#foo unsatisfactory in read and print
@@ -1919,10 +1919,85 @@ static obj_t entry_letrec(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_do -- (do (() ...) ( ...) ...) */
-
+/* entry_do -- (do (() ...) ( ...) ...)
+ * Do is an iteration construct. It specifies a set of variables to be
+ * bound, how they are to be initialized at the start, and how they
+ * are to be updated on each iteration. When a termination condition
+ * is met, the loop exits with a specified result value.
+ * See R4RS 4.2.4.
+ */
static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
+ obj_t inner_env, next_env, bindings;
+ unless(TYPE(operands) == TYPE_PAIR &&
+ TYPE(CDR(operands)) == TYPE_PAIR &&
+ TYPE(CADR(operands)) == TYPE_PAIR)
+ error("%s: illegal syntax", operator->operator.name);
+ inner_env = make_pair(obj_empty, env);
+
+ /* Do expressions are evaluated as follows: The expressions
+ are evaluated (in some unspecified order), the s are
+ bound to fresh locations, the results of the expressions
+ are stored in the bindings of the s, and then the
+ iteration phase begins. */
+ bindings = CAR(operands);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(TYPE(binding) == TYPE_PAIR &&
+ TYPE(CAR(binding)) == TYPE_SYMBOL &&
+ TYPE(CDR(binding)) == TYPE_PAIR &&
+ (CDDR(binding) == obj_empty ||
+ (TYPE(CDDR(binding)) == TYPE_PAIR &&
+ CDDDR(binding) == obj_empty)))
+ error("%s: illegal binding", operator->operator.name);
+ define(inner_env, CAR(binding), eval(env, op_env, CADR(binding)));
+ bindings = CDR(bindings);
+ }
+ for(;;) {
+ /* Each iteration begins by evaluating ; */
+ obj_t test = CADR(operands);
+ if(eval(inner_env, op_env, CAR(test)) == obj_false) {
+ /* if the result is false (see section see section 6.1
+ Booleans), then the expressions are evaluated in
+ order for effect, */
+ obj_t commands = CDDR(operands);
+ while(TYPE(commands) == TYPE_PAIR) {
+ eval(inner_env, op_env, CAR(commands));
+ commands = CDR(commands);
+ }
+ unless(commands == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+
+ /* the expressions are evaluated in some unspecified
+ order, the s are bound to fresh locations, the
+ results of the s are stored in the bindings of the
+ s, and the next iteration begins. */
+ bindings = CAR(operands);
+ next_env = make_pair(obj_empty, inner_env);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(CDDR(binding) == obj_empty)
+ define(next_env, CAR(binding), eval(inner_env, op_env, CADDR(binding)));
+ bindings = CDR(bindings);
+ }
+ inner_env = next_env;
+ } else {
+ /* If evaluates to a true value, then the s
+ are evaluated from left to right and the value of the last
+ is returned as the value of the do expression.
+ If no s are present, then the value of the do
+ expression is unspecified. */
+ obj_t result = obj_undefined;
+ test = CDR(test);
+ while(TYPE(test) == TYPE_PAIR) {
+ result = eval(inner_env, op_env, CAR(test));
+ test = CDR(test);
+ }
+ unless(test == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+ return result;
+ }
+ }
error("%s: unimplemented", operator->operator.name);
return obj_error;
}
@@ -2087,11 +2162,10 @@ static obj_t entry_begin(obj_t env, obj_t op_env, obj_t operator, obj_t operands
/* BUILT-IN FUNCTIONS */
-/* entry_not -- (not )
- *
- * Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
+/* (not )
+ * Not returns #t if obj is false, and return #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2100,11 +2174,10 @@ static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_booleanp -- (boolean? )
- *
- * Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
+/* (boolean? )
+ * Boolean? return #t if obj is either #t or #f, and #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2113,8 +2186,11 @@ static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
-/* entry_eqvp -- (eqv? ) */
-
+/* (eqv? )
+ * The eqv? procedure defines a useful equivalence relation on
+ * objects.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2123,8 +2199,11 @@ static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_eqp -- (eq? ) */
-
+/* (eq? )
+ * Eq? is similar to eqv? except that in some cases it is capable of
+ * discerning distinctions finer than those detectable by eqv?.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2133,8 +2212,6 @@ static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_equalp -- (equal? ) */
-
static int equalp(obj_t obj1, obj_t obj2)
{
size_t i;
@@ -2159,6 +2236,14 @@ static int equalp(obj_t obj1, obj_t obj2)
}
}
+/* (equal? )
+ * Equal? recursively compares the contents of pairs, vectors, and
+ * strings, applying eqv? on other objects such as numbers and
+ * symbols. A rule of thumb is that objects are generally equal? if
+ * they print the same. Equal? may fail to terminate if its arguments
+ * are circular data structures.
+ * See R4RS 6.2.
+ */
static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2167,8 +2252,10 @@ static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_pairp -- (pair? ) */
-
+/* (pair? )
+ * Pair? returns #t if obj is a pair, and otherwise returns #f.
+ * See R4RS 6.3.
+ */
static obj_t entry_pairp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2311,6 +2398,11 @@ static obj_t entry_length(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (append list ...)
+ * Returns a list consisting of the elements of the first list
+ * followed by the elements of the other lists.
+ * See R4RS 6.3.
+ */
static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2, result, pair, end;
@@ -2334,6 +2426,12 @@ static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (integer? obj)
+ * These numerical type predicates can be applied to any kind of
+ * argument, including non-numbers. They return #t if the object is of
+ * the named type, and otherwise they return #f.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_integerp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2430,6 +2528,10 @@ static obj_t entry_apply(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (+ z1 ...)
+ * This procedure returns the sum of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2447,6 +2549,10 @@ static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
+/* (* z1 ...)
+ * This procedure returns the product of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2464,6 +2570,14 @@ static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (- z)
+ * (- z1 z2)
+ * (- z1 z2 ...)
+ * With two or more arguments, this procedure returns the difference
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the additive inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2487,6 +2601,14 @@ static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (/ z)
+ * (/ z1 z2)
+ * (/ z1 z2 ...)
+ * With two or more arguments, this procedure returns the quotient
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the multiplicative inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2514,6 +2636,11 @@ static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (< x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * increasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2535,6 +2662,11 @@ static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (> x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * decreasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_greaterthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2777,8 +2909,15 @@ static obj_t entry_load(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* TODO: This doesn't work if the promise refers to its own value. */
-
+/* (force promise)
+ * Forces the value of promise. If no value has been computed for the
+ * promise, then a value is computed and returned. The value of the
+ * promise is cached (or "memoized") so that if it is forced a second
+ * time, the previously computed value is returned.
+ * See R4RS 6.9.
+ *
+ * TODO: This doesn't work if the promise refers to its own value.
+ */
static obj_t entry_force(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t promise;
@@ -2842,6 +2981,10 @@ static obj_t entry_integer_to_char(obj_t env, obj_t op_env, obj_t operator, obj_
}
+/* (vector? obj)
+ * Returns #t if obj is a vector, otherwise returns #f.
+ * See R4RS 6.8.
+ */
static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2850,6 +2993,13 @@ static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operan
}
+/* (make-vector k)
+ * (make-vector k fill)
+ * Returns a newly allocated vector of k elements. If a second
+ * argument is given, then each element is initialized to fill.
+ * Otherwise the initial contents of each element is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t length, rest, fill = obj_undefined;
@@ -2865,6 +3015,11 @@ static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t op
}
+/* (vector obj ...)
+ * Returns a newly allocated vector whose elements contain the given
+ * arguments. Analogous to list.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t rest, vector;
@@ -2875,6 +3030,10 @@ static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (vector-length vector)
+ * Returns the number of elements in vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector;
@@ -2885,6 +3044,11 @@ static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-ref vector k)
+ * k must be a valid index of vector. Vector-ref returns the contents
+ * of element k of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index;
@@ -2900,6 +3064,12 @@ static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector-set! vector k obj
+ * k must be a valid index of vector. Vector-set! stores obj in
+ * element k of vector. The value returned by vector-set! is
+ * unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index, obj;
@@ -2916,6 +3086,11 @@ static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector->list vector)
+ * Vector->list returns a newly allocated list of the objects
+ * contained in the elements of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, list;
@@ -2933,6 +3108,11 @@ static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (list->vector list)
+ * List->vector returns a newly created vector initialized to the
+ * elements of the list list.
+ * See R4RS 6.8.
+ */
static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t list, vector;
@@ -2944,6 +3124,11 @@ static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-fill! vector fill)
+ * Stores fill in every element of vector. The value returned by
+ * vector-fill! is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_fill(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, obj;
@@ -2976,6 +3161,10 @@ static obj_t entry_error(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (symbol->string symbol)
+ * Returns the name of symbol as a string.
+ * See R4RS 6.4.
+ */
static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t symbol;
@@ -2986,6 +3175,10 @@ static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj
}
+/* (string->symbol symbol)
+ * Returns the symbol whose name is string.
+ * See R4RS 6.4.
+ */
static obj_t entry_string_to_symbol(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t string;
@@ -4266,8 +4459,9 @@ static void *start(void *p, size_t s)
*/
static mps_gen_param_s obj_gen_params[] = {
- { 150, 0.85 },
- { 170, 0.45 }
+ { 6400, 0.80 },
+ { 6400, 0.80 },
+ { 6400, 0.80 }
};
@@ -4288,7 +4482,7 @@ int main(int argc, char *argv[])
It holds all the MPS "global" state and is where everything happens. */
res = mps_arena_create(&arena,
mps_arena_class_vm(),
- (size_t)(32 * 1024 * 1024));
+ (size_t)(32ul * 1024 * 1024));
if (res != MPS_RES_OK) error("Couldn't create arena");
/* Create the object format. */
diff --git a/mps/manual/html/_downloads/scheme-malloc.c b/mps/manual/html/_downloads/scheme-malloc.c
index 003c9cd7abf..cf94e0210a8 100644
--- a/mps/manual/html/_downloads/scheme-malloc.c
+++ b/mps/manual/html/_downloads/scheme-malloc.c
@@ -1,11 +1,11 @@
/* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM
*
- * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme-malloc.c#18 $
+ * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme-malloc.c#20 $
* Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license.
*
* TO DO
* - unbounded integers, other number types.
- * - do, named let.
+ * - named let.
* - quasiquote: vectors; nested; dotted.
* - Lots of library.
* - \#foo unsatisfactory in read and print
@@ -1649,10 +1649,85 @@ static obj_t entry_letrec(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_do -- (do (() ...) ( ...) ...) */
-
+/* entry_do -- (do (() ...) ( ...) ...)
+ * Do is an iteration construct. It specifies a set of variables to be
+ * bound, how they are to be initialized at the start, and how they
+ * are to be updated on each iteration. When a termination condition
+ * is met, the loop exits with a specified result value.
+ * See R4RS 4.2.4.
+ */
static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
+ obj_t inner_env, next_env, bindings;
+ unless(TYPE(operands) == TYPE_PAIR &&
+ TYPE(CDR(operands)) == TYPE_PAIR &&
+ TYPE(CADR(operands)) == TYPE_PAIR)
+ error("%s: illegal syntax", operator->operator.name);
+ inner_env = make_pair(obj_empty, env);
+
+ /* Do expressions are evaluated as follows: The expressions
+ are evaluated (in some unspecified order), the s are
+ bound to fresh locations, the results of the expressions
+ are stored in the bindings of the s, and then the
+ iteration phase begins. */
+ bindings = CAR(operands);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(TYPE(binding) == TYPE_PAIR &&
+ TYPE(CAR(binding)) == TYPE_SYMBOL &&
+ TYPE(CDR(binding)) == TYPE_PAIR &&
+ (CDDR(binding) == obj_empty ||
+ (TYPE(CDDR(binding)) == TYPE_PAIR &&
+ CDDDR(binding) == obj_empty)))
+ error("%s: illegal binding", operator->operator.name);
+ define(inner_env, CAR(binding), eval(env, op_env, CADR(binding)));
+ bindings = CDR(bindings);
+ }
+ for(;;) {
+ /* Each iteration begins by evaluating ; */
+ obj_t test = CADR(operands);
+ if(eval(inner_env, op_env, CAR(test)) == obj_false) {
+ /* if the result is false (see section see section 6.1
+ Booleans), then the expressions are evaluated in
+ order for effect, */
+ obj_t commands = CDDR(operands);
+ while(TYPE(commands) == TYPE_PAIR) {
+ eval(inner_env, op_env, CAR(commands));
+ commands = CDR(commands);
+ }
+ unless(commands == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+
+ /* the expressions are evaluated in some unspecified
+ order, the s are bound to fresh locations, the
+ results of the s are stored in the bindings of the
+ s, and the next iteration begins. */
+ bindings = CAR(operands);
+ next_env = make_pair(obj_empty, inner_env);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(CDDR(binding) == obj_empty)
+ define(next_env, CAR(binding), eval(inner_env, op_env, CADDR(binding)));
+ bindings = CDR(bindings);
+ }
+ inner_env = next_env;
+ } else {
+ /* If evaluates to a true value, then the s
+ are evaluated from left to right and the value of the last
+ is returned as the value of the do expression.
+ If no s are present, then the value of the do
+ expression is unspecified. */
+ obj_t result = obj_undefined;
+ test = CDR(test);
+ while(TYPE(test) == TYPE_PAIR) {
+ result = eval(inner_env, op_env, CAR(test));
+ test = CDR(test);
+ }
+ unless(test == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+ return result;
+ }
+ }
error("%s: unimplemented", operator->operator.name);
return obj_error;
}
@@ -1817,11 +1892,10 @@ static obj_t entry_begin(obj_t env, obj_t op_env, obj_t operator, obj_t operands
/* BUILT-IN FUNCTIONS */
-/* entry_not -- (not )
- *
- * Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
+/* (not )
+ * Not returns #t if obj is false, and return #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -1830,11 +1904,10 @@ static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_booleanp -- (boolean? )
- *
- * Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
+/* (boolean? )
+ * Boolean? return #t if obj is either #t or #f, and #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -1843,8 +1916,11 @@ static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
-/* entry_eqvp -- (eqv? ) */
-
+/* (eqv? )
+ * The eqv? procedure defines a useful equivalence relation on
+ * objects.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -1853,8 +1929,11 @@ static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_eqp -- (eq? ) */
-
+/* (eq? )
+ * Eq? is similar to eqv? except that in some cases it is capable of
+ * discerning distinctions finer than those detectable by eqv?.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -1863,8 +1942,6 @@ static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_equalp -- (equal? ) */
-
static int equalp(obj_t obj1, obj_t obj2)
{
size_t i;
@@ -1889,6 +1966,14 @@ static int equalp(obj_t obj1, obj_t obj2)
}
}
+/* (equal? )
+ * Equal? recursively compares the contents of pairs, vectors, and
+ * strings, applying eqv? on other objects such as numbers and
+ * symbols. A rule of thumb is that objects are generally equal? if
+ * they print the same. Equal? may fail to terminate if its arguments
+ * are circular data structures.
+ * See R4RS 6.2.
+ */
static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -1897,8 +1982,10 @@ static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_pairp -- (pair? ) */
-
+/* (pair? )
+ * Pair? returns #t if obj is a pair, and otherwise returns #f.
+ * See R4RS 6.3.
+ */
static obj_t entry_pairp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2041,6 +2128,11 @@ static obj_t entry_length(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (append list ...)
+ * Returns a list consisting of the elements of the first list
+ * followed by the elements of the other lists.
+ * See R4RS 6.3.
+ */
static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2, result, pair, end;
@@ -2064,6 +2156,12 @@ static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (integer? obj)
+ * These numerical type predicates can be applied to any kind of
+ * argument, including non-numbers. They return #t if the object is of
+ * the named type, and otherwise they return #f.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_integerp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2160,6 +2258,10 @@ static obj_t entry_apply(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (+ z1 ...)
+ * This procedure returns the sum of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2177,6 +2279,10 @@ static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
+/* (* z1 ...)
+ * This procedure returns the product of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2194,6 +2300,14 @@ static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (- z)
+ * (- z1 z2)
+ * (- z1 z2 ...)
+ * With two or more arguments, this procedure returns the difference
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the additive inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2217,6 +2331,14 @@ static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (/ z)
+ * (/ z1 z2)
+ * (/ z1 z2 ...)
+ * With two or more arguments, this procedure returns the quotient
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the multiplicative inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2244,6 +2366,11 @@ static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (< x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * increasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2265,6 +2392,11 @@ static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (> x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * decreasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_greaterthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2509,8 +2641,15 @@ static obj_t entry_load(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* TODO: This doesn't work if the promise refers to its own value. */
-
+/* (force promise)
+ * Forces the value of promise. If no value has been computed for the
+ * promise, then a value is computed and returned. The value of the
+ * promise is cached (or "memoized") so that if it is forced a second
+ * time, the previously computed value is returned.
+ * See R4RS 6.9.
+ *
+ * TODO: This doesn't work if the promise refers to its own value.
+ */
static obj_t entry_force(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t promise;
@@ -2574,6 +2713,10 @@ static obj_t entry_integer_to_char(obj_t env, obj_t op_env, obj_t operator, obj_
}
+/* (vector? obj)
+ * Returns #t if obj is a vector, otherwise returns #f.
+ * See R4RS 6.8.
+ */
static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2582,6 +2725,13 @@ static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operan
}
+/* (make-vector k)
+ * (make-vector k fill)
+ * Returns a newly allocated vector of k elements. If a second
+ * argument is given, then each element is initialized to fill.
+ * Otherwise the initial contents of each element is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t length, rest, fill = obj_undefined;
@@ -2597,6 +2747,11 @@ static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t op
}
+/* (vector obj ...)
+ * Returns a newly allocated vector whose elements contain the given
+ * arguments. Analogous to list.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t rest, vector;
@@ -2607,6 +2762,10 @@ static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (vector-length vector)
+ * Returns the number of elements in vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector;
@@ -2617,6 +2776,11 @@ static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-ref vector k)
+ * k must be a valid index of vector. Vector-ref returns the contents
+ * of element k of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index;
@@ -2632,6 +2796,12 @@ static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector-set! vector k obj
+ * k must be a valid index of vector. Vector-set! stores obj in
+ * element k of vector. The value returned by vector-set! is
+ * unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index, obj;
@@ -2648,6 +2818,11 @@ static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector->list vector)
+ * Vector->list returns a newly allocated list of the objects
+ * contained in the elements of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, list;
@@ -2665,6 +2840,11 @@ static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (list->vector list)
+ * List->vector returns a newly created vector initialized to the
+ * elements of the list list.
+ * See R4RS 6.8.
+ */
static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t list, vector;
@@ -2676,6 +2856,11 @@ static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-fill! vector fill)
+ * Stores fill in every element of vector. The value returned by
+ * vector-fill! is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_fill(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, obj;
@@ -2708,6 +2893,10 @@ static obj_t entry_error(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (symbol->string symbol)
+ * Returns the name of symbol as a string.
+ * See R4RS 6.4.
+ */
static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t symbol;
@@ -2718,6 +2907,10 @@ static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj
}
+/* (string->symbol symbol)
+ * Returns the symbol whose name is string.
+ * See R4RS 6.4.
+ */
static obj_t entry_string_to_symbol(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t string;
diff --git a/mps/manual/html/_downloads/scheme.c b/mps/manual/html/_downloads/scheme.c
index 3ab01fc9775..138155a04ca 100644
--- a/mps/manual/html/_downloads/scheme.c
+++ b/mps/manual/html/_downloads/scheme.c
@@ -1,6 +1,6 @@
/* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM
*
- * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme.c#32 $
+ * $Id: //info.ravenbrook.com/project/mps/branch/2012-10-09/user-guide/example/scheme/scheme.c#34 $
* Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license.
*
* This is a toy interpreter for a subset of the Scheme programming
@@ -31,7 +31,7 @@
*
* SCHEME TO DO LIST
* - unbounded integers, other number types.
- * - do, named let.
+ * - named let.
* - quasiquote: vectors; nested; dotted.
* - Lots of library.
* - \#foo unsatisfactory in read and print
@@ -1948,10 +1948,85 @@ static obj_t entry_letrec(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_do -- (do (() ...) ( ...) ...) */
-
+/* entry_do -- (do (() ...) ( ...) ...)
+ * Do is an iteration construct. It specifies a set of variables to be
+ * bound, how they are to be initialized at the start, and how they
+ * are to be updated on each iteration. When a termination condition
+ * is met, the loop exits with a specified result value.
+ * See R4RS 4.2.4.
+ */
static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
+ obj_t inner_env, next_env, bindings;
+ unless(TYPE(operands) == TYPE_PAIR &&
+ TYPE(CDR(operands)) == TYPE_PAIR &&
+ TYPE(CADR(operands)) == TYPE_PAIR)
+ error("%s: illegal syntax", operator->operator.name);
+ inner_env = make_pair(obj_empty, env);
+
+ /* Do expressions are evaluated as follows: The expressions
+ are evaluated (in some unspecified order), the s are
+ bound to fresh locations, the results of the expressions
+ are stored in the bindings of the s, and then the
+ iteration phase begins. */
+ bindings = CAR(operands);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(TYPE(binding) == TYPE_PAIR &&
+ TYPE(CAR(binding)) == TYPE_SYMBOL &&
+ TYPE(CDR(binding)) == TYPE_PAIR &&
+ (CDDR(binding) == obj_empty ||
+ (TYPE(CDDR(binding)) == TYPE_PAIR &&
+ CDDDR(binding) == obj_empty)))
+ error("%s: illegal binding", operator->operator.name);
+ define(inner_env, CAR(binding), eval(env, op_env, CADR(binding)));
+ bindings = CDR(bindings);
+ }
+ for(;;) {
+ /* Each iteration begins by evaluating ; */
+ obj_t test = CADR(operands);
+ if(eval(inner_env, op_env, CAR(test)) == obj_false) {
+ /* if the result is false (see section see section 6.1
+ Booleans), then the expressions are evaluated in
+ order for effect, */
+ obj_t commands = CDDR(operands);
+ while(TYPE(commands) == TYPE_PAIR) {
+ eval(inner_env, op_env, CAR(commands));
+ commands = CDR(commands);
+ }
+ unless(commands == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+
+ /* the expressions are evaluated in some unspecified
+ order, the s are bound to fresh locations, the
+ results of the s are stored in the bindings of the
+ s, and the next iteration begins. */
+ bindings = CAR(operands);
+ next_env = make_pair(obj_empty, inner_env);
+ while(TYPE(bindings) == TYPE_PAIR) {
+ obj_t binding = CAR(bindings);
+ unless(CDDR(binding) == obj_empty)
+ define(next_env, CAR(binding), eval(inner_env, op_env, CADDR(binding)));
+ bindings = CDR(bindings);
+ }
+ inner_env = next_env;
+ } else {
+ /* If evaluates to a true value, then the s
+ are evaluated from left to right and the value of the last
+ is returned as the value of the do expression.
+ If no s are present, then the value of the do
+ expression is unspecified. */
+ obj_t result = obj_undefined;
+ test = CDR(test);
+ while(TYPE(test) == TYPE_PAIR) {
+ result = eval(inner_env, op_env, CAR(test));
+ test = CDR(test);
+ }
+ unless(test == obj_empty)
+ error("%s: illegal syntax", operator->operator.name);
+ return result;
+ }
+ }
error("%s: unimplemented", operator->operator.name);
return obj_error;
}
@@ -2116,11 +2191,10 @@ static obj_t entry_begin(obj_t env, obj_t op_env, obj_t operator, obj_t operands
/* BUILT-IN FUNCTIONS */
-/* entry_not -- (not )
- *
- * Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
+/* (not )
+ * Not returns #t if obj is false, and return #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2129,11 +2203,10 @@ static obj_t entry_not(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_booleanp -- (boolean? )
- *
- * Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
+/* (boolean? )
+ * Boolean? return #t if obj is either #t or #f, and #f otherwise.
+ * See R4RS 6.1.
*/
-
static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2142,8 +2215,11 @@ static obj_t entry_booleanp(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
-/* entry_eqvp -- (eqv? ) */
-
+/* (eqv? )
+ * The eqv? procedure defines a useful equivalence relation on
+ * objects.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2152,8 +2228,11 @@ static obj_t entry_eqvp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_eqp -- (eq? ) */
-
+/* (eq? )
+ * Eq? is similar to eqv? except that in some cases it is capable of
+ * discerning distinctions finer than those detectable by eqv?.
+ * See R4RS 6.2.
+ */
static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2162,8 +2241,6 @@ static obj_t entry_eqp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* entry_equalp -- (equal? ) */
-
static int equalp(obj_t obj1, obj_t obj2)
{
size_t i;
@@ -2188,6 +2265,14 @@ static int equalp(obj_t obj1, obj_t obj2)
}
}
+/* (equal? )
+ * Equal? recursively compares the contents of pairs, vectors, and
+ * strings, applying eqv? on other objects such as numbers and
+ * symbols. A rule of thumb is that objects are generally equal? if
+ * they print the same. Equal? may fail to terminate if its arguments
+ * are circular data structures.
+ * See R4RS 6.2.
+ */
static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2;
@@ -2196,8 +2281,10 @@ static obj_t entry_equalp(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
-/* entry_pairp -- (pair? ) */
-
+/* (pair? )
+ * Pair? returns #t if obj is a pair, and otherwise returns #f.
+ * See R4RS 6.3.
+ */
static obj_t entry_pairp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2340,6 +2427,11 @@ static obj_t entry_length(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (append list ...)
+ * Returns a list consisting of the elements of the first list
+ * followed by the elements of the other lists.
+ * See R4RS 6.3.
+ */
static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg1, arg2, result, pair, end;
@@ -2363,6 +2455,12 @@ static obj_t entry_append(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (integer? obj)
+ * These numerical type predicates can be applied to any kind of
+ * argument, including non-numbers. They return #t if the object is of
+ * the named type, and otherwise they return #f.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_integerp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2459,6 +2557,10 @@ static obj_t entry_apply(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (+ z1 ...)
+ * This procedure returns the sum of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2476,6 +2578,10 @@ static obj_t entry_add(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
+/* (* z1 ...)
+ * This procedure returns the product of its arguments.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t args;
@@ -2493,6 +2599,14 @@ static obj_t entry_multiply(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (- z)
+ * (- z1 z2)
+ * (- z1 z2 ...)
+ * With two or more arguments, this procedure returns the difference
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the additive inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2516,6 +2630,14 @@ static obj_t entry_subtract(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (/ z)
+ * (/ z1 z2)
+ * (/ z1 z2 ...)
+ * With two or more arguments, this procedure returns the quotient
+ * of its arguments, associating to the left. With one argument,
+ * however, it returns the multiplicative inverse of its argument.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2543,6 +2665,11 @@ static obj_t entry_divide(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (< x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * increasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2564,6 +2691,11 @@ static obj_t entry_lessthan(obj_t env, obj_t op_env, obj_t operator, obj_t opera
}
+/* (> x1 x2 x3 ...)
+ * This procedure returns #t if its arguments are monotonically
+ * decreasing.
+ * See R4RS 6.5.5.
+ */
static obj_t entry_greaterthan(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg, args;
@@ -2805,8 +2937,15 @@ static obj_t entry_load(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
}
-/* TODO: This doesn't work if the promise refers to its own value. */
-
+/* (force promise)
+ * Forces the value of promise. If no value has been computed for the
+ * promise, then a value is computed and returned. The value of the
+ * promise is cached (or "memoized") so that if it is forced a second
+ * time, the previously computed value is returned.
+ * See R4RS 6.9.
+ *
+ * TODO: This doesn't work if the promise refers to its own value.
+ */
static obj_t entry_force(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t promise;
@@ -2870,6 +3009,10 @@ static obj_t entry_integer_to_char(obj_t env, obj_t op_env, obj_t operator, obj_
}
+/* (vector? obj)
+ * Returns #t if obj is a vector, otherwise returns #f.
+ * See R4RS 6.8.
+ */
static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
@@ -2878,6 +3021,13 @@ static obj_t entry_vectorp(obj_t env, obj_t op_env, obj_t operator, obj_t operan
}
+/* (make-vector k)
+ * (make-vector k fill)
+ * Returns a newly allocated vector of k elements. If a second
+ * argument is given, then each element is initialized to fill.
+ * Otherwise the initial contents of each element is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t length, rest, fill = obj_undefined;
@@ -2893,6 +3043,11 @@ static obj_t entry_make_vector(obj_t env, obj_t op_env, obj_t operator, obj_t op
}
+/* (vector obj ...)
+ * Returns a newly allocated vector whose elements contain the given
+ * arguments. Analogous to list.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t rest, vector;
@@ -2903,6 +3058,10 @@ static obj_t entry_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operand
}
+/* (vector-length vector)
+ * Returns the number of elements in vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector;
@@ -2913,6 +3072,11 @@ static obj_t entry_vector_length(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-ref vector k)
+ * k must be a valid index of vector. Vector-ref returns the contents
+ * of element k of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index;
@@ -2928,6 +3092,12 @@ static obj_t entry_vector_ref(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector-set! vector k obj
+ * k must be a valid index of vector. Vector-set! stores obj in
+ * element k of vector. The value returned by vector-set! is
+ * unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, index, obj;
@@ -2944,6 +3114,11 @@ static obj_t entry_vector_set(obj_t env, obj_t op_env, obj_t operator, obj_t ope
}
+/* (vector->list vector)
+ * Vector->list returns a newly allocated list of the objects
+ * contained in the elements of vector.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, list;
@@ -2961,6 +3136,11 @@ static obj_t entry_vector_to_list(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (list->vector list)
+ * List->vector returns a newly created vector initialized to the
+ * elements of the list list.
+ * See R4RS 6.8.
+ */
static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t list, vector;
@@ -2972,6 +3152,11 @@ static obj_t entry_list_to_vector(obj_t env, obj_t op_env, obj_t operator, obj_t
}
+/* (vector-fill! vector fill)
+ * Stores fill in every element of vector. The value returned by
+ * vector-fill! is unspecified.
+ * See R4RS 6.8.
+ */
static obj_t entry_vector_fill(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t vector, obj;
@@ -3004,6 +3189,10 @@ static obj_t entry_error(obj_t env, obj_t op_env, obj_t operator, obj_t operands
}
+/* (symbol->string symbol)
+ * Returns the name of symbol as a string.
+ * See R4RS 6.4.
+ */
static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t symbol;
@@ -3014,6 +3203,10 @@ static obj_t entry_symbol_to_string(obj_t env, obj_t op_env, obj_t operator, obj
}
+/* (string->symbol symbol)
+ * Returns the symbol whose name is string.
+ * See R4RS 6.4.
+ */
static obj_t entry_string_to_symbol(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t string;
diff --git a/mps/manual/html/_sources/guide/debug.txt b/mps/manual/html/_sources/guide/debug.txt
index 2c10c5ff640..0afd97493b8 100644
--- a/mps/manual/html/_sources/guide/debug.txt
+++ b/mps/manual/html/_sources/guide/debug.txt
@@ -22,6 +22,8 @@ delayed. And even if it does die, the space it occupies may not be
re-allocated for some time.
+.. _guide-debug-advice:
+
General debugging advice
------------------------
diff --git a/mps/manual/html/_sources/guide/perf.txt b/mps/manual/html/_sources/guide/perf.txt
index 3477085b3d2..d9beee520b0 100644
--- a/mps/manual/html/_sources/guide/perf.txt
+++ b/mps/manual/html/_sources/guide/perf.txt
@@ -26,31 +26,55 @@ most of the blocks allocated in that generation should be found to be
entirely). If a generation is collected when its blocks are mostly
alive, that is a waste of time.
-In the table below I give the execution time of ``test-leaf.scm`` in
+In the tables below I give the execution time of ``test-leaf.scm`` in
the toy Scheme interpreter under different settings for its generation
-chain. (This test case allocates millions of small short-lived
-objects.) In each case the AMC pool is given a chain with a single
-generation with the specified capacity and mortality.
+chain. (This test case allocates hundreds of millions of small
+short-lived objects.)
+
+First, the effect of varying the capacity of a chain with a single
+generation.
======== ========= =========================
Capacity Mortality Execution time (user+sys)
======== ========= =========================
-100 0.80 39.9
-200 0.80 30.2
-400 0.80 25.5
-800 0.80 16.3
-1600 0.80 9.0
-3200 0.80 5.8
-6400 0.20 4.2
-6400 0.40 4.1
-6400 0.60 4.1
-6400 0.80 4.1
-6400 0.99 4.2
-12800 0.80 4.2
-25600 0.80 5.2
+100 0.80 362.6
+200 0.80 354.9
+400 0.80 349.7
+800 0.80 314.4
+1600 0.80 215.7
+3200 0.80 94.0
+6400 0.80 53.5
+12800 0.80 79.6
+25600 0.80 77.6
======== ========= =========================
-This table suggests that:
+Second, the effect of varying the mortality of a chain with a single
+generation.
+
+======== ========= =========================
+Capacity Mortality Execution time (user+sys)
+======== ========= =========================
+6400 0.20 55.4
+6400 0.40 54.0
+6400 0.60 54.0
+6400 0.80 53.5
+6400 0.99 54.8
+======== ========= =========================
+
+Third, the effect of varying the number of generations (all
+generations being identical).
+
+=========== ======== ========= =========================
+Generations Capacity Mortality Execution time (user+sys)
+=========== ======== ========= =========================
+1 6400 0.80 53.5
+2 6400 0.80 42.4
+3 6400 0.80 42.1
+4 6400 0.80 42.2
+5 6400 0.80 42.2
+=========== ======== ========= =========================
+
+These tables suggest that:
1. The improvement in performance to be gained by getting generation
sizes right is dramatic: much bigger than the small improvements to
@@ -62,8 +86,43 @@ This table suggests that:
3. You can make generations too big as well as too small.
+4. There are rapidly diminishing returns to be gained from adding
+ generations.
+
.. note::
:ref:`topic-telemetry` can be used to discover when generations
are being collected and what proportion of blocks were found to be
alive.
+
+The table below shows the effect of varying the initial allocation of
+address space to the arena (using three generations each with capacity
+6400 kB, mortality 0.80).
+
+============= ========== =========== =========================
+Address space Extensions Collections Execution time (user+sys)
+============= ========== =========== =========================
+2 32 371 52.0
+4 21 370 47.0
+8 0 [1]_ [1]_
+14 0 [1]_ [1]_
+16 0 2436 160.5
+18 0 1135 89.1
+20 0 673 60.6
+22 0 484 48.7
+24 0 400 43.1
+32 0 368 41.2
+64 0 368 43.1
+128 0 368 46.4
+256 0 368 46.3
+512 0 368 49.3
+============= ========== =========== =========================
+
+.. note::
+
+ .. [1] With this initial allocation of address space, the test
+ case failed to run to completion after thousands of seconds
+ and tens of thousands of garbage collection cycles.
+
+The lesson here is that the allocation of address space has to be
+comfortably larger than the working set of the program.
diff --git a/mps/manual/html/_sources/mmref/lang.txt b/mps/manual/html/_sources/mmref/lang.txt
index 46ca8a91fef..fb4473d525e 100644
--- a/mps/manual/html/_sources/mmref/lang.txt
+++ b/mps/manual/html/_sources/mmref/lang.txt
@@ -94,8 +94,9 @@ Memory management in various languages
COBOL was designed by the CODASYL committee in 1959–60 to be a
business programming language, and has been extended many
- times since. It is still the most widely-used programming
- language (in terms of lines of code in use).
+ times since. A 1997 Gartner Group report estimated that 80% of
+ computer software (by count of source lines) was written in
+ COBOL.
Prior to 2002, COBOL had no :term:`heap allocation`, and did
well in its application domain without it. COBOL 2002 has
@@ -456,7 +457,8 @@ Memory management in various languages
their keys and values can be dynamically switched from being
:term:`strong references` to weak references, and vice versa
(by assigning to the ``__mode`` field of the table's
- metatable).
+ metatable). It also supports :term:`finalization` (by
+ assigning the ``__gc`` field of the object's metatable).
.. link::
diff --git a/mps/manual/html/_sources/topic/arena.txt b/mps/manual/html/_sources/topic/arena.txt
index 166da503a68..f5137796d04 100644
--- a/mps/manual/html/_sources/topic/arena.txt
+++ b/mps/manual/html/_sources/topic/arena.txt
@@ -572,6 +572,14 @@ allocation and scanning code.
If you do not want the arena to remain in the parked state, you
must explicitly call :c:func:`mps_arena_release` afterwards.
+ .. note::
+
+ It is not normally necessary to call this function: in the
+ :term:`unclamped state`, collections start automatically.
+ However, it may be useful during development and debugging:
+ the more frequently the collector runs, the sooner and more
+ reliably errors are discovered. See :ref:`guide-debug-advice`.
+
.. c:function:: mps_res_t mps_arena_start_collect(mps_arena_t arena)
diff --git a/mps/manual/html/_sources/topic/low.txt b/mps/manual/html/_sources/topic/low.txt
deleted file mode 100644
index 2324583558a..00000000000
--- a/mps/manual/html/_sources/topic/low.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _topic-low:
-
-Handling low memory
-===================
-
-What does it mean to be "low on memory" in a virtual memory operating
-system?
-
-How does the MPS behave when it's low on memory? Performance degrades
-(due to running out of zones) and then there are emergency
-collections.
-
-How can you handle low memory situations gracefully while still
-keeping allocation fast and inline?
diff --git a/mps/manual/html/glossary/f.html b/mps/manual/html/glossary/f.html
index 8a7eed138f7..c2e6e341dcc 100644
--- a/mps/manual/html/glossary/f.html
+++ b/mps/manual/html/glossary/f.html
@@ -297,7 +297,7 @@
Navigation
that foreign code is not passed the address of a block in
a movingpools, or
which contain references to blocks in moving pools.
The LO (Leaf Object)pool class is designed for this
use case: blocks allocated from this pool do not move and
are never protected, and so may be passed safely to
foreign code.
copying them can be avoided
entirely). If a generation is collected when its blocks are mostly
alive, that is a waste of time.
-
In the table below I give the execution time of test-leaf.scm in
+
In the tables below I give the execution time of test-leaf.scm in
the toy Scheme interpreter under different settings for its generation
-chain. (This test case allocates millions of small short-lived
-objects.) In each case the AMC pool is given a chain with a single
-generation with the specified capacity and mortality.
+chain. (This test case allocates hundreds of millions of small
+short-lived objects.)
+
First, the effect of varying the capacity of a chain with a single
+generation.
@@ -93,59 +94,124 @@
Navigation
100
0.80
-
39.9
+
362.6
200
0.80
-
30.2
+
354.9
400
0.80
-
25.5
+
349.7
800
0.80
-
16.3
+
314.4
1600
0.80
-
9.0
+
215.7
3200
0.80
-
5.8
+
94.0
6400
-
0.20
-
4.2
-
-
6400
-
0.40
-
4.1
-
-
6400
-
0.60
-
4.1
-
-
6400
0.80
-
4.1
-
-
6400
-
0.99
-
4.2
+
53.5
12800
0.80
-
4.2
+
79.6
25600
0.80
-
5.2
+
77.6
-
This table suggests that:
+
Second, the effect of varying the mortality of a chain with a single
+generation.
+
+
+
+
+
+
+
+
Capacity
+
Mortality
+
Execution time (user+sys)
+
+
+
+
6400
+
0.20
+
55.4
+
+
6400
+
0.40
+
54.0
+
+
6400
+
0.60
+
54.0
+
+
6400
+
0.80
+
53.5
+
+
6400
+
0.99
+
54.8
+
+
+
+
Third, the effect of varying the number of generations (all
+generations being identical).
+
+
+
+
+
+
+
+
+
Generations
+
Capacity
+
Mortality
+
Execution time (user+sys)
+
+
+
+
1
+
6400
+
0.80
+
53.5
+
+
2
+
6400
+
0.80
+
42.4
+
+
3
+
6400
+
0.80
+
42.1
+
+
4
+
6400
+
0.80
+
42.2
+
+
5
+
6400
+
0.80
+
42.2
+
+
+
+
These tables suggest that:
The improvement in performance to be gained by getting generation
sizes right is dramatic: much bigger than the small improvements to
@@ -154,6 +220,8 @@
Navigation
execution time (it does affect the distribution of pause times,
however: see Scheduling of collections.)
You can make generations too big as well as too small.
+
There are rapidly diminishing returns to be gained from adding
+generations.
Note
@@ -161,6 +229,109 @@
Navigation
are being collected and what proportion of blocks were found to be
alive.
+
The table below shows the effect of varying the initial allocation of
+address space to the arena (using three generations each with capacity
+6400 kB, mortality 0.80).
(1, 2, 3, 4) With this initial allocation of address space, the test
+case failed to run to completion after thousands of seconds
+and tens of thousands of garbage collection cycles.
+
+
+
+
The lesson here is that the allocation of address space has to be
+comfortably larger than the working set of the program.
COBOL was designed by the CODASYL committee in 1959–60 to be a
business programming language, and has been extended many
-times since. It is still the most widely-used programming
-language (in terms of lines of code in use).
+times since. A 1997 Gartner Group report estimated that 80% of
+computer software (by count of source lines) was written in
+COBOL.
Prior to 2002, COBOL had no heap allocation, and did
well in its application domain without it. COBOL 2002 has
pointers and heap allocation through ALLOCATE and
@@ -454,7 +455,8 @@
Navigation
their keys and values can be dynamically switched from being
strong references to weak references, and vice versa
(by assigning to the __mode field of the table’s
-metatable).
+metatable). It also supports finalization (by
+assigning the __gc field of the object’s metatable).