1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-25 06:50:46 -08:00

Update html.

Copied from Perforce
 Change: 180468
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-11-14 14:13:19 +00:00
parent 5e9f42cd44
commit bd034b6eb0
21 changed files with 966 additions and 258 deletions

View file

@ -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 ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...) */
/* entry_do -- (do ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...)
* 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 <init> expressions
are evaluated (in some unspecified order), the <variable>s are
bound to fresh locations, the results of the <init> expressions
are stored in the bindings of the <variable>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 <test>; */
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 <command> 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 <step> expressions are evaluated in some unspecified
order, the <variable>s are bound to fresh locations, the
results of the <step>s are stored in the bindings of the
<variable>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 <test> evaluates to a true value, then the <expression>s
are evaluated from left to right and the value of the last
<expression> is returned as the value of the do expression.
If no <expression>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 <obj>)
*
* Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
/* (not <obj>)
* 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? <obj>)
*
* Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
/* (boolean? <obj>)
* 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? <obj1> <obj2>) */
/* (eqv? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
/* (eq? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
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? <obj1> <obj2>)
* 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? <obj>) */
/* (pair? <obj>)
* 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. */

View file

@ -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 ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...) */
/* entry_do -- (do ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...)
* 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 <init> expressions
are evaluated (in some unspecified order), the <variable>s are
bound to fresh locations, the results of the <init> expressions
are stored in the bindings of the <variable>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 <test>; */
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 <command> 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 <step> expressions are evaluated in some unspecified
order, the <variable>s are bound to fresh locations, the
results of the <step>s are stored in the bindings of the
<variable>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 <test> evaluates to a true value, then the <expression>s
are evaluated from left to right and the value of the last
<expression> is returned as the value of the do expression.
If no <expression>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 <obj>)
*
* Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
/* (not <obj>)
* 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? <obj>)
*
* Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
/* (boolean? <obj>)
* 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? <obj1> <obj2>) */
/* (eqv? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
/* (eq? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
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? <obj1> <obj2>)
* 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? <obj>) */
/* (pair? <obj>)
* 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;

View file

@ -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 ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...) */
/* entry_do -- (do ((<var> <init> <step1>) ...) (<test> <exp> ...) <command> ...)
* 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 <init> expressions
are evaluated (in some unspecified order), the <variable>s are
bound to fresh locations, the results of the <init> expressions
are stored in the bindings of the <variable>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 <test>; */
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 <command> 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 <step> expressions are evaluated in some unspecified
order, the <variable>s are bound to fresh locations, the
results of the <step>s are stored in the bindings of the
<variable>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 <test> evaluates to a true value, then the <expression>s
are evaluated from left to right and the value of the last
<expression> is returned as the value of the do expression.
If no <expression>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 <obj>)
*
* Not returns #t if obj is false, and return #f otherwise. R4RS 6.1.
/* (not <obj>)
* 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? <obj>)
*
* Boolean? return #t if obj is either #t or #f, and #f otherwise. R4RS 6.1.
/* (boolean? <obj>)
* 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? <obj1> <obj2>) */
/* (eqv? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
/* (eq? <obj1> <obj2>)
* 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? <obj1> <obj2>) */
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? <obj1> <obj2>)
* 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? <obj>) */
/* (pair? <obj>)
* 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;

View file

@ -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
------------------------

View file

@ -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.

View file

@ -94,8 +94,9 @@ Memory management in various languages
COBOL was designed by the CODASYL committee in 195960 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::

View file

@ -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)

View file

@ -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?

View file

@ -297,7 +297,7 @@ co-operate with the MPS. The client program must take care
that foreign code is not passed the address of a block in
a <a class="reference internal" href="m.html#term-moving-memory-manager"><em class="xref std std-term">moving</em></a> <a class="reference internal" href="p.html#term-pool"><em class="xref std std-term">pools</em></a>, or
which contain references to blocks in moving pools.</p>
<p class="last">The <a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Only)</em></a> <a class="reference internal" href="p.html#term-pool-class"><em class="xref std std-term">pool class</em></a> is designed for this
<p class="last">The <a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Object)</em></a> <a class="reference internal" href="p.html#term-pool-class"><em class="xref std std-term">pool class</em></a> 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.</p>

View file

@ -69,7 +69,7 @@ other references to that object, or a garbage collection may be
delayed. And even if it does die, the space it occupies may not be
re-allocated for some time.</p>
<div class="section" id="general-debugging-advice">
<h2>4.1. General debugging advice<a class="headerlink" href="#general-debugging-advice" title="Permalink to this headline"></a></h2>
<span id="guide-debug-advice"></span><h2>4.1. General debugging advice<a class="headerlink" href="#general-debugging-advice" title="Permalink to this headline"></a></h2>
<ol class="arabic">
<li><p class="first">Compile with debugging information turned on (<tt class="docutils literal"><span class="pre">-g</span></tt> on the GCC or
Clang command line).</p>

View file

@ -73,11 +73,12 @@ most of the blocks allocated in that generation should be found to be
<a class="reference internal" href="../glossary/c.html#term-copying-garbage-collection"><em class="xref std std-term">copying</em></a> them can be avoided
entirely). If a generation is collected when its blocks are mostly
alive, that is a waste of time.</p>
<p>In the table below I give the execution time of <tt class="docutils literal"><span class="pre">test-leaf.scm</span></tt> in
<p>In the tables below I give the execution time of <tt class="docutils literal"><span class="pre">test-leaf.scm</span></tt> 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.</p>
chain. (This test case allocates hundreds of millions of small
short-lived objects.)</p>
<p>First, the effect of varying the capacity of a chain with a single
generation.</p>
<table border="1" class="docutils">
<colgroup>
<col width="19%" />
@ -93,59 +94,124 @@ generation with the specified capacity and mortality.</p>
<tbody valign="top">
<tr class="row-even"><td>100</td>
<td>0.80</td>
<td>39.9</td>
<td>362.6</td>
</tr>
<tr class="row-odd"><td>200</td>
<td>0.80</td>
<td>30.2</td>
<td>354.9</td>
</tr>
<tr class="row-even"><td>400</td>
<td>0.80</td>
<td>25.5</td>
<td>349.7</td>
</tr>
<tr class="row-odd"><td>800</td>
<td>0.80</td>
<td>16.3</td>
<td>314.4</td>
</tr>
<tr class="row-even"><td>1600</td>
<td>0.80</td>
<td>9.0</td>
<td>215.7</td>
</tr>
<tr class="row-odd"><td>3200</td>
<td>0.80</td>
<td>5.8</td>
<td>94.0</td>
</tr>
<tr class="row-even"><td>6400</td>
<td>0.20</td>
<td>4.2</td>
</tr>
<tr class="row-odd"><td>6400</td>
<td>0.40</td>
<td>4.1</td>
</tr>
<tr class="row-even"><td>6400</td>
<td>0.60</td>
<td>4.1</td>
</tr>
<tr class="row-odd"><td>6400</td>
<td>0.80</td>
<td>4.1</td>
</tr>
<tr class="row-even"><td>6400</td>
<td>0.99</td>
<td>4.2</td>
<td>53.5</td>
</tr>
<tr class="row-odd"><td>12800</td>
<td>0.80</td>
<td>4.2</td>
<td>79.6</td>
</tr>
<tr class="row-even"><td>25600</td>
<td>0.80</td>
<td>5.2</td>
<td>77.6</td>
</tr>
</tbody>
</table>
<p>This table suggests that:</p>
<p>Second, the effect of varying the mortality of a chain with a single
generation.</p>
<table border="1" class="docutils">
<colgroup>
<col width="19%" />
<col width="21%" />
<col width="60%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Capacity</th>
<th class="head">Mortality</th>
<th class="head">Execution time (user+sys)</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>6400</td>
<td>0.20</td>
<td>55.4</td>
</tr>
<tr class="row-odd"><td>6400</td>
<td>0.40</td>
<td>54.0</td>
</tr>
<tr class="row-even"><td>6400</td>
<td>0.60</td>
<td>54.0</td>
</tr>
<tr class="row-odd"><td>6400</td>
<td>0.80</td>
<td>53.5</td>
</tr>
<tr class="row-even"><td>6400</td>
<td>0.99</td>
<td>54.8</td>
</tr>
</tbody>
</table>
<p>Third, the effect of varying the number of generations (all
generations being identical).</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%" />
<col width="15%" />
<col width="17%" />
<col width="47%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Generations</th>
<th class="head">Capacity</th>
<th class="head">Mortality</th>
<th class="head">Execution time (user+sys)</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>1</td>
<td>6400</td>
<td>0.80</td>
<td>53.5</td>
</tr>
<tr class="row-odd"><td>2</td>
<td>6400</td>
<td>0.80</td>
<td>42.4</td>
</tr>
<tr class="row-even"><td>3</td>
<td>6400</td>
<td>0.80</td>
<td>42.1</td>
</tr>
<tr class="row-odd"><td>4</td>
<td>6400</td>
<td>0.80</td>
<td>42.2</td>
</tr>
<tr class="row-even"><td>5</td>
<td>6400</td>
<td>0.80</td>
<td>42.2</td>
</tr>
</tbody>
</table>
<p>These tables suggest that:</p>
<ol class="arabic simple">
<li>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 @@ gained from other techniques.</li>
execution time (it does affect the distribution of pause times,
however: see <a class="reference internal" href="../topic/collection.html#topic-collection-schedule"><em>Scheduling of collections</em></a>.)</li>
<li>You can make generations too big as well as too small.</li>
<li>There are rapidly diminishing returns to be gained from adding
generations.</li>
</ol>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
@ -161,6 +229,109 @@ however: see <a class="reference internal" href="../topic/collection.html#topic-
are being collected and what proportion of blocks were found to be
alive.</p>
</div>
<p>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).</p>
<table border="1" class="docutils">
<colgroup>
<col width="22%" />
<col width="17%" />
<col width="19%" />
<col width="42%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Address space</th>
<th class="head">Extensions</th>
<th class="head">Collections</th>
<th class="head">Execution time (user+sys)</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>2</td>
<td>32</td>
<td>371</td>
<td>52.0</td>
</tr>
<tr class="row-odd"><td>4</td>
<td>21</td>
<td>370</td>
<td>47.0</td>
</tr>
<tr class="row-even"><td>8</td>
<td>0</td>
<td><a class="footnote-reference" href="#id5" id="id1">[1]</a></td>
<td><a class="footnote-reference" href="#id5" id="id2">[1]</a></td>
</tr>
<tr class="row-odd"><td>14</td>
<td>0</td>
<td><a class="footnote-reference" href="#id5" id="id3">[1]</a></td>
<td><a class="footnote-reference" href="#id5" id="id4">[1]</a></td>
</tr>
<tr class="row-even"><td>16</td>
<td>0</td>
<td>2436</td>
<td>160.5</td>
</tr>
<tr class="row-odd"><td>18</td>
<td>0</td>
<td>1135</td>
<td>89.1</td>
</tr>
<tr class="row-even"><td>20</td>
<td>0</td>
<td>673</td>
<td>60.6</td>
</tr>
<tr class="row-odd"><td>22</td>
<td>0</td>
<td>484</td>
<td>48.7</td>
</tr>
<tr class="row-even"><td>24</td>
<td>0</td>
<td>400</td>
<td>43.1</td>
</tr>
<tr class="row-odd"><td>32</td>
<td>0</td>
<td>368</td>
<td>41.2</td>
</tr>
<tr class="row-even"><td>64</td>
<td>0</td>
<td>368</td>
<td>43.1</td>
</tr>
<tr class="row-odd"><td>128</td>
<td>0</td>
<td>368</td>
<td>46.4</td>
</tr>
<tr class="row-even"><td>256</td>
<td>0</td>
<td>368</td>
<td>46.3</td>
</tr>
<tr class="row-odd"><td>512</td>
<td>0</td>
<td>368</td>
<td>49.3</td>
</tr>
</tbody>
</table>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<table class="last docutils footnote" frame="void" id="id5" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id2">2</a>, <a class="fn-backref" href="#id3">3</a>, <a class="fn-backref" href="#id4">4</a>)</em> 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.</td></tr>
</tbody>
</table>
</div>
<p>The lesson here is that the allocation of address space has to be
comfortably larger than the working set of the program.</p>
</div>

View file

@ -137,8 +137,9 @@ longer required (see <a class="reference internal" href="../glossary/m.html#term
<dt id="term-cobol">COBOL</dt>
<dd><p class="first">COBOL was designed by the CODASYL committee in 195960 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).</p>
times since. A 1997 Gartner Group report estimated that 80% of
computer software (by count of source lines) was written in
COBOL.</p>
<p>Prior to 2002, COBOL had no <a class="reference internal" href="../glossary/h.html#term-heap-allocation"><em class="xref std std-term">heap allocation</em></a>, and did
well in its application domain without it. COBOL 2002 has
<a class="reference internal" href="../glossary/p.html#term-pointer"><em class="xref std std-term">pointers</em></a> and heap allocation through <tt class="docutils literal"><span class="pre">ALLOCATE</span></tt> and
@ -454,7 +455,8 @@ of weak (hash) tables, which have the unusual feature that
their keys and values can be dynamically switched from being
<a class="reference internal" href="../glossary/s.html#term-strong-reference"><em class="xref std std-term">strong references</em></a> to weak references, and vice versa
(by assigning to the <tt class="docutils literal"><span class="pre">__mode</span></tt> field of the table&#8217;s
metatable).</p>
metatable). It also supports <a class="reference internal" href="../glossary/f.html#term-finalization"><em class="xref std std-term">finalization</em></a> (by
assigning the <tt class="docutils literal"><span class="pre">__gc</span></tt> field of the object&#8217;s metatable).</p>
<div class="admonition-related-link last admonition">
<p class="first admonition-title">Related links</p>
<p class="last"><a class="reference external" href="http://lua.org">Lua</a>,

Binary file not shown.

View file

@ -28,7 +28,7 @@
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
<link rel="next" title="1. Choosing a pool class" href="intro.html" />
<link rel="prev" title="20. Weak references" href="../topic/weak.html" />
<link rel="prev" title="19. Weak references" href="../topic/weak.html" />
</head>
<body>
<div class="related">
@ -41,7 +41,7 @@
<a href="intro.html" title="1. Choosing a pool class"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../topic/weak.html" title="20. Weak references"
<a href="../topic/weak.html" title="19. Weak references"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
</ul>
@ -132,7 +132,7 @@
</a></p>
<h4>Previous topic</h4>
<p class="topless"><a href="../topic/weak.html"
title="previous chapter">20. Weak references</a></p>
title="previous chapter">19. Weak references</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="intro.html"
title="next chapter">1. Choosing a pool class</a></p><h4>Contact us</h4>
@ -152,7 +152,7 @@
<a href="intro.html" title="1. Choosing a pool class"
>next</a> |</li>
<li class="right" >
<a href="../topic/weak.html" title="20. Weak references"
<a href="../topic/weak.html" title="19. Weak references"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
</ul>

View file

@ -119,7 +119,7 @@ pool class to use:</p>
<tr class="row-even"><td>yes</td>
<td>no</td>
<td>none</td>
<td><a class="reference internal" href="lo.html#pool-lo"><em>LO (Leaf Only)</em></a></td>
<td><a class="reference internal" href="lo.html#pool-lo"><em>LO (Leaf Object)</em></a></td>
</tr>
<tr class="row-odd"><td>yes</td>
<td>no</td>

File diff suppressed because one or more lines are too long

View file

@ -853,7 +853,7 @@ pointer to array of size classes&#8221;?</p>
while still keeping the allocation fast and inline? How does the
MPS behave when it&#8217;s low on memory? Performance degrades (due to
running out of zones) and then there are emergency collections.</p>
<p><em>Action:</em> created <a class="reference internal" href="topic/low.html#topic-low"><em>Handling low memory</em></a>.</p>
<p><em>Action:</em> created <em class="xref std std-ref">topic-low</em>.</p>
</li>
</ol>
<ol class="arabic" start="127">

View file

@ -519,6 +519,14 @@ some objects (such as those near the destination of ambiguous
references) even though they are not reachable.</p>
<p>If you do not want the arena to remain in the parked state, you
must explicitly call <a class="reference internal" href="#mps_arena_release" title="mps_arena_release"><tt class="xref c c-func docutils literal"><span class="pre">mps_arena_release()</span></tt></a> afterwards.</p>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p class="last">It is not normally necessary to call this function: in the
<a class="reference internal" href="../glossary/u.html#term-unclamped-state"><em class="xref std std-term">unclamped state</em></a>, 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 <a class="reference internal" href="../guide/debug.html#guide-debug-advice"><em>General debugging advice</em></a>.</p>
</div>
</dd></dl>
<dl class="function">

View file

@ -299,7 +299,7 @@ implements copying garbage collection), or was already moved when
fixing a previous reference to it, the reference being fixed must be
updated (this is the origin of the term &#8220;fix&#8221;).</p>
<p>As a simple example, <tt class="docutils literal"><span class="pre">LOFix</span></tt> is the pool fix method for the
<a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Only)</em></a> pool class. It implements a <a class="reference internal" href="../glossary/m.html#term-marking"><em class="xref std std-term">marking</em></a> garbage
<a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Object)</em></a> pool class. It implements a <a class="reference internal" href="../glossary/m.html#term-marking"><em class="xref std std-term">marking</em></a> garbage
collector, and does not have to worry about scanning preserved objects
because it is used to store objects that don&#8217;t contain pointers. (It
is used in compiler run-time systems to store binary data such as

View file

@ -540,7 +540,7 @@ an array and its size as parameters.</p>
<p>Each <a class="reference internal" href="../glossary/p.html#term-pool-class"><em class="xref std std-term">pool class</em></a> determines for which objects the stepper
function is called. Typically, all validly formatted objects are
visited. During a <a class="reference internal" href="../glossary/t.html#term-trace"><em class="xref std std-term">trace</em></a> this will in general be only the
<a class="reference internal" href="../glossary/b.html#term-black"><em class="xref std std-term">black</em></a> objects, though the <a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Only)</em></a> pool, for
<a class="reference internal" href="../glossary/b.html#term-black"><em class="xref std std-term">black</em></a> objects, though the <a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Object)</em></a> pool, for
example, will walk all objects since they are validly formatted
whether they are black or <a class="reference internal" href="../glossary/w.html#term-white"><em class="xref std std-term">white</em></a>. <a class="reference internal" href="../glossary/p.html#term-padding-object"><em class="xref std std-term">Padding objects</em></a>
may be visited at the pool class&#8217;s discretion: the <a class="reference internal" href="../glossary/c.html#term-client-program"><em class="xref std std-term">client

View file

@ -1,110 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>19. Handling low memory &mdash; Memory Pool System 1.111.0 documentation</title>
<link rel="stylesheet" href="../_static/mps.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.111.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
<link rel="up" title="Reference" href="index.html" />
<link rel="next" title="20. Weak references" href="weak.html" />
<link rel="prev" title="18. Telemetry" href="telemetry.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="weak.html" title="20. Weak references"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="telemetry.html" title="18. Telemetry"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" accesskey="U">Reference</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="handling-low-memory">
<span id="topic-low"></span><h1>19. Handling low memory<a class="headerlink" href="#handling-low-memory" title="Permalink to this headline"></a></h1>
<p>What does it mean to be &#8220;low on memory&#8221; in a virtual memory operating
system?</p>
<p>How does the MPS behave when it&#8217;s low on memory? Performance degrades
(due to running out of zones) and then there are emergency
collections.</p>
<p>How can you handle low memory situations gracefully while still
keeping allocation fast and inline?</p>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.png" alt="Logo"/>
</a></p>
<h4>Previous topic</h4>
<p class="topless"><a href="telemetry.html"
title="previous chapter">18. Telemetry</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="weak.html"
title="next chapter">20. Weak references</a></p><h4>Contact us</h4>
<p class="topless"><a href="mailto:mps-questions@ravenbrook.com">mps-questions@ravenbrook.com</a></p>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="weak.html" title="20. Weak references"
>next</a> |</li>
<li class="right" >
<a href="telemetry.html" title="18. Telemetry"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" >Reference</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2012, Ravenbrook Limited.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>