5344 lines
211 KiB
Text
5344 lines
211 KiB
Text
|
% Copyright 2005-2018 Cisco Systems, Inc.
|
||
|
%
|
||
|
% Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
% you may not use this file except in compliance with the License.
|
||
|
% You may obtain a copy of the License at
|
||
|
%
|
||
|
% http://www.apache.org/licenses/LICENSE-2.0
|
||
|
%
|
||
|
% Unless required by applicable law or agreed to in writing, software
|
||
|
% distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
% See the License for the specific language governing permissions and
|
||
|
% limitations under the License.
|
||
|
\chapter{System Operations\label{CHPTSYSTEM}}
|
||
|
|
||
|
This chapter describes operations for
|
||
|
handling exceptions, interrupts, environments,
|
||
|
compilation and evaluation, profiling,
|
||
|
controlling the operation of the system,
|
||
|
timing and statistics,
|
||
|
defining and setting parameters,
|
||
|
and
|
||
|
querying the operating system environment.
|
||
|
|
||
|
\schemeinit
|
||
|
(load "docond.ss")
|
||
|
\endschemeinit
|
||
|
|
||
|
\section{Exceptions\label{SECTSYSTEMEXCEPTIONS}}
|
||
|
|
||
|
\index{exception handling}{\ChezScheme} provides some extensions to the
|
||
|
Revised$^6$ Report exception-handling mechanism, including mechanisms
|
||
|
for producing formatted error messages, displaying conditions,
|
||
|
and redefining the base exception handler.
|
||
|
These extensions are described in this section.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{warning}{\categoryprocedure}{(warning \var{who} \var{msg} \var{irritant} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{warning} raises a continuable exception with condition type
|
||
|
\scheme{&warning} and should be used to describe situations for which the
|
||
|
\scheme{&warning} condition type is appropriate, typically a situation
|
||
|
that should not prevent the program from continuing but might result
|
||
|
in a more serious problem at some later point.
|
||
|
|
||
|
The continuation object with which the exception is raised also includes
|
||
|
a \scheme{&who} condition whose who field is \var{who} if \var{who} is
|
||
|
not \scheme{#f}, a \scheme{&message} condition whose message field is
|
||
|
\var{msg}, and an \scheme{&irritants} condition whose irritants field
|
||
|
is \scheme{(\var{irritant} \dots)}.
|
||
|
|
||
|
\var{who} must be a string, a symbol, or \scheme{#f} identifying the procedure
|
||
|
or syntactic form reporting the warning.
|
||
|
It is usually best to identify a procedure the programmer has called rather
|
||
|
than some other procedure the programmer may not be aware is involved in
|
||
|
carrying out the operation.
|
||
|
\var{msg} must be a string and should describe the exceptional situation.
|
||
|
The irritants may be any Scheme objects and should include values that may
|
||
|
have caused or been materially involved in the exceptional situation.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{assertion-violationf}{\categoryprocedure}{(assertion-violationf \var{who} \var{msg} \var{irritant} \dots)}
|
||
|
\returns does not return
|
||
|
\formdef{errorf}{\categoryprocedure}{(errorf \var{who} \var{msg} \var{irritant} \dots)}
|
||
|
\returns does not return
|
||
|
\formdef{warningf}{\categoryprocedure}{(warningf \var{who} \var{msg} \var{irritant} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\index{formatted error messages}%
|
||
|
These procedures are like \scheme{assertion-violation}, \scheme{error},
|
||
|
and \scheme{warning} except
|
||
|
that \var{msg} is assumed to be a format string, as if in a call to
|
||
|
\scheme{format} (Section~\ref{SECTFORMAT}), with
|
||
|
\scheme{\var{irritant} \dots} treated as the additional arguments to
|
||
|
\scheme{format}.
|
||
|
This allows programs to control the appearance of the error message, at
|
||
|
least when the default exception handler is in place.
|
||
|
|
||
|
For each of these procedures, the continuation object with which the exception
|
||
|
is raised includes a \scheme{&format} condition to signify that the string
|
||
|
contained in the condition object's \scheme{&message} condition is a
|
||
|
\scheme{format} string and the objects contained in the condition object's
|
||
|
\scheme{&irritants} condition should be treated as the additional
|
||
|
\scheme{format} arguments.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\conditionformdef{(define-condition-type &format &condition
|
||
|
make-format-condition format-condition?)}
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Presence of this condition type within a compound condition indicates
|
||
|
that the string provided by the \scheme{&message} condition, if
|
||
|
present, is a \scheme{format} string and the list of objects provided by
|
||
|
the \scheme{&irritants} condition, if present, should be treated as
|
||
|
additional \scheme{format} arguments.
|
||
|
\showit
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\conditionformdef{(define-condition-type &source &condition
|
||
|
make-source-condition source-condition?
|
||
|
(form source-condition-form))}
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
This condition type can be included within a compound condition when a
|
||
|
source expression can be identified in situations in which a
|
||
|
\scheme{&syntax} condition would be inappropriate, such as when a
|
||
|
run-time assertion violation is detected.
|
||
|
The \scheme{form} argument should be an s-expression or syntax object
|
||
|
representing the source expression.
|
||
|
\showit
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\conditionformdef{(define-condition-type &continuation &condition
|
||
|
make-continuation-condition continuation-condition?
|
||
|
(continuation condition-continuation))}
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
This condition type can be included within a compound condition to indicate
|
||
|
the current continuation at the point where the exception described by the
|
||
|
condition occurred.
|
||
|
The continuation of a failed \scheme{assert} or a call to
|
||
|
\scheme{assertion-violation}, \scheme{assertion-violationf},
|
||
|
\scheme{error}, \scheme{errorf}, or \scheme{syntax-error} is now included
|
||
|
via this condition type in the conditions passed to \scheme{raise}.
|
||
|
The \scheme{continuation} argument should be a continuation.
|
||
|
\showit
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{display-condition}{\categoryprocedure}{(display-condition \var{obj})}
|
||
|
\formdef{display-condition}{\categoryprocedure}{(display-condition \var{obj} \var{textual-output-port})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
If \var{textual-output-port} is not supplied, it defaults to the current output port.
|
||
|
This procedure displays a message to the effect that an exception
|
||
|
has occurred with value \var{obj}.
|
||
|
If \var{obj} is a condition (Chapter~\ref{TSPL:CHPTEXCEPTIONS} of
|
||
|
{\TSPLFOUR}), it displays information encapsulated within the condition,
|
||
|
handling messages, \var{who} conditions, irritants, source information,
|
||
|
etc., as appropriate.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{default-exception-handler}{\categoryprocedure}{(default-exception-handler \var{obj})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure is the default value of the \scheme{base-exception-handler}
|
||
|
parameter called on a condition when no other exception handler has been
|
||
|
defined or when all dynamically established exception handlers have chosen
|
||
|
not to handle the condition.
|
||
|
It first displays \var{obj}, as if with \scheme{display-condition}, to the
|
||
|
console error port.
|
||
|
For non-serious warning conditions, it returns immediately after displaying
|
||
|
the condition.
|
||
|
|
||
|
For serious or other non-warning conditions, it
|
||
|
saves the condition in the parameter \scheme{debug-condition}, where
|
||
|
\scheme{debug} (Section~\ref{SECTDEBUGINTERACTIVE}) can retrieve it and
|
||
|
allow it to be inspected.
|
||
|
If the \scheme{debug-on-exception} parameter is set to \scheme{#f} (the
|
||
|
default unless the \index{\scheme{--debug-on-exception} command-line
|
||
|
option}\scheme{--debug-on-exception} command-line option is provided), the
|
||
|
handler prints a message instructing the user to type \scheme{(debug)} to
|
||
|
enter the debugger, then resets to the current caf\'e.
|
||
|
Otherwise, the handler invokes \scheme{debug} directly and resets if
|
||
|
\scheme{debug} returns.
|
||
|
|
||
|
If an I/O exception occurs while attempting to display the condition,
|
||
|
the default exception handler resets (as if by calling \scheme{reset}).
|
||
|
The intent is to avoid an infinite regression (ultimately ending
|
||
|
in exhaustion of memory) in which the process repeatedly recurs
|
||
|
back to the default exception handler trying to write to a console-error
|
||
|
port (typically stderr) that is no longer writable, e.g., due to
|
||
|
the other end of a pipe or socket having been closed.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{debug-on-exception}{\categoryglobalparameter}{debug-on-exception}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The value of this parameter determines whether the default exception handler
|
||
|
immediately enters the debugger immediately when it receives a serious or
|
||
|
non-warning condition.
|
||
|
If the \index{\scheme{--debug-on-exception} command-line option}\scheme{--debug-on-exception}
|
||
|
command-line option (Section~\ref{SECTUSEINTERACTION}) has been provided, the
|
||
|
initial value of this parameter is \scheme{#t}.
|
||
|
Otherwise, the initial value is \scheme{#f}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{base-exception-handler}{\categorythreadparameter}{base-exception-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The value of this parameter must be a procedure, and the procedure
|
||
|
should accept one argument.
|
||
|
The default value of \scheme{base-exception-handler} is
|
||
|
the procedure \scheme{default-exception-handler}.
|
||
|
|
||
|
The value of this parameter is invoked whenever no exception handler
|
||
|
established by a program has chosen to handle an exception.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{debug-condition}{\categorythreadparameter}{debug-condition}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This parameter is used by the default exception handler to hold the
|
||
|
last serious or non-warning condition received by the handler, where
|
||
|
it can be inspected via the \scheme{debug} procedure
|
||
|
(Section~\ref{SECTDEBUGINTERACTIVE}).
|
||
|
It can also be invoked by user code to store or retrieve a
|
||
|
condition.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-exception-state}{\categorythreadparameter}{current-exception-state}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{current-exception-state} may be used to get or set
|
||
|
the current exception state.
|
||
|
When called without arguments, \scheme{current-exception-state} returns
|
||
|
an \emph{exception state} comprising the current stack of handlers established
|
||
|
by \scheme{with-exception-handler} and \scheme{guard}.
|
||
|
When called with a single argument, which must be an exception state,
|
||
|
\scheme{current-exception-state} sets the exception state.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{create-exception-state}{\categoryprocedure}{(create-exception-state)}
|
||
|
\formdef{create-exception-state}{\categoryprocedure}{(create-exception-state \var{procedure})}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{create-exception-state} creates an exception
|
||
|
state whose stack of exception handlers is empty except for, in effect,
|
||
|
an infinite number of occurrences of \emph{handler} at its
|
||
|
base.
|
||
|
\var{handler} must be a procedure, and should accept one argument.
|
||
|
If not provided, \var{handler} defaults to a procedure equivalent
|
||
|
to the value of the following expression.
|
||
|
|
||
|
\schemedisplay
|
||
|
(lambda (x) ((base-exception-handler) x))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Interrupts\label{SECTSYSTEMINTERRUPTS}}
|
||
|
|
||
|
\index{interrupts}{\ChezScheme} allows programs to control
|
||
|
the action of the Scheme system when various events
|
||
|
occur, including an interrupt from the
|
||
|
keyboard, the expiration of an internal timer set by \scheme{set-timer},
|
||
|
a breakpoint caused by a call to \scheme{break}, or a request from the
|
||
|
storage manager to initiate a garbage collection.
|
||
|
These mechanisms are described in this section, except for the
|
||
|
collect request mechanism, which is described in Section~\ref{SECTSMGMTGC}.
|
||
|
|
||
|
Timer, keyboard, and collect-request interrupts are supported via a counter
|
||
|
that is decremented approximately once for each call to a nonleaf procedure.
|
||
|
(A leaf procedure is one that does not itself make any calls.)
|
||
|
When no timer is running, this counter is set to a default value (1000
|
||
|
in Version~9) when a program starts or after an interrupt occurs.
|
||
|
If a timer is set (via \scheme{set-timer}), the counter is set to the
|
||
|
minimum of the default value and the number of ticks to which the timer is
|
||
|
set.
|
||
|
When the counter reaches zero, the system looks to see if the timer
|
||
|
is set and has expired or if a keyboard or collect request interrupt
|
||
|
has occurred.
|
||
|
If so, the current procedure call is pended (``put on hold'') while the
|
||
|
appropriate interrupt handler is invoked to handle the interrupt.
|
||
|
When (if) the interrupt handler returns, the pended call takes place.
|
||
|
Thus, timer, keyboard, and collect-request interrupts effectively occur
|
||
|
synchronously with respect to the procedure call mechanism, and
|
||
|
keyboard and collect request interrupts may be delayed by a number
|
||
|
of calls equal to the default timer value.
|
||
|
|
||
|
Calls to the break handler occur immediately
|
||
|
whenever \scheme{break} is called.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{break}{\categoryprocedure}{(break \var{who} \var{msg} \var{irritant} \dots)}
|
||
|
\formdef{break}{\categoryprocedure}{(break \var{who})}
|
||
|
\formdef{break}{\categoryprocedure}{(break)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The arguments to \scheme{break} follow the protocol described above for
|
||
|
\scheme{errorf}.
|
||
|
The default break handler (see \scheme{break-handler}) displays a message and
|
||
|
invokes the \index{debugger}debugger.
|
||
|
The format string and objects may be omitted, in which case the
|
||
|
message issued by the default break handler identifies the break
|
||
|
using the \var{who} argument but provides no more information
|
||
|
about the break.
|
||
|
If the \var{who} argument is omitted as well, no message is generated.
|
||
|
The default break handler returns normally if the debugger
|
||
|
exits normally.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{break-handler}{\categorythreadparameter}{break-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter must be a procedure.
|
||
|
The current break handler is called by \scheme{break}, which passes
|
||
|
along its arguments.
|
||
|
See \scheme{break} for a description of the default break
|
||
|
handler.
|
||
|
The example below shows how to disable breaks.
|
||
|
|
||
|
\schemedisplay
|
||
|
(break-handler (lambda args (void)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{keyboard-interrupt-handler}{\categorythreadparameter}{keyboard-interrupt-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter must be a procedure.
|
||
|
The keyboard-interrupt handler is called (with no arguments) when
|
||
|
a keyboard interrupt occurs.
|
||
|
The default keyboard-interrupt handler invokes the interactive
|
||
|
\index{debugger}debugger.
|
||
|
If the debugger exits normally the interrupted computation is
|
||
|
resumed.
|
||
|
The example below shows how to install a keyboard-interrupt handler
|
||
|
that resets without invoking the debugger.
|
||
|
|
||
|
\schemedisplay
|
||
|
(keyboard-interrupt-handler
|
||
|
(lambda ()
|
||
|
(newline (console-output-port))
|
||
|
(reset)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:set-timer}
|
||
|
\formdef{set-timer}{\categoryprocedure}{(set-timer \var{n})}
|
||
|
\returns previous current timer value
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\index{timer interrupts}\var{n} must be a nonnegative integer.
|
||
|
When \var{n} is nonzero, \scheme{set-timer} starts an internal timer with
|
||
|
an initial value of \var{n}.
|
||
|
When \var{n} ticks elapse, a timer interrupt occurs, resulting in
|
||
|
invocation of the timer interrupt handler.
|
||
|
Each tick corresponds roughly to one nonleaf procedure call (see the
|
||
|
introduction to this section); thus, ticks are not
|
||
|
uniform time units but instead depend heavily on how much work is done
|
||
|
by each procedure call.
|
||
|
|
||
|
When \var{n} is zero, \scheme{set-timer} turns the timer off.
|
||
|
|
||
|
The value returned in either case is the value of the timer before the
|
||
|
call to \scheme{set-timer}.
|
||
|
A return value of 0 should not be taken to imply that the timer was not on;
|
||
|
the return value may also be 0 if the timer was just about to fire when
|
||
|
the call to \scheme{set-timer} occurred.
|
||
|
|
||
|
The engine mechanism (Section~\ref{SECTENGINES}) is built on top of the
|
||
|
timer interrupt so timer interrupts should not be used with engines.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{timer-interrupt-handler}{\categorythreadparameter}{timer-interrupt-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\index{timer interrupts}The value of this parameter must be a procedure.
|
||
|
The timer interrupt handler is called by the system when the internal timer
|
||
|
(set by \scheme{set-timer}) expires.
|
||
|
The default handler raises an exception with condition type \scheme{&assertion}
|
||
|
to say that the handler has not
|
||
|
been defined; any program that uses the timer should redefine the
|
||
|
handler before setting the timer.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{disable-interrupts}{\categoryprocedure}{(disable-interrupts)}
|
||
|
\formdef{enable-interrupts}{\categoryprocedure}{(enable-interrupts)}
|
||
|
\returns disable count
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{disable-interrupts} disables the handling of interrupts,
|
||
|
including timer, keyboard, and collect request interrupts.
|
||
|
\scheme{enable-interrupts} re-enables these interrupts.
|
||
|
The system maintains a disable count that starts at zero; when zero,
|
||
|
interrupts are enabled.
|
||
|
Each call to \scheme{disable-interrupts} increments the count,
|
||
|
effectively disabling interrupts.
|
||
|
Each call to \scheme{enable-interrupts} decrements the count, if
|
||
|
not already zero, effectively enabling interrupts.
|
||
|
For example, two calls to \scheme{disable-interrupts} followed by one call to
|
||
|
\scheme{enable-interrupts} leaves interrupts disabled.
|
||
|
Calls to \scheme{enable-interrupts} when the count is already zero
|
||
|
(and interrupts are enabled) have no effect.
|
||
|
The value returned by either procedure is the number of calls to
|
||
|
\scheme{enable-interrupts} required to enable interrupts.
|
||
|
|
||
|
Great care should be exercised when using these procedures, since disabling
|
||
|
interrupts inhibits the normal processing of keyboard interrupts,
|
||
|
timer interrupts, and, perhaps most importantly, collect request interrupts.
|
||
|
Since garbage collection does not happen automatically when interrupts are
|
||
|
disabled, it is possible for the storage allocator to run out of space
|
||
|
unnecessarily should interrupts be disabled for a long period of time.
|
||
|
|
||
|
The \scheme{with-interrupts-disabled} syntactic form should be used instead of
|
||
|
these more primitive procedures whenever possible,
|
||
|
since \scheme{with-interrupts-disabled} ensures that interrupts are re-enabled
|
||
|
whenever a nonlocal exit occurs, such as when an exception is handled by
|
||
|
the default exception handler.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{with-interrupts-disabled}{\categorysyntax}{(with-interrupts-disabled \var{body_1} \var{body_2} \dots)}
|
||
|
\formdef{critical-section}{\categorysyntax}{(critical-section \var{body_1} \var{body_2} \dots)}
|
||
|
\returns the values of the body \scheme{\var{body_1} \var{body_2} \dots}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{with-interrupts-disabled} evaluates the body
|
||
|
\scheme{\var{body_1} \var{body_2} \dots} with interrupts disabled.
|
||
|
That is, upon entry, interrupts are disabled, and
|
||
|
upon exit, interrupts are re-enabled.
|
||
|
Thus, \scheme{with-interrupts-disabled} allows the implementation of indivisible
|
||
|
operations in nonthreaded versions of {\ChezScheme} or within a single thread
|
||
|
in threaded versions of {\ChezScheme}.
|
||
|
\scheme{critical-section} is the same as \scheme{with-interrupts-disabled} and
|
||
|
is provided for backward compatibility.
|
||
|
|
||
|
\scheme{with-interrupts-disabled} can be defined as follows.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax with-interrupts-disabled
|
||
|
(syntax-rules ()
|
||
|
[(_ b1 b2 ...)
|
||
|
(dynamic-wind
|
||
|
disable-interrupts
|
||
|
(lambda () b1 b2 ...)
|
||
|
enable-interrupts)]))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
The use of \scheme{dynamic-wind} ensures that interrupts are
|
||
|
disabled whenever the body of the \scheme{with-interrupts-disabled} expression
|
||
|
is active and re-enabled whenever it is not.
|
||
|
Since calls to \scheme{disable-interrupts} are counted (see the
|
||
|
discussion under \scheme{disable-interrupts} and
|
||
|
\scheme{enable-interrupts} above), \scheme{with-interrupts-disabled}
|
||
|
expressions may be nested with the desired effect.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{register-signal-handler}{\categoryprocedure}{(register-signal-handler \var{sig} \var{procedure})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{register-signal-handler} is used to
|
||
|
establish a signal handler for a given low-level signal.
|
||
|
\var{sig} must be an exact integer identifying a valid signal, and
|
||
|
\var{procedure} should accept one argument.
|
||
|
See your host system's \scheme{<signal.h>} or documentation for a list
|
||
|
of valid signals and their numbers.
|
||
|
After a signal handler for a given signal has been registered, receipt
|
||
|
of the specified signal results in a call to the handler.
|
||
|
The handler is passed the signal number, allowing the same handler to
|
||
|
be used for different signals while differentiating among them.
|
||
|
|
||
|
Signals handled in this fashion are treated like keyboard interrupts in
|
||
|
that the handler is not called immediately when the signal is delivered
|
||
|
to the process, but rather at some procedure call boundary after the
|
||
|
signal is delivered.
|
||
|
It is generally not a good idea, therefore, to establish handlers for
|
||
|
memory faults, illegal instructions, and the like, since the code that
|
||
|
causes the fault or illegal instruction will continue to execute
|
||
|
(presumably erroneously) for some time before the handler is invoked.
|
||
|
A finite amount of storage is used to buffer as-yet unhandled
|
||
|
signals, after which additional signals are dropped.
|
||
|
|
||
|
\scheme{register-signal-handler} is supported only on Unix-based
|
||
|
systems.
|
||
|
|
||
|
|
||
|
\section{Environments\label{SECTMISCENVIRONMENTS}}
|
||
|
|
||
|
Environments are first-class objects containing identifier bindings.
|
||
|
They are similar to modules but, unlike modules, may be manipulated
|
||
|
at run time.
|
||
|
Environments may be provided as optional arguments to \scheme{eval},
|
||
|
\scheme{expand}, and the procedures that define, assign, or
|
||
|
reference top-level values.
|
||
|
|
||
|
There are several built-in environments, and new environments can
|
||
|
be created by copying existing environments or selected bindings
|
||
|
from existing environments.
|
||
|
|
||
|
Environments can be mutable or immutable.
|
||
|
A mutable environment can be extended with new bindings, its
|
||
|
existing bindings can be modified, and its variables can be assigned.
|
||
|
An immutable environment cannot be modified in any of these ways.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{environment?}{\categoryprocedure}{(environment? \var{obj})}
|
||
|
\returns \scheme{#t} if \var{obj} is an environment, otherwise \scheme{#f}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\schemedisplay
|
||
|
(environment? (interaction-environment)) ;=> #t
|
||
|
(environment? 'interaction-environment) ;=> #f
|
||
|
(environment? (copy-environment (scheme-environment))) ;=> #t
|
||
|
(environment? (environment '(prefix (rnrs) $rnrs-))) ;=> #t
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{environment-mutable?}{\categoryprocedure}{(environment-mutable? \var{env})}
|
||
|
\returns \scheme{#t} if \var{env} is mutable, otherwise \scheme{#f}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\schemedisplay
|
||
|
(environment-mutable? (interaction-environment)) ;=> #t
|
||
|
(environment-mutable? (scheme-environment)) ;=> #f
|
||
|
(environment-mutable? (copy-environment (scheme-environment))) ;=> #t
|
||
|
(environment-mutable? (environment '(prefix (rnrs) $rnrs-))) ;=> #f
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{scheme-environment}{\categoryprocedure}{(scheme-environment)}
|
||
|
\returns an environment
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{scheme-environment} returns an environment containing
|
||
|
the initial top-level bindings.
|
||
|
This environment corresponds to the \scheme{scheme} module.
|
||
|
|
||
|
The environment returned by this procedure is immutable.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define cons 3)
|
||
|
(top-level-value 'cons (scheme-environment)) ;=> #<procedure cons>
|
||
|
(set-top-level-value! 'cons 3 (scheme-environment)) ;=> \var{exception}
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{ieee-environment}{\categoryprocedure}{(ieee-environment)}
|
||
|
\returns an IEEE/ANSI standard compatibility environment
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{ieee-environment} returns an environment containing
|
||
|
bindings for the keywords and variables whose meanings are
|
||
|
defined by the IEEE/ANSI Standard for Scheme~\cite{IEEE:1178}.
|
||
|
|
||
|
The bindings for each of the identifiers in the IEEE environment are those
|
||
|
of the corresponding Revised$^6$ Report library, so this does not provide
|
||
|
full backward compatibility.
|
||
|
|
||
|
The environment returned by this procedure is immutable.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define cons 3)
|
||
|
(top-level-value 'cons (ieee-environment)) ;=> #<procedure cons>
|
||
|
(set-top-level-value! 'cons 3 (ieee-environment)) ;=> \var{exception}
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{interaction-environment}{\categorythreadparameter}{interaction-environment}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The original value of \scheme{interaction-environment} is the default
|
||
|
top-level environment.
|
||
|
It is initially set to a mutable copy of
|
||
|
\scheme{(scheme-environment)} and which may be extended or otherwise
|
||
|
altered by top-level definitions and assignments.
|
||
|
It may be set to any environment, mutable or not, to change the
|
||
|
default top-level evaluation environment.
|
||
|
|
||
|
An expression's top-level bindings resolve to the environment that is
|
||
|
in effect when the expression is expanded, and changing the value
|
||
|
of this parameter has no effect on running code.
|
||
|
Changes affect only code that is subsequently expanded, e.g., as the
|
||
|
result of a call to \scheme{eval}, \scheme{load}, or
|
||
|
\scheme{compile-file}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define cons 3)
|
||
|
cons ;=> 3
|
||
|
(top-level-value 'cons (interaction-environment)) ;=> 3
|
||
|
|
||
|
(interaction-environment (scheme-environment))
|
||
|
cons ;=> #<procedure cons>
|
||
|
(set! cons 3) ;=> \var{exception: attempt to assign immutable variable}
|
||
|
(define cons 3) ;=> \var{exception: invalid definition in immutable environment}
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{copy-environment}{\categoryprocedure}{(copy-environment \var{env})}
|
||
|
\formdef{copy-environment}{\categoryprocedure}{(copy-environment \var{env} \var{mutable?})}
|
||
|
\formdef{copy-environment}{\categoryprocedure}{(copy-environment \var{env} \var{mutable?} \var{syms})}
|
||
|
\returns a new environment
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{copy-environment} returns a copy of \var{env}, i.e., a new
|
||
|
environment that contains the same bindings as \var{env}.
|
||
|
|
||
|
The environment is mutable if \var{mutable?} is omitted or true;
|
||
|
if \var{mutable?} is false, the environment is immutable.
|
||
|
|
||
|
The set of bindings copied from \var{env} to the new environment
|
||
|
is determined by \var{syms}, which defaults to the value of
|
||
|
\scheme{(environment-symbols \var{env})}.
|
||
|
The binding, if any, for each element of \var{syms} is copied to the
|
||
|
new environment, and no other bindings are present in the new
|
||
|
environment.
|
||
|
|
||
|
In the current implementation, the storage space used by an environment
|
||
|
is never collected, so repeated use of \scheme{copy-environment} will
|
||
|
eventually cause the system to run out of memory.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define e (copy-environment (scheme-environment)))
|
||
|
(eval '(define cons +) e)
|
||
|
(eval '(cons 3 4) e) ;=> 7
|
||
|
(eval '(cons 3 4) (scheme-environment)) ;=> (3 . 4)
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{environment-symbols}{\categoryprocedure}{(environment-symbols \var{env})}
|
||
|
\returns a list of symbols
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure returns a list of symbols representing the identifiers
|
||
|
bound in environment \var{env}.
|
||
|
It is primarily useful in building the list of symbols to be copied
|
||
|
from one environment to another.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define listless-environment
|
||
|
(copy-environment
|
||
|
(scheme-environment)
|
||
|
#t
|
||
|
(remq 'list (environment-symbols (scheme-environment)))))
|
||
|
(eval '(let ([x (cons 3 4)]) x) listless-environment) ;=> (3 . 4)
|
||
|
(eval '(list 3 4) listless-environment) ;=> \var{exception}
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{apropos-list}{\categoryprocedure}{(apropos-list \var{s})}
|
||
|
\formdef{apropos-list}{\categoryprocedure}{(apropos-list \var{s} \var{env})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure returns a selected list of symbols and pairs.
|
||
|
Each symbol in the list represents an identifier bound in \var{env}.
|
||
|
Each pair represents a set of identifiers exported by a
|
||
|
predefined library or a library previously defined or loaded
|
||
|
into the system.
|
||
|
The car of the pair is the library name, and the cdr is a list
|
||
|
of symbols.
|
||
|
If \var{s} is a string, only entries whose names have \var{s} as a
|
||
|
substring are included, and if \var{s} is a symbol, only those whose names
|
||
|
have the name of \var{s} as a substring are selected.
|
||
|
If no environment is provided, it defaults to the value of
|
||
|
\scheme{interaction-environment}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(library (a) (export a-vector-sortof) (import (rnrs))
|
||
|
(define a-vector-sortof '(vector 1 2 3)))
|
||
|
(apropos-list 'vector-sort) ;=>
|
||
|
(vector-sort vector-sort!
|
||
|
((a) a-vector-sortof)
|
||
|
((chezscheme) vector-sort vector-sort!)
|
||
|
((rnrs) vector-sort vector-sort!)
|
||
|
((rnrs sorting) vector-sort vector-sort!)
|
||
|
((scheme) vector-sort vector-sort!))
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{apropos}{\categoryprocedure}{(apropos \var{s})}
|
||
|
\formdef{apropos}{\categoryprocedure}{(apropos \var{s} \var{env})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{apropos} is like \scheme{apropos-list} except the information is
|
||
|
displayed to the current output port, as shown in the following
|
||
|
transcript.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (library (a) (export a-vector-sortof) (import (rnrs))
|
||
|
(define a-vector-sortof '(vector 1 2 3)))
|
||
|
> (apropos 'vector-sort)
|
||
|
interaction environment:
|
||
|
vector-sort, vector-sort!
|
||
|
(a):
|
||
|
a-vector-sortof
|
||
|
(chezscheme):
|
||
|
vector-sort, vector-sort!
|
||
|
(rnrs):
|
||
|
vector-sort, vector-sort!
|
||
|
(rnrs sorting):
|
||
|
vector-sort, vector-sort!
|
||
|
(scheme):
|
||
|
vector-sort, vector-sort!
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Compilation, Evaluation, and Loading\label{SECTMISCCOMPILEEVAL}}
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{eval}{\categoryprocedure}{(eval \var{obj})}
|
||
|
\formdef{eval}{\categoryprocedure}{(eval \var{obj} \var{env})}
|
||
|
\returns value of the Scheme form represented by \var{obj}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{eval} treats \var{obj} as the representation of an expression.
|
||
|
It evaluates the expression in environment \var{env} and returns
|
||
|
its value.
|
||
|
If no environment is provided, it defaults to the environment
|
||
|
returned by \scheme{interaction-environment}.
|
||
|
|
||
|
Single-argument \scheme{eval} is a {\ChezScheme} extension.
|
||
|
{\ChezScheme} also permits \var{obj} to be the representation of a
|
||
|
nonexpression form, i.e., a definition, whenever the environment
|
||
|
is mutable.
|
||
|
{\ChezScheme} further allows \var{obj} to be an annotation
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}), and the default evaluators
|
||
|
make use of annotations to incorporate source-file
|
||
|
information in error messages and associate source-file
|
||
|
information with compiled code.
|
||
|
|
||
|
In {\ChezScheme}, \scheme{eval} is actually a wrapper that simply
|
||
|
passes its arguments to the current evaluator.
|
||
|
(See \scheme{current-eval}.)
|
||
|
The default evaluator is \scheme{compile}, which expands the
|
||
|
expression via the current expander (see
|
||
|
\scheme{current-expand}), compiles it,
|
||
|
executes the resulting code, and returns its value.
|
||
|
If the environment argument, \var{env}, is present,
|
||
|
\scheme{compile} passes it along to the current expander,
|
||
|
which is \scheme{sc-expand} by default.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-eval}{\categorythreadparameter}{current-eval}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{current-eval} determines the evaluation procedure used by the
|
||
|
procedures \index{\scheme{eval}}\scheme{eval}, \scheme{load}, and
|
||
|
\scheme{new-cafe}.
|
||
|
\scheme{current-eval} is initially bound to the value of
|
||
|
\index{\scheme{compile}}\scheme{compile}.
|
||
|
(In {\PetiteChezScheme}, it is initially bound to the value of
|
||
|
\index{\scheme{interpret}}\scheme{interpret}.)
|
||
|
The evaluation procedure should expect one or two arguments: an object
|
||
|
to evaluate and an optional environment.
|
||
|
The second argument might be an annotation
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
|
||
|
\schemedisplay
|
||
|
(current-eval interpret)
|
||
|
(+ 1 1) ;=> 2
|
||
|
|
||
|
(current-eval (lambda (x . ignore) x))
|
||
|
(+ 1 1) ;=> (+ 1 1)
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile}{\categoryprocedure}{(compile \var{obj})}
|
||
|
\formdef{compile}{\categoryprocedure}{(compile \var{obj} \var{env})}
|
||
|
\returns value of the Scheme form represented by \var{obj}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{obj}, which can be an annotation (Section~\ref{SECTSYNTAXANNOTATIONS})
|
||
|
or unannotated value, is treated as a Scheme expression, expanded with the
|
||
|
current expander (the value of \scheme{current-expand}) in the specified
|
||
|
environment (or the interaction environment, if no environment
|
||
|
is provided), compiled to machine code, and executed.
|
||
|
\scheme{compile} is the default value of the \scheme{current-eval}
|
||
|
parameter.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{interpret}{\categoryprocedure}{(interpret \var{obj})}
|
||
|
\formdef{interpret}{\categoryprocedure}{(interpret \var{obj} \var{env})}
|
||
|
\returns value of the Scheme form represented by \var{obj}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{interpret} is like \scheme{compile}, except that the expression
|
||
|
is interpreted rather than compiled.
|
||
|
\scheme{interpret} may be used as a replacement for \scheme{compile},
|
||
|
with the following caveats:
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item
|
||
|
Interpreted code runs significantly slower.
|
||
|
|
||
|
\item
|
||
|
Inspector information is not generated for
|
||
|
interpreted code, so the inspector is not as useful for interpreted
|
||
|
code as it is for compiled code.
|
||
|
|
||
|
\item
|
||
|
Foreign procedure expressions cannot be
|
||
|
interpreted, so the interpreter invokes the compiler for all
|
||
|
foreign procedure expressions (this is done transparently).
|
||
|
\end{itemize}
|
||
|
|
||
|
\noindent
|
||
|
\scheme{interpret} is sometimes faster than \scheme{compile} when the
|
||
|
form to be evaluated is short running, since it avoids some of the
|
||
|
work done by \scheme{compile} prior to evaluation.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{load}{\categoryprocedure}{(load \var{path})}
|
||
|
\formdef{load}{\categoryprocedure}{(load \var{path} \var{eval-proc})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
\scheme{load} reads and evaluates the contents of the file specified by
|
||
|
\var{path}.
|
||
|
The file may contain source or object code.
|
||
|
By default, \scheme{load} employs \scheme{eval} to evaluate each source
|
||
|
expression found in a source file.
|
||
|
If \var{eval-proc} is specified, \scheme{load} uses this procedure instead.
|
||
|
\var{eval-proc} must accept one argument, the expression to evaluate.
|
||
|
The expression passed to \var{eval-proc} might be an annotation
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}) or an unannotated value.
|
||
|
|
||
|
The \var{eval-proc} argument
|
||
|
facilitates the implementation of embedded Scheme-like languages
|
||
|
and the use of alternate
|
||
|
evaluation mechanisms to be used for Scheme programs.
|
||
|
\var{eval-proc} can be put to other uses as well.
|
||
|
For example,
|
||
|
|
||
|
\schemedisplay
|
||
|
(load "myfile.ss"
|
||
|
(lambda (x)
|
||
|
(pretty-print
|
||
|
(if (annotation? x)
|
||
|
(annotation-stripped x)
|
||
|
x))
|
||
|
(newline)
|
||
|
(eval x)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
pretty-prints each expression before evaluating it.
|
||
|
|
||
|
\index{\scheme{source-directories}}%
|
||
|
The parameter \scheme{source-directories} (Section~\ref{SECTSYSTEMSOURCE})
|
||
|
determines the set of directories searched for source files not identified
|
||
|
by absolute path names.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{load-library}{\categoryprocedure}{(load-library \var{path})}
|
||
|
\formdef{load-library}{\categoryprocedure}{(load-library \var{path} \var{eval-proc})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{load-library} is identical to \scheme{load} except
|
||
|
that it treats the input file as if it were prefixed by an implicit
|
||
|
\scheme{#!r6rs}.
|
||
|
This effectively disables any non-R6RS lexical
|
||
|
syntax except where subsequently overridden by \scheme{#!chezscheme}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{load-program}{\categoryprocedure}{(load-program \var{path})}
|
||
|
\formdef{load-program}{\categoryprocedure}{(load-program \var{path} \var{eval-proc})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
\scheme{load-program} reads and evaluates the contents of the file specified by
|
||
|
\var{path}.
|
||
|
The file may contain source or object code.
|
||
|
If it contains source code, \scheme{load-program} wraps
|
||
|
the code in a \scheme{top-level-program} form so that the file's
|
||
|
content is treated as an RNRS top-level program
|
||
|
(Section~\ref{TSPL:SECTLIBPROGRAMS} of {\TSPLFOUR}).
|
||
|
By default, \scheme{load-program} employs \scheme{eval} to evaluate each source
|
||
|
expression found in the file.
|
||
|
If \var{eval-proc} is specified, \scheme{load-program} uses this procedure instead.
|
||
|
\var{eval-proc} must accept one argument, the expression to evaluate.
|
||
|
The expression passed to \var{eval-proc} might be an annotation
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}) or an unannotated value.
|
||
|
|
||
|
\index{\scheme{source-directories}}%
|
||
|
The parameter \scheme{source-directories} (Section~\ref{SECTSYSTEMSOURCE})
|
||
|
determines the set of directories searched for source files not identified
|
||
|
by absolute path names.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
|
||
|
\entryheader
|
||
|
\formdef{verify-loadability}{\categoryprocedure}{(verify-loadability \var{situation} \var{input} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{situation} must be one of the symbols \scheme{visit}, \scheme{revisit}, or \scheme{load}.
|
||
|
Each \var{input} must be a string pathname or a pair of a string pathname and a library search path.
|
||
|
Each of the pathnames should name a file containing object code for a set of libraries and
|
||
|
top-level programs, such as would be produced by
|
||
|
\index{\scheme{compile-program}}\scheme{compile-program},
|
||
|
\index{\scheme{compile-library}}\scheme{compile-library},
|
||
|
\index{\scheme{compile-whole-program}}\scheme{compile-whole-program},
|
||
|
or
|
||
|
\index{\scheme{compile-whole-library}}\scheme{compile-whole-library}.
|
||
|
A library search path must be a suitable argument for
|
||
|
\index{\scheme{library-directories}}\scheme{library-directories}.
|
||
|
|
||
|
\scheme{verify-loadability} verifies, without actually loading any
|
||
|
code or defining any libraries, whether the object files named
|
||
|
by the specified pathnames and their library dependencies, direct
|
||
|
or indirect, are present, readable, and mutually compatible.
|
||
|
The type of dependencies for each named object file is determined
|
||
|
by the \var{situation} argument: compile-time dependencies for
|
||
|
\var{visit}, run-time dependencies for \var{revisit} and both for
|
||
|
\var{load}.
|
||
|
|
||
|
For each input pathname that is paired with a search path,
|
||
|
the \scheme{library-directories} parameter is parameterized to the
|
||
|
library search path during the recursive search for dependencies
|
||
|
of the programs and libraries found in the object file named by the
|
||
|
pathname.
|
||
|
|
||
|
If \scheme{verify-loadability} finds a problem, such as a missing
|
||
|
library dependency or compilation-instance mismatch, it raises an
|
||
|
exception with an appropriate condition.
|
||
|
Otherwise, it returns an unspecified value.
|
||
|
|
||
|
Since \scheme{verify-loadability} does not load or run any code
|
||
|
from the files it processes, it cannot determine whether errors
|
||
|
unrelated to missing or unreadable files or mutual compatibility
|
||
|
will occur when the files are actually loaded.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{load-compiled-from-port}{\categoryprocedure}{(load-compiled-from-port \var{input-port})}
|
||
|
\returns result of the last compiled expression
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{load-compiled-from-port} reads and evaluates the object-code contents
|
||
|
of \var{input-port} as previously created by functions like \scheme{compile-file},
|
||
|
\scheme{compile-script}, \scheme{compile-library}, and
|
||
|
\scheme{compile-to-port}.
|
||
|
|
||
|
The return value is the value of the last expression whose compiled
|
||
|
form is in \var{input-port}. If \var{input-port} is empty, then the
|
||
|
result value is unspecified.
|
||
|
The port is left at end-of-file but is not closed.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{visit-compiled-from-port}{\categoryprocedure}{(visit-compiled-from-port \var{input-port})}
|
||
|
\returns result of the last compiled expression processed
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{visit-compiled-from-port} reads and evaluates the object-code contents
|
||
|
of \var{input-port} as previously created by functions like \scheme{compile-file},
|
||
|
\scheme{compile-script}, \scheme{compile-library}, and
|
||
|
\scheme{compile-to-port}. In the process, it skips any revisit (run-time-only) code.
|
||
|
|
||
|
The return value is the value of the last expression whose last non-revisit compiled
|
||
|
form is in \var{input-port}. If there are no such forms, then the
|
||
|
result value is unspecified.
|
||
|
The port is left at end-of-file but is not closed.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{revisit-compiled-from-port}{\categoryprocedure}{(revisit-compiled-from-port \var{input-port})}
|
||
|
\returns result of the last compiled expression processed
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{revisit-compiled-from-port} reads and evaluates the object-code contents
|
||
|
of \var{input-port} as previously created by functions like \scheme{compile-file},
|
||
|
\scheme{compile-script}, \scheme{compile-library}, and
|
||
|
\scheme{compile-to-port}. In the process, it skips any visit (compile-time-only) code.
|
||
|
|
||
|
The return value is the value of the last expression whose last non-visit compiled
|
||
|
form is in \var{input-port}. If there are no such forms, then the
|
||
|
result value is unspecified.
|
||
|
The port is left at end-of-file but is not closed.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{visit}{\categoryprocedure}{(visit \var{path})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
\scheme{visit} reads the named file, which must contain compiled object
|
||
|
code compatible with the current machine type and version, and it
|
||
|
runs those portions of the compiled object code that
|
||
|
establish compile-time information or correspond to expressions
|
||
|
identified as ``visit'' time by \scheme{eval-when} forms contained in
|
||
|
the original source file.
|
||
|
|
||
|
For example, assume the file \scheme{t1.ss} contains the following
|
||
|
forms:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax a (identifier-syntax 3))
|
||
|
(module m (x) (define x 4))
|
||
|
(define y 5)
|
||
|
\endschemedisplay
|
||
|
|
||
|
If \scheme{t1.ss} is compiled to \scheme{t1.so}, applying \scheme{load}
|
||
|
to \scheme{t1.so} has the effect of defining all three identifiers.
|
||
|
Applying \scheme{visit} to \scheme{t1.so}, however, has the effect of
|
||
|
installing the transformer for \scheme{a}, installing the interface for
|
||
|
\scheme{m} (for use by \scheme{import}), and recording \scheme{y} as
|
||
|
a variable.
|
||
|
\scheme{visit} is useful when separately compiling one file that depends
|
||
|
on bindings defined in another without actually loading and evaluating
|
||
|
the code in the supporting file.
|
||
|
|
||
|
\index{\scheme{source-directories}}%
|
||
|
The parameter \scheme{source-directories} (Section~\ref{SECTSYSTEMSOURCE})
|
||
|
determines the set of directories searched for source files not identified
|
||
|
by absolute path names.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{revisit}{\categoryprocedure}{(revisit \var{path})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
\scheme{revisit} reads the named file, which must contain compiled object
|
||
|
code compatible with the current machine type and version, and it
|
||
|
runs those portions of the compiled object code that compute
|
||
|
run-time values or correspond to expressions identified as ``revisit'' time by
|
||
|
\scheme{eval-when} forms contained in the original source file.
|
||
|
|
||
|
Continuing the example given for \scheme{visit} above,
|
||
|
applying \scheme{revisit} to the object file, \scheme{t1.so}, has
|
||
|
the effect of establishing the values of the variable \scheme{x}
|
||
|
exported from \scheme{m} and the top-level variable \scheme{y},
|
||
|
without installing either the interface for \scheme{m} or
|
||
|
the transformer for \scheme{a}.
|
||
|
|
||
|
\scheme{revisit} is useful for loading compiled application code without
|
||
|
loading unnecessary compile-time information.
|
||
|
Care must be taken when using this feature if the application calls
|
||
|
\scheme{eval} or uses \scheme{top-level-value},
|
||
|
\scheme{set-top-level-value!}, or \scheme{top-level-syntax} to access
|
||
|
top-level bindings at run-time, since these procedures use compile-time
|
||
|
information to resolve top-level bindings.
|
||
|
|
||
|
\index{\scheme{source-directories}}%
|
||
|
The parameter \scheme{source-directories} (Section~\ref{SECTSYSTEMSOURCE})
|
||
|
determines the set of directories searched for source files not identified
|
||
|
by absolute path names.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-file}{\categoryprocedure}{(compile-file \var{input-filename})}
|
||
|
\formdef{compile-file}{\categoryprocedure}{(compile-file \var{input-filename} \var{output-filename})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{input-filename} and \var{output-filename} must be strings.
|
||
|
\var{input-filename} must name an existing, readable file.
|
||
|
It must contain a sequence of zero or more source expressions;
|
||
|
if this is not the case, \scheme{compile-file} raises an exception
|
||
|
with condition type \scheme{&syntax}.
|
||
|
|
||
|
The normal evaluation process proceeds in two steps: \index{compilation}compilation and
|
||
|
execution.
|
||
|
\scheme{compile-file} performs the compilation process for an entire source
|
||
|
file, producing an object file.
|
||
|
When the object file is subsequently loaded (see \index{\scheme{load}}\scheme{load}), the
|
||
|
compilation process is not necessary, and the file typically loads
|
||
|
several times faster.
|
||
|
|
||
|
If the optional \var{output-filename} argument is omitted, the
|
||
|
actual input and output filenames are determined as follows.
|
||
|
If \var{input-filename} has no extension, the input filename
|
||
|
is \var{input-filename} followed by \scheme{.ss} and the
|
||
|
output filename is \var{input-filename} followed by \scheme{.so}.
|
||
|
If \var{input-filename} has the extension \scheme{.so}, the
|
||
|
input filename is \var{input-filename} and the output filename
|
||
|
is \var{input-filename} followed by \scheme{.so}.
|
||
|
Otherwise, the input filename is \var{input-filename} and the
|
||
|
output filename is \var{input-filename} without its extension,
|
||
|
followed by \scheme{.so}.
|
||
|
For example, \scheme{(compile-file "myfile")} produces an object file
|
||
|
with the name \scheme{"myfile.so"} from the source file named
|
||
|
\scheme{"myfile.ss"}, \scheme{(compile-file "myfile.sls")} produces an
|
||
|
object file with the name \scheme{"myfile.so"} from the source file named
|
||
|
\scheme{"myfile.sls"}, and
|
||
|
\scheme{(compile-file "myfile1" "myfile2")} produces an object file with
|
||
|
the name \scheme{"myfile2"} from the source file name \scheme{"myfile1"}.
|
||
|
|
||
|
Before compiling a file, \scheme{compile-file} saves the values of the
|
||
|
following parameters:
|
||
|
|
||
|
\schemedisplay
|
||
|
optimize-level
|
||
|
debug-level
|
||
|
run-cp0
|
||
|
cp0-effort-limit
|
||
|
cp0-score-limit
|
||
|
cp0-outer-unroll-limit
|
||
|
generate-inspector-information
|
||
|
generate-procedure-source-information
|
||
|
compile-profile
|
||
|
generate-covin-files
|
||
|
generate-interrupt-trap
|
||
|
enable-cross-library-optimization
|
||
|
\endschemedisplay
|
||
|
|
||
|
It restores the values after the file has been compiled.
|
||
|
This allows the programmer to control the values of these parameters on
|
||
|
a per-file basis, e.g., via an \scheme{eval-when} with situation
|
||
|
\scheme{compile} embedded in the source file.
|
||
|
For example, if
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile) (optimize-level 3))
|
||
|
\endschemedisplay
|
||
|
|
||
|
appears at the top of a source file, the optimization level is set
|
||
|
to 3 just while the remainder of file is compiled.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-script}{\categoryprocedure}{(compile-script \var{input-filename})}
|
||
|
\formdef{compile-script}{\categoryprocedure}{(compile-script \var{input-filename} \var{output-filename})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{input-filename} and \var{output-filename} must be strings.
|
||
|
|
||
|
\scheme{compile-script} is like \scheme{compile-file} but differs in
|
||
|
that it copies the leading \scheme{#!} line from the
|
||
|
source-file script into the object file.
|
||
|
|
||
|
\scheme{compile-script} permits compiled script files to be created from
|
||
|
source script to reduce script load time.
|
||
|
As with source-code scripts, compiled scripts may be run with the
|
||
|
\index{\scheme{--script} command-line option}\scheme{--script}
|
||
|
command-line option.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-library}{\categoryprocedure}{(compile-library \var{input-filename})}
|
||
|
\formdef{compile-library}{\categoryprocedure}{(compile-library \var{input-filename} \var{output-filename})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{input-filename} and \var{output-filename} must be strings.
|
||
|
|
||
|
\scheme{compile-library} is identical to \scheme{compile-file} except
|
||
|
that it treats the input file as if it were prefixed by an implicit
|
||
|
\scheme{#!r6rs}.
|
||
|
This effectively disables any non-R6RS lexical
|
||
|
syntax except where subsequently overridden by \scheme{#!chezscheme}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-program}{\categoryprocedure}{(compile-program \var{input-filename})}
|
||
|
\formdef{compile-program}{\categoryprocedure}{(compile-program \var{input-filename} \var{output-filename})}
|
||
|
\returns a list of libraries invoked by the program
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{input-filename} and \var{output-filename} must be strings.
|
||
|
|
||
|
\scheme{compile-program} is like \scheme{compile-script} but differs in
|
||
|
that it implements the semantics of RNRS top-level programs, while
|
||
|
\scheme{compile-script} implements the semantics of the interactive
|
||
|
top-level.
|
||
|
The resulting compiled program will also run faster than if compiled
|
||
|
via \scheme{compile-file} or \scheme{compile-script}.
|
||
|
|
||
|
\scheme{compile-program} returns a list of libraries directly
|
||
|
invoked by the compiled top-level program, excluding built-in
|
||
|
libraries like \scheme{(rnrs)} and \scheme{(chezscheme)}.
|
||
|
The procedure \scheme{library-requirements} may be used to determine
|
||
|
the indirect requirements, i.e., additional libraries required by
|
||
|
the directly invoked libraries.
|
||
|
When combined with \scheme{library-object-filename}, this information can
|
||
|
be used to determine the set of files that must be distributed with the
|
||
|
compiled program file.
|
||
|
|
||
|
A program invokes a library only if it references one or more variables
|
||
|
exported from the library.
|
||
|
The set of libraries invoked by a top-level program, and hence
|
||
|
loaded when the program is loaded, might be smaller than the set
|
||
|
imported by the program, and it might be larger than the set
|
||
|
directly imported by the program.
|
||
|
|
||
|
As with source-code top-level programs, compiled top-level programs may be
|
||
|
run with the
|
||
|
\index{\scheme{--program} command-line option}\scheme{--program}
|
||
|
command-line option.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{maybe-compile-file}{\categoryprocedure}{(maybe-compile-file \var{input-filename})}
|
||
|
\formdef{maybe-compile-file}{\categoryprocedure}{(maybe-compile-file \var{input-filename} \var{output-filename})}
|
||
|
\formdef{maybe-compile-library}{\categoryprocedure}{(maybe-compile-library \var{input-filename})}
|
||
|
\formdef{maybe-compile-library}{\categoryprocedure}{(maybe-compile-library \var{input-filename} \var{output-filename})}
|
||
|
\formdef{maybe-compile-program}{\categoryprocedure}{(maybe-compile-program \var{input-filename})}
|
||
|
\formdef{maybe-compile-program}{\categoryprocedure}{(maybe-compile-program \var{input-filename} \var{output-filename})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
These procedures are like their non-\scheme{maybe} counterparts but
|
||
|
compile the source file only if the object file is out-of-date.
|
||
|
An object file \var{X} is considered out-of-date if it does not exist or
|
||
|
if it is older than the source file or any files included (via \scheme{include})
|
||
|
when \var{X} was created.
|
||
|
When the value of the parameter \scheme{compile-imported-libraries}
|
||
|
is \scheme{#t}, \var{X} is also considered out-of-date if the object
|
||
|
file for any library imported when \var{X} was compiled is out-of-date.
|
||
|
If \scheme{maybe-compile-file} determines that compilation is necessary,
|
||
|
it compiles the source file by passing \scheme{compile-file} the
|
||
|
input and output filenames.
|
||
|
\scheme{compile-library} does so by similarly invoking the value of the
|
||
|
\scheme{compile-library-handler} parameter, and
|
||
|
\scheme{compile-program} does so by similarly invoking the value of the
|
||
|
\scheme{compile-program-handler} parameter.
|
||
|
|
||
|
When \var{output-filename} is not specified, the input and output
|
||
|
filenames are determined in the same manner as for \scheme{compile-file}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-library-handler}{\categorythreadparameter}{compile-library-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This parameter must be set to a procedure, and the procedure should
|
||
|
accept two string arguments naming a source file and an object file.
|
||
|
The procedure should typically invoke \scheme{compile-library} and
|
||
|
pass it the two arguments, but it can also use one of the other
|
||
|
file or port compilation procedures.
|
||
|
For example, it might read the source file using its own parser and
|
||
|
use \index{\scheme{compile-to-file}}\scheme{compile-to-file} to finish
|
||
|
the compilation process.
|
||
|
The procedure can perform other actions as well, such as parameterizing
|
||
|
compilation parameters, establishing guards, or gathering statistics.
|
||
|
The default value of this parameter simply invokes
|
||
|
\scheme{compile-library} on the two string arguments without taking
|
||
|
any other action.
|
||
|
|
||
|
The value of this parameter is called by \scheme{maybe-compile-library}
|
||
|
when the object file is out-of-date.
|
||
|
It is also called by the expander to compile an
|
||
|
imported library when \scheme{compile-imported-libraries} is \scheme{#t}
|
||
|
and the expander determines the object file is out-of-date.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-program-handler}{\categorythreadparameter}{compile-program-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This parameter must be set to a procedure, and the procedure should
|
||
|
accept two string arguments naming a source file and an object file.
|
||
|
The procedure should typically invoke \scheme{compile-program} and
|
||
|
pass it the two arguments, but it can also use one of the other
|
||
|
file or port compilation procedures.
|
||
|
For example, it might read the source file using its own parser and
|
||
|
use \index{\scheme{compile-to-file}}\scheme{compile-to-file} to finish
|
||
|
the compilation process.
|
||
|
The procedure can perform other actions as well, such as parameterizing
|
||
|
compilation parameters, establishing guards, or gathering statistics.
|
||
|
The default value of this parameter simply invokes
|
||
|
\scheme{compile-program} on the two string arguments without taking
|
||
|
any other action and returns the list of libraries returned by
|
||
|
\scheme{compile-program}.
|
||
|
|
||
|
The value of this parameter is called by \scheme{maybe-compile-program}
|
||
|
when the object file is out-of-date.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-whole-program}{\categoryprocedure}{(compile-whole-program \var{input-filename} \var{output-filename})}
|
||
|
\formdef{compile-whole-program}{\categoryprocedure}{(compile-whole-program \var{input-filename} \var{output-filename} \var{libs-visible?})}
|
||
|
\returns a list of libraries left to be loaded at run time
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{compile-whole-program} accepts as input a filename naming
|
||
|
a ``whole program optimization'' (wpo) file for a top-level program
|
||
|
and produces an object file incorporating the program and each
|
||
|
library upon which it depends, provided that a wpo file for the
|
||
|
library can be found.
|
||
|
|
||
|
If a wpo file for a required library cannot be found, but an object
|
||
|
file for the library can, the library is not incorporated in the
|
||
|
resulting object file.
|
||
|
Such libraries are left to be loaded at run time.
|
||
|
\scheme{compile-whole-program} returns a list of such libraries.
|
||
|
If there are no such libraries, the resulting object file is
|
||
|
self-contained and \scheme{compile-whole-program} returns the empty
|
||
|
list.
|
||
|
|
||
|
The libraries incorporated into the resulting object file are visible (for
|
||
|
use by \scheme{environment} and \scheme{eval}) if the \var{libs-visible?}
|
||
|
argument is supplied and non-false.
|
||
|
Any library incorporated into the resulting object file and required by
|
||
|
an object file left to be loaded at run time is also visible, as are any
|
||
|
libraries the object file depends upon, regardless of the value of
|
||
|
\var{libs-visible?}.
|
||
|
|
||
|
\scheme{compile-whole-program} linearizes the initialization code for the
|
||
|
set of incorporated libraries in a way that respects static
|
||
|
dependencies among the libraries but not necessary dynamic dependencies
|
||
|
deriving from initialization-time uses of \scheme{environment}
|
||
|
or \scheme{eval}.
|
||
|
Additional static dependencies can be added in most cases to force
|
||
|
an ordering that allows the dynamic imports to succeed,
|
||
|
though not in general since a different order might be required each
|
||
|
time the program is run.
|
||
|
Adding a static dependency of one library on a second requires
|
||
|
adding an import of the second in the first as well as a run-time
|
||
|
reference to one of the variables exported by the second in the
|
||
|
body of the first.
|
||
|
|
||
|
\var{input-filename} and \var{output-filename} must be strings.
|
||
|
\var{input-filename} must identify a wpo file, and a wpo or object
|
||
|
file must also be present for each required library somewhere in
|
||
|
the directories specified by the \scheme{library-directories}
|
||
|
parameter.
|
||
|
|
||
|
To the extent possible given the specified set of visible libraries
|
||
|
and requirements of libraries to be loaded at run time,
|
||
|
\scheme{compile-whole-program} discards unused code and optimizes
|
||
|
across program and library boundaries, potentially reducing program
|
||
|
load time, run time, and memory requirements.
|
||
|
Some optimization also occurs even across the boundaries of libraries
|
||
|
that are not incorporated into the output, though this optimization
|
||
|
is limited in nature.
|
||
|
|
||
|
\index{\scheme{generate-wpo-files}}%
|
||
|
The procedures \scheme{compile-file}, \scheme{compile-program}, \scheme{compile-library},
|
||
|
\scheme{compile-script}, and \scheme{compile-whole-library} produce wpo files as well as ordinary
|
||
|
object files when the \scheme{generate-wpo-files} parameter is set
|
||
|
to \scheme{#t} (the default is \scheme{#f}).
|
||
|
\scheme{compile-port} and \scheme{compile-to-port} do so when passed
|
||
|
an optional wpo port.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-whole-library}{\categoryprocedure}{(compile-whole-library \var{input-filename} \var{output-filename})}
|
||
|
\returns a list of libraries left to be loaded at run time
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{compile-whole-library} is like \scheme{compile-whole-program},
|
||
|
except \var{input-filename} must specify a wpo file for a library,
|
||
|
all libraries are automatically made visible, and a new wpo file is
|
||
|
produced (when \scheme{generate-wpo-files} is \scheme{#t}) as well
|
||
|
as an object file for the resulting combination of libraries.
|
||
|
|
||
|
The comment in the description of \scheme{compile-whole-program}
|
||
|
about the effect of initialization-code linearization on dynamic
|
||
|
dependencies applies to \scheme{compile-whole-library} as well.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-port}{\categoryprocedure}{(compile-port \var{input-port} \var{output-port})}
|
||
|
\formdef{compile-port}{\categoryprocedure}{(compile-port \var{input-port} \var{output-port} \var{sfd})}
|
||
|
\formdef{compile-port}{\categoryprocedure}{(compile-port \var{input-port} \var{output-port} \var{sfd} \var{wpo-port})}
|
||
|
\formdef{compile-port}{\categoryprocedure}{(compile-port \var{input-port} \var{output-port} \var{sfd} \var{wpo-port} \var{covop})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{input-port} must be a textual input port.
|
||
|
\var{output-port} and, if present and non-false, \var{wpo-port} must be binary output ports.
|
||
|
If present and non-false, \var{sfd} must be a source-file descriptor.
|
||
|
If present and non-false, \var{covop} must be a textual output port.
|
||
|
|
||
|
\scheme{compile-port} is like \scheme{compile-file} except that it takes
|
||
|
input from an arbitrary textual input port and sends output to an arbitrary
|
||
|
binary output port.
|
||
|
If \var{sfd} is supplied, it is passed to the reader so that source information
|
||
|
can be associated with the expressions read from \var{input-port}.
|
||
|
It is also used to associate block-profiling information with the input
|
||
|
file name encapsulated within \var{sfd}.
|
||
|
If \var{wpo-port} is supplied, \scheme{compile-port} sends whole-program optimization information
|
||
|
to \var{wpo-port} for use by \scheme{compile-whole-program}, as if
|
||
|
(and regardless of whether) \scheme{generate-wpo-files} is set.
|
||
|
If \var{covop} is supplied, \scheme{compile-port} sends coverage information to
|
||
|
\var{covop}, as if (and regardless of whether) \scheme{generate-covin-files} is set.
|
||
|
|
||
|
The ports are closed automatically after compilation under the assumption
|
||
|
the program that opens the ports and invokes \scheme{compile-port}
|
||
|
will take care of closing the ports.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-to-port}{\categoryprocedure}{(compile-to-port \var{obj-list} \var{output-port})}
|
||
|
\formdef{compile-to-port}{\categoryprocedure}{(compile-to-port \var{obj-list} \var{output-port} \var{sfd})}
|
||
|
\formdef{compile-to-port}{\categoryprocedure}{(compile-to-port \var{obj-list} \var{output-port} \var{sfd} \var{wpo-port})}
|
||
|
\formdef{compile-to-port}{\categoryprocedure}{(compile-to-port \var{obj-list} \var{output-port} \var{sfd} \var{wpo-port} \var{covop})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{obj-list} must be a list containing a sequence of
|
||
|
objects that represent syntactically valid expressions, each possibly
|
||
|
annotated (Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
If any of the objects does not represent a syntactically valid
|
||
|
expression, \scheme{compile-to-port} raises an exception with
|
||
|
condition type \scheme{&syntax}.
|
||
|
\var{output-port} and, if present, \var{wpo-port} must be binary output ports.
|
||
|
If present, \var{sfd} must be a source-file descriptor.
|
||
|
|
||
|
\scheme{compile-to-port} is like \scheme{compile-file} except that it takes
|
||
|
input from a list of objects and sends output to an arbitrary binary
|
||
|
output port.
|
||
|
\var{sfd} is used to associate block-profiling information with the
|
||
|
input file name encapsulated within \var{sfd}.
|
||
|
If \var{wpo-port} is present, \var{compile-to-port} sends whole-program optimization information
|
||
|
to \var{wpo-port} for use by \scheme{compile-whole-program}, as if
|
||
|
(and regardless of whether) \scheme{generate-wpo-files} is set.
|
||
|
If \var{covop} is present, \var{compile-to-port} sends coverage information to
|
||
|
\var{covop}, as if (and regardless of whether) \scheme{generate-covin-files} is set.
|
||
|
|
||
|
The ports are not closed automatically after compilation under the assumption
|
||
|
the program that opens the port and invokes \scheme{compile-to-port}
|
||
|
will take care of closing the port.
|
||
|
|
||
|
When \var{obj-list} contains a single list-structured element whose
|
||
|
first-element is the symbol \scheme{top-level-program},
|
||
|
\scheme{compile-to-port} returns a list of the libraries the top-level
|
||
|
program requires at run time, as with \scheme{compile-program}.
|
||
|
Otherwise, the return value is unspecified.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-to-file}{\categoryprocedure}{(compile-to-file \var{obj-list} \var{output-file})}
|
||
|
\formdef{compile-to-file}{\categoryprocedure}{(compile-to-file \var{obj-list} \var{output-file} \var{sfd})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{obj-list} must be a list containing a sequence of
|
||
|
objects that represent syntactically valid expressions, each possibly
|
||
|
annotated (Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
If any of the objects does not represent a syntactically valid
|
||
|
expression, \scheme{compile-to-file} raises an exception with
|
||
|
condition type \scheme{&syntax}.
|
||
|
\var{output-file} must be a string.
|
||
|
If present, \var{sfd} must be a source-file descriptor.
|
||
|
|
||
|
\scheme{compile-to-file} is like \scheme{compile-file} except that it takes
|
||
|
input from a list of objects.
|
||
|
\var{sfd} is used to associate block-profiling information with the
|
||
|
input file name encapsulated within \var{sfd}.
|
||
|
|
||
|
When \var{obj-list} contains a single list-structured element whose
|
||
|
first-element is the symbol \scheme{top-level-program},
|
||
|
\scheme{compile-to-file} returns a list of the libraries the top-level
|
||
|
program requires at run time, as with \scheme{compile-program}.
|
||
|
Otherwise, the return value is unspecified.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{concatenate-object-files}{\categoryprocedure}{(concatenate-object-files \var{out-file} \var{in-file_1} \var{in-file_2} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{out-file} and each \var{in-file} must be strings.
|
||
|
|
||
|
\scheme{concatenate-object-files} combines the header information
|
||
|
contained in the object files named by each \var{in-file}. It then
|
||
|
writes the combined header information to the file named by
|
||
|
\var{out-file}, followed by the remaining object code from each
|
||
|
input file in turn.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-boot-file}{\categoryprocedure}{(make-boot-file \var{output-filename} \var{base-boot-list} \var{input-filename} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{output-filename}, \var{input-filename}, and the elements of
|
||
|
\var{base-boot-list} must be strings.
|
||
|
|
||
|
\scheme{make-boot-file} writes a boot header to the file named by
|
||
|
\var{output-filename}, followed by the object code for each
|
||
|
\var{input-filename} in turn.
|
||
|
If an input file is not already compiled, \scheme{make-boot-file} compiles
|
||
|
the file as it proceeds.
|
||
|
|
||
|
The boot header identifies the elements of \var{base-boot-list} as
|
||
|
alternative boot files upon which the new boot file depends.
|
||
|
If the list of strings naming base boot files is empty, the first named
|
||
|
input file should be a base boot file, i.e., petite.boot or some boot file
|
||
|
derived from petite.boot.
|
||
|
|
||
|
\index{\scheme{--boot} command-line option}%
|
||
|
\index{\scheme{-b} command-line option}%
|
||
|
Boot files are loaded explicitly via the \scheme{--boot} or \scheme{-b}
|
||
|
command-line options or implicitly based on the name of the executable
|
||
|
(Section~\ref{SECTUSECOMMANDLINE}).
|
||
|
|
||
|
See Section~\ref{SECTUSEAPPLICATIONS} for more information on boot files
|
||
|
and the use of \scheme{make-boot-file}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-boot-header}{\categoryprocedure}{(make-boot-header \var{output-filename} \var{base-boot_1} \var{base-boot_2}\dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure has been subsumed by \scheme{make-boot-file} and is provided for
|
||
|
backward compatibility.
|
||
|
The call
|
||
|
|
||
|
\schemedisplay
|
||
|
(make-boot-header \var{output-filename} \var{base-boot_1} \var{base-boot_2} \dots)
|
||
|
\endschemedisplay
|
||
|
|
||
|
is equivalent to
|
||
|
|
||
|
\schemedisplay
|
||
|
(make-boot-file \var{output-filename} '(\var{base-boot_1} \var{base-boot_2} \dots))
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{strip-fasl-file}{\categoryprocedure}{(strip-fasl-file \var{input-path} \var{output-path} \var{options})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{input-path} and \var{output-path} must be strings.
|
||
|
\var{input-path} must name an existing, readable file containing
|
||
|
object code produced by \scheme{compile-file}, one of the other
|
||
|
file-compiling procedures, or an earlier run of \scheme{strip-fasl-file}.
|
||
|
\var{options} must be an enumeration set over the symbols constituting
|
||
|
valid strip options, as described in the \scheme{fasl-strip-options}
|
||
|
entry below.
|
||
|
|
||
|
The new procedure \scheme{strip-fasl-file} allows the removal of
|
||
|
source information of various sorts from a compiled object (fasl)
|
||
|
file produced by \scheme{compile-file} or one of the other file
|
||
|
compiling procedures.
|
||
|
It also allows removal of library visit code from object files
|
||
|
containing compiled libraries.
|
||
|
Visit code is the code for macro transformers and meta definitions
|
||
|
required to compile (but not run) dependent libraries.
|
||
|
|
||
|
On most platforms, the input and output paths can be the same,
|
||
|
in which case the input file is replaced with a new file containing
|
||
|
the stripped object code.
|
||
|
Using the same path will likely fail on Windows file systems,
|
||
|
which do not generally permit an open file to be removed.
|
||
|
|
||
|
If \var{options} is empty, the output file is effectively equivalent
|
||
|
to the input file, though it will not necessarily be identical.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{fasl-strip-options}{\categorysyntax}{(fasl-strip-options \var{symbol} \dots)}
|
||
|
\returns a fasl-strip-options enumeration set
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Fasl-strip-options enumeration sets are passed to \scheme{strip-fasl-file}
|
||
|
to determine what is stripped.
|
||
|
The available options are described below.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{inspector-source}:]
|
||
|
Strip inspector source information.
|
||
|
This includes source expressions that might otherwise be available
|
||
|
for procedures and continuations with the ``code'' and ``call''
|
||
|
commands and messages in the interactive and object inspectors.
|
||
|
It also includes filename and position information that might
|
||
|
otherwise be available for the same via the ``file'' command and
|
||
|
``source'' messages.
|
||
|
|
||
|
\item[\scheme{source-annotations}:]
|
||
|
Strip source annotations, which typically appear only on syntax objects,
|
||
|
e.g., identifiers, in the templates of macro transformers.
|
||
|
|
||
|
\item[\scheme{profile-source}:]
|
||
|
Strip source file and character position information from profiled
|
||
|
code objects.
|
||
|
This does not remove the profile counters or eliminate the overhead
|
||
|
for incrementing them at run time.
|
||
|
|
||
|
\item[\scheme{compile-time-information}: ]
|
||
|
This strips compile-time information from compiled libraries, potentially
|
||
|
reducing the size of the resulting file but making it impossible to
|
||
|
use the file to compile dependent code.
|
||
|
This option is useful for creating smaller object files to ship
|
||
|
as part of a binary-only package.
|
||
|
\end{description}
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{machine-type}{\categoryprocedure}{(machine-type)}
|
||
|
\returns the current machine type
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Consult the release notes for the current version of {\ChezScheme}
|
||
|
for a list of supported machine types.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:expand}
|
||
|
\formdef{expand}{\categoryprocedure}{(expand \var{obj})}
|
||
|
\formdef{expand}{\categoryprocedure}{(expand \var{obj} \var{env})}
|
||
|
\returns expansion of the Scheme form represented by \var{obj}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{expand} treats \var{obj} as the representation of an expression.
|
||
|
It expands the expression in environment \var{env} and returns
|
||
|
an object representing the expanded form.
|
||
|
If no environment is provided, it defaults to the environment
|
||
|
returned by \scheme{interaction-environment}.
|
||
|
|
||
|
\var{obj} can be an annotation
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}), and the default expander
|
||
|
makes use of annotations to incorporate source-file
|
||
|
information in error messages.
|
||
|
|
||
|
\scheme{expand} actually passes its arguments to the current expander
|
||
|
(see \scheme{current-expand}), initially \scheme{sc-expand}.
|
||
|
|
||
|
\index{\scheme{expand-output}}%
|
||
|
See also \scheme{expand-output} (page~\pageref{desc:expand-output})
|
||
|
which can be used to request that the compiler or interpreter show
|
||
|
expander output.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-expand}{\categorythreadparameter}{current-expand}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{current-expand} determines the expansion procedure used by
|
||
|
the compiler, interpreter, and direct calls to
|
||
|
\index{\scheme{expand}}\scheme{expand}
|
||
|
to expand syntactic extensions.
|
||
|
\scheme{current-expand} is initially bound to the value of
|
||
|
\index{\scheme{sc-expand}}\scheme{sc-expand}.
|
||
|
|
||
|
It may be set another procedure, but since the format of
|
||
|
expanded code expected by the compiler and interpreter is not publicly
|
||
|
documented, only \scheme{sc-expand} produces correct output, so the
|
||
|
other procedure must ultimately be defined in terms of
|
||
|
\scheme{sc-expand}.
|
||
|
|
||
|
The first argument to the expansion procedure represents the input
|
||
|
expression.
|
||
|
It can be an annotation (Section~\ref{SECTSYNTAXANNOTATIONS}) or an
|
||
|
unannotated value.
|
||
|
the second argument is an environment.
|
||
|
Additional arguments might be passed to the expansion procedure
|
||
|
by the compiler, interpreter, and \scheme{expand}; their number
|
||
|
and roles are unspecified.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sc-expand}{\categoryprocedure}{(sc-expand \var{obj})}
|
||
|
\formdef{sc-expand}{\categoryprocedure}{(sc-expand \var{obj} \var{env})}
|
||
|
\returns the expanded form of \var{obj}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
|
||
|
\noindent
|
||
|
The procedure
|
||
|
\scheme{sc-expand} is used to expand programs written using
|
||
|
\scheme{syntax-case} macros.
|
||
|
\scheme{sc-expand} is the default expander, i.e., the initial
|
||
|
value of \scheme{current-expand}.
|
||
|
\var{obj} represents the program to be expanded, and
|
||
|
\var{env} must be an environment.
|
||
|
\var{obj} can be an annotation (Section~\ref{SECTSYNTAXANNOTATIONS})
|
||
|
or unannotated value.
|
||
|
If not provided, \var{env} defaults to the environment returned by
|
||
|
\scheme{interaction-environment}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:expand/optimize}
|
||
|
\formdef{expand/optimize}{\categoryprocedure}{(expand/optimize \var{obj})}
|
||
|
\formdef{expand/optimize}{\categoryprocedure}{(expand/optimize \var{obj} \var{env})}
|
||
|
\returns result of expanding and optimizing form represented by \var{obj}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{expand/optimize} treats \var{obj} as the representation of
|
||
|
an expression.
|
||
|
\var{obj} can be an annotation (Section~\ref{SECTSYNTAXANNOTATIONS})
|
||
|
or unannotated value.
|
||
|
\scheme{expand/optimize} expands the expression in environment \var{env}
|
||
|
and passes the expression through the source optimizer \scheme{cp0}
|
||
|
(unless \scheme{cp0} is disabled via \scheme{run-cp0}).
|
||
|
It also simplifies \scheme{letrec} and \scheme{letrec*} expressions within
|
||
|
the expression and makes their undefined checks explicit.
|
||
|
It returns an object representing the expanded, simplified, and optimized form.
|
||
|
If no environment is provided, it defaults to the environment
|
||
|
returned by \scheme{interaction-environment}.
|
||
|
|
||
|
\scheme{expand/optimize} is primarily useful for understanding what
|
||
|
\scheme{cp0} does and does not optimize.
|
||
|
Many optimizations are performed later in the compiler,
|
||
|
so \scheme{expand/optimize} does not give a complete picture of
|
||
|
optimizations performed.
|
||
|
|
||
|
\schemedisplay
|
||
|
(expand/optimize
|
||
|
'(let ([y '(3 . 4)])
|
||
|
(+ (car y) (cdr y)))) ;=> 7
|
||
|
|
||
|
(print-gensym #f)
|
||
|
(expand/optimize
|
||
|
'(let ([y '(3 . 4)])
|
||
|
(lambda (x)
|
||
|
(* (+ (car y) (cdr y)) x)))) ;=> (lambda (x) (#2%* 7 x))
|
||
|
|
||
|
(expand/optimize
|
||
|
'(let ([n (expt 2 10)])
|
||
|
(define even?
|
||
|
(lambda (x) (or (zero? x) (not (odd? x)))))
|
||
|
(define odd?
|
||
|
(lambda (x) (not (even? (- x 1)))))
|
||
|
(define f
|
||
|
(lambda (x)
|
||
|
(lambda (y)
|
||
|
(lambda (z)
|
||
|
(if (= z 0) (omega) (+ x y z))))))
|
||
|
(define omega
|
||
|
(lambda ()
|
||
|
((lambda (x) (x x)) (lambda (x) (x x)))))
|
||
|
(let ([g (f 1)] [m (f n)])
|
||
|
(let ([h (if (> ((g 2) 3) 5)
|
||
|
(lambda (x) (+ x 1))
|
||
|
odd?)])
|
||
|
(h n))))) ;=> 1025
|
||
|
\endschemedisplay
|
||
|
|
||
|
\index{\scheme{expand/optimize-output}}%
|
||
|
See also \scheme{expand/optimize-output} (page~\pageref{desc:expand/optimize-output})
|
||
|
which can be used to request that the compiler or interpreter show
|
||
|
source-optimizer output.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{eval-when}{\categorysyntax}{(eval-when \var{situations} \var{form_1} \var{form_2} \dots)}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{situations} must be a list containing some combination of the symbols
|
||
|
\scheme{eval}, \scheme{compile}, \scheme{load}, \scheme{visit}, and
|
||
|
\scheme{revisit}.
|
||
|
|
||
|
When source files are loaded (see \scheme{load}), the forms in the file
|
||
|
are read, compiled, and executed sequentially, so that each form in
|
||
|
the file is fully evaluated before the next one is read.
|
||
|
When a source file is compiled (see \scheme{compile-file}), however, the
|
||
|
forms are read and compiled, \emph{but not executed}, in sequence.
|
||
|
This distinction matters only when the execution of one
|
||
|
form in the file affects the compilation of later forms, e.g.,
|
||
|
when the form results in the definition of a module or syntactic form or
|
||
|
sets a compilation parameter such as \scheme{optimize-level} or
|
||
|
\scheme{case-sensitive}.
|
||
|
|
||
|
For example, assume that a file contains the following two forms:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax reverse-define
|
||
|
(syntax-rules ()
|
||
|
[(_ e x) (define x e)]))
|
||
|
|
||
|
(reverse-define 3 three)
|
||
|
\endschemedisplay
|
||
|
|
||
|
Loading this from source has the effect of defining
|
||
|
\scheme{reverse-define} as a syntactic form and binding the identifier
|
||
|
\scheme{three} to 3.
|
||
|
The situation may be different if the file is compiled with
|
||
|
\scheme{compile-file}, however.
|
||
|
Unless the system or programmer takes steps to assure that the first
|
||
|
form is fully executed before the second expression is compiled,
|
||
|
the syntax expander will not recognize \scheme{reverse-define} as a syntactic
|
||
|
form and will generate code for a procedure call to \scheme{reverse-define}
|
||
|
instead of generating code to define \scheme{three} to be 3.
|
||
|
When the object file is subsequently loaded, the attempt to reference
|
||
|
either \scheme{reverse-define} or \scheme{three} will fail.
|
||
|
|
||
|
As it happens, when a \scheme{define-syntax}, \scheme{module},
|
||
|
\scheme{import}, or \scheme{import-only} form appears at top level, as in the
|
||
|
example above, the compiler does indeed arrange to evaluate it before
|
||
|
going on to compile the remainder of the file.
|
||
|
If the compiler encounters a variable definition for an identifier that
|
||
|
was previously something else, it records that fact as well.
|
||
|
The compiler also generates the
|
||
|
appropriate code so that the bindings will be present as well when
|
||
|
the object file is subsequently loaded.
|
||
|
This solves most, but not all, problems of this nature, since most are
|
||
|
related to the use of \scheme{define-syntax} and modules.
|
||
|
Some problems are not so straightforwardly handled, however.
|
||
|
For example, assume that the file contains the following definitions
|
||
|
for \index{\scheme{nodups?}}\scheme{nodups?} and \index{\scheme{mvlet}}\scheme{mvlet}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define nodups?
|
||
|
(lambda (ids)
|
||
|
(define bound-id-member?
|
||
|
(lambda (id ids)
|
||
|
(and (not (null? ids))
|
||
|
(or (bound-identifier=? id (car ids))
|
||
|
(bound-id-member? id (cdr ids))))))
|
||
|
(or (null? ids)
|
||
|
(and (not (bound-id-member? (car ids) (cdr ids)))
|
||
|
(nodups? (cdr ids))))))
|
||
|
|
||
|
(define-syntax mvlet
|
||
|
(lambda (x)
|
||
|
(syntax-case x ()
|
||
|
[(_ ((x ...) expr) b1 b2 ...)
|
||
|
(and (andmap identifier? #'(x ...))
|
||
|
(nodups? #'(x ...)))
|
||
|
#'(call-with-values
|
||
|
(lambda () expr)
|
||
|
(lambda (x ...) b1 b2 ...))])))
|
||
|
|
||
|
(mvlet ((a b c) (values 1 2 3))
|
||
|
(list (* a a) (* b b) (* c c)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
When loaded directly, this results in the definition of
|
||
|
\scheme{nodups?} as a procedure and \scheme{mvlet} as a syntactic
|
||
|
abstraction before evaluation of the \scheme{mvlet} expression.
|
||
|
Because \scheme{nodups?} is defined before the \scheme{mvlet}
|
||
|
expression is expanded, the call to \scheme{nodups?} during the
|
||
|
expansion of \scheme{mvlet} causes no difficulty.
|
||
|
If instead this file were compiled, using \scheme{compile-file}, the
|
||
|
compiler would arrange to define \scheme{mvlet} before continuing
|
||
|
with the expansion and evaluation of the \scheme{mvlet} expression,
|
||
|
but it would not arrange to define \scheme{nodups?}.
|
||
|
Thus the expansion of the \scheme{mvlet} expression would fail.
|
||
|
|
||
|
In this case it does not help to evaluate the syntactic extension alone.
|
||
|
A solution in this case would be to move the definition of
|
||
|
\scheme{nodups?} inside the definition for \scheme{mvlet}, just as
|
||
|
the definition for \scheme{bound-id-member?} is placed within
|
||
|
\scheme{nodups?}, but this does not work for help routines shared
|
||
|
among several syntactic definitions.
|
||
|
Another solution is to label the \scheme{nodups?} definition a
|
||
|
``meta'' definition (see Section~\ref{SECTSYNTAXMETA}) but this
|
||
|
does not work for helpers that are used both by syntactic
|
||
|
abstractions and by run-time code.
|
||
|
|
||
|
A somewhat simpler problem occurs when setting parameters that affect
|
||
|
compilation, such as \scheme{optimize-level} and
|
||
|
\scheme{case-sensitive?}.
|
||
|
If not set prior to compilation, their settings usually will not have
|
||
|
the desired effect.
|
||
|
|
||
|
\scheme{eval-when} offers a solution to these problems by allowing the
|
||
|
programmer to explicitly control what forms should or should not
|
||
|
be evaluated during compilation.
|
||
|
\scheme{eval-when} is a syntactic form and is handled directly by the
|
||
|
expander.
|
||
|
The action of \scheme{eval-when} depends upon the \var{situations} argument
|
||
|
and whether or not the forms \scheme{\var{form_1} \var{form_2} \dots}
|
||
|
are being compiled via \scheme{compile-file} or are being evaluated
|
||
|
directly.
|
||
|
Let's consider each of the possible situation specifiers
|
||
|
\scheme{eval}, \scheme{compile}, \scheme{load}, \scheme{visit}, and
|
||
|
\scheme{revisit} in turn.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{eval}:]
|
||
|
The \scheme{eval} specifier is relevant only when the \scheme{eval-when}
|
||
|
form is being
|
||
|
evaluated directly, i.e., if it is typed at the keyboard or loaded from a
|
||
|
source file.
|
||
|
Its presence causes \scheme{\var{form_1} \var{form_2} \dots} to be
|
||
|
expanded and this expansion to be included in the expansion of the
|
||
|
\scheme{eval-when} form.
|
||
|
Thus, the forms will be evaluated directly as if not contained within an
|
||
|
\scheme{eval-when} form.
|
||
|
|
||
|
\item[\scheme{compile}:]
|
||
|
The \scheme{compile} specifier is relevant only when the \scheme{eval-when}
|
||
|
form appears in a file currently being compiled.
|
||
|
(Its presence is simply ignored otherwise.)
|
||
|
Its presence forces \scheme{\var{form_1} \var{form_2} \dots} to be
|
||
|
expanded and evaluated immediately.
|
||
|
|
||
|
\item[\scheme{load}:]
|
||
|
The \scheme{load} specifier is also relevant only when the \scheme{eval-when}
|
||
|
form appears
|
||
|
in a file currently being compiled.
|
||
|
Its presence causes \scheme{\var{form_1} \var{form_2} \dots} to be
|
||
|
expanded and this expansion to be included in the expansion of the
|
||
|
\scheme{eval-when} form.
|
||
|
Any code necessary to record binding information and evaluate syntax
|
||
|
transformers for definitions contained in the forms is marked for
|
||
|
execution when the file is ``visited,'' and any code necessary to
|
||
|
compute the values of variable definitions and the expressions contained
|
||
|
within the forms is marked for execution when the file is ``revisited.''
|
||
|
|
||
|
\item[\scheme{visit}:]
|
||
|
The \scheme{visit} specifier is also relevant only when the \scheme{eval-when}
|
||
|
form appears
|
||
|
in a file currently being compiled.
|
||
|
Its presence causes \scheme{\var{form_1} \var{form_2} \dots} to be
|
||
|
expanded and this expansion to be included in the expansion of the
|
||
|
\scheme{eval-when} form, with an annotation that the forms are to be
|
||
|
executed when the file is ``visited.''
|
||
|
|
||
|
\item[\scheme{revisit}:]
|
||
|
The \scheme{revisit} specifier is also relevant only when the \scheme{eval-when}
|
||
|
form appears
|
||
|
in a file currently being compiled.
|
||
|
Its presence causes \scheme{\var{form_1} \var{form_2} \dots} to be
|
||
|
expanded and this expansion to be included in the expansion of the
|
||
|
\scheme{eval-when} form, with an annotation that the forms are to be
|
||
|
executed when the file is ``revisited.''
|
||
|
\end{description}
|
||
|
|
||
|
\noindent
|
||
|
A file is considered ``visited'' when it is brought in by either
|
||
|
\scheme{load} or \scheme{visit} and ``revisited'' when it is brought in
|
||
|
by either \scheme{load} or \scheme{revisit}.
|
||
|
|
||
|
Top-level expressions are treated as if they are wrapped in an
|
||
|
\scheme{eval-when} with situations \scheme{load} and \scheme{eval}.
|
||
|
This means that, by default, forms typed at the keyboard or
|
||
|
loaded from a source file are evaluated, and forms appearing in a
|
||
|
file to be compiled are not evaluated directly but are compiled for
|
||
|
execution when the resulting object file is subsequently loaded.
|
||
|
|
||
|
The treatment of top-level definitions is slightly more involved.
|
||
|
All definitions result in changes to the compile-time environment.
|
||
|
For example, an identifier defined by \scheme{define} is recorded
|
||
|
as a variable, and an identifier defined by \scheme{define-syntax}
|
||
|
is recorded as a keyword and associated with the value of its
|
||
|
right-hand-side (transformer) expression.
|
||
|
These changes are made at eval, compile, and load
|
||
|
time as if the definitions were wrapped in an \scheme{eval-when} with
|
||
|
situations \scheme{eval}, \scheme{load}, and \scheme{compile}.
|
||
|
(This behavior can be altered by changing the value of the
|
||
|
parameter \scheme{eval-syntax-expanders-when}.)
|
||
|
Some definitions also result in changes to the run-time environment.
|
||
|
For example, a variable is associated with the value of its
|
||
|
right-hand-side expression.
|
||
|
These changes are made just at evaluation and load time as if the
|
||
|
definitions were wrapped in an \scheme{eval-when} with situations
|
||
|
\scheme{eval} and \scheme{load}.
|
||
|
|
||
|
The treatment of local expressions or definitions (those not at top level)
|
||
|
that are wrapped in an \scheme{eval-when} depends only upon whether the
|
||
|
situation \scheme{eval} is present in the list of situations.
|
||
|
If the situation \scheme{eval} is present, the definitions and expressions
|
||
|
are evaluated as if they were not wrapped in an \scheme{eval-when} form,
|
||
|
i.e., the \scheme{eval-when} form is treated as a \scheme{begin} form.
|
||
|
If the situation \scheme{eval} is not present, the forms are ignored;
|
||
|
in a definition context, the \scheme{eval-when} form is treated as an
|
||
|
empty \scheme{begin}, and in an expression context, the \scheme{eval-when}
|
||
|
form is treated as a constant with an unspecified value.
|
||
|
|
||
|
Since top-level syntax bindings are established, by default, at compile
|
||
|
time as well as eval and load time, top-level variable bindings needed
|
||
|
by syntax transformers should be wrapped in an \scheme{eval-when} form
|
||
|
with situations \scheme{compile}, \scheme{load}, and \scheme{eval}.
|
||
|
We can thus \scheme{nodups?} problem above by enclosing the definition
|
||
|
of \scheme{nodups?} in an \scheme{eval-when} as follows.
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile load eval)
|
||
|
(define nodups?
|
||
|
(lambda (ids)
|
||
|
(define bound-id-member?
|
||
|
(lambda (id ids)
|
||
|
(and (not (null? ids))
|
||
|
(or (bound-identifier=? id (car ids))
|
||
|
(bound-id-member? id (cdr ids))))))
|
||
|
(or (null? ids)
|
||
|
(and (not (bound-id-member? (car ids) (cdr ids)))
|
||
|
(nodups? (cdr ids)))))))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
This forces it to be evaluated before it is needed during the expansion
|
||
|
of the \scheme{mvlet} expression.
|
||
|
|
||
|
Just as it is useful to add \scheme{compile} to the default
|
||
|
\scheme{load} and \scheme{eval} situations, omitting options is also
|
||
|
useful.
|
||
|
Omitting one or more of \scheme{compile}, \scheme{load}, and
|
||
|
\scheme{eval} has the effect of preventing the evaluation at the given
|
||
|
time.
|
||
|
Omitting all of the options has the effect of inhibiting evaluation
|
||
|
altogether.
|
||
|
|
||
|
One common combination of situations is \scheme{(compile eval)}, which by the
|
||
|
inclusion of \scheme{compile} causes the expression to be evaluated at
|
||
|
compile time, and by the omission of \scheme{load} inhibits the generation
|
||
|
of code by the compiler for execution when the file is subsequently loaded.
|
||
|
This is typically used for the definition of syntactic extensions used only
|
||
|
within the file in which they appear; in this case their presence in the
|
||
|
object file is not necessary.
|
||
|
It is also used to set compilation parameters that are intended to be in
|
||
|
effect whether the file is loaded from source or compiled via
|
||
|
\scheme{compile-file}
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile eval) (case-sensitive #t))
|
||
|
\endschemedisplay
|
||
|
|
||
|
Another common situations list is \scheme{(compile)}, which might be
|
||
|
used to set compilation options to be used only when the file is
|
||
|
compiled via \scheme{compile-file}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile) (optimize-level 3))
|
||
|
\endschemedisplay
|
||
|
|
||
|
Finally, one other common combination is \scheme{(load eval)}, which might
|
||
|
be useful for inhibiting the double evaluation (during the compilation of
|
||
|
a file and again when the resulting object file is loaded) of syntax
|
||
|
definitions when the syntactic extensions are not needed within
|
||
|
the file in which their definitions appear.
|
||
|
|
||
|
The behavior of \scheme{eval-when} is usually intuitive but can be
|
||
|
understood precisely as follows.
|
||
|
The \scheme{syntax-case} expander, which handles \scheme{eval-when}
|
||
|
forms, maintains two state sets, one for compile-time forms and
|
||
|
one for run-time forms.
|
||
|
The set of possible states in each set are ``L'' for \scheme{load},
|
||
|
``C'' for \scheme{compile}, ``V'' for \scheme{visit}, ``R'' for
|
||
|
\scheme{revisit}, and ``E'' for \scheme{eval}.
|
||
|
|
||
|
When compiling a file, the compile-time set initially contains ``L''
|
||
|
and ``C'' and the run-time set initially contains only ``L.''
|
||
|
When not compiling a file (as when a form is evaluated by the
|
||
|
read-eval-print loop or loaded from a source file), both sets
|
||
|
initially contain only ``E.''
|
||
|
The subforms of an \scheme{eval-when} form at top level are expanded with
|
||
|
new compile- and run-time sets determined by the current sets and
|
||
|
the situations listed in the \scheme{eval-when} form.
|
||
|
Each element of the current set contributes zero or more elements to the
|
||
|
new set depending upon the given situations according to the following
|
||
|
table.
|
||
|
|
||
|
\begin{tabular}{cccccc}
|
||
|
& \scheme{load}~ & ~\scheme{compile}~ & ~\scheme{visit}~ & ~\scheme{revisit}~ & ~\scheme{eval}\\
|
||
|
L & L & C & V & R & --- \\
|
||
|
C & --- & --- & --- & --- & C \\
|
||
|
V & V & C & V & --- & --- \\
|
||
|
R & R & C & --- & R & --- \\
|
||
|
E & --- & --- & --- & --- & E \\
|
||
|
\end{tabular}
|
||
|
|
||
|
For example, if the current compile-time state set is \{L\}
|
||
|
and the situations are \scheme{load} and \scheme{compile}, the new compile-time
|
||
|
state set is \{L,~C\}, since L/\scheme{load}
|
||
|
contributes ``L'' and L/\scheme{compile} contributes ``C.''
|
||
|
|
||
|
The state sets determine how forms are treated by the expander.
|
||
|
Compile-time forms such as syntax definitions are evaluated at a time
|
||
|
or times determined by the compile-time state set, and run-time forms
|
||
|
are evaluated at a time or times determined by the run-time state set.
|
||
|
A form is evaluated immediately if ``C'' is in the state set.
|
||
|
Code is generated to evaluate the form at visit or revisit
|
||
|
time if ``V'' or ``R'' is present.
|
||
|
If ``L'' is present in the compile-time set, it is treated as ``V;''
|
||
|
likewise, if ``L'' is present in the run-time set, it is treated as
|
||
|
``R.''
|
||
|
If more than one of states is present in the state set, the
|
||
|
form is evaluated at each specified time.
|
||
|
|
||
|
``E'' can appear in the state set only when not compiling a file, i.e.,
|
||
|
when the expander is invoked from an evaluator such as \scheme{compile}
|
||
|
or \scheme{interpret}.
|
||
|
When it does appear, the expanded form is returned from the expander to be
|
||
|
processed by the evaluator, e.g., \scheme{compile} or \scheme{interpret},
|
||
|
that invoked the expander.
|
||
|
|
||
|
The value of the parameter \scheme{eval-syntax-expanders-when} actually determines
|
||
|
the initial compile-time state set.
|
||
|
The parameter is bound to a list of situations, which defaults to
|
||
|
\scheme{(compile load eval)}.
|
||
|
When compiling a file, \scheme{compile} contributes ``C'' to the
|
||
|
state set, \scheme{load} contributes ``L,'' \scheme{visit} contributes
|
||
|
``V,'' \scheme{revisit} contributes ``R,'' and \scheme{eval}
|
||
|
contributes nothing.
|
||
|
When not compiling a file, \scheme{eval} contributes ``E'' to the
|
||
|
state set, and the other situations contribute nothing.
|
||
|
There is no corresponding parameter for controlling the initial value
|
||
|
of the run-time state set.
|
||
|
|
||
|
\label{eval-when-tlp}%
|
||
|
For RNRS top-level programs, \scheme{eval-when} is essentially ineffective.
|
||
|
The entire program is treated as a single expression, so \scheme{eval-when}
|
||
|
becomes a local \scheme{eval-when} for which only the \scheme{eval}
|
||
|
situation has any relevance.
|
||
|
As for any local \scheme{eval-when} form, the subforms are ignored if
|
||
|
the \scheme{eval} situation is not present; otherwise, they are treated as
|
||
|
if the \scheme{eval-when} wrapper were absent.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{eval-syntax-expanders-when}{\categorythreadparameter}{eval-syntax-expanders-when}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
This parameter must be set to a list representing a set of
|
||
|
\scheme{eval-when} situations, e.g., a list containing at most one
|
||
|
occurrence of each of the symbols \scheme{eval}, \scheme{compile},
|
||
|
\scheme{load}, \scheme{visit}, and \scheme{revisit}.
|
||
|
It is used to determine the evaluation time of syntax
|
||
|
definitions, module forms, and import forms are expanded.
|
||
|
(See the discussion of \scheme{eval-when} above.)
|
||
|
The default value is \scheme{(compile load eval)}, which causes
|
||
|
compile-time information in a file to be established when the file is
|
||
|
loaded from source, when it is compiled via \scheme{compile-file},
|
||
|
and when a compiled version of the file is loaded via \scheme{load}
|
||
|
or \scheme{visit}.
|
||
|
|
||
|
\section{Source Directories and Files\label{SECTSYSTEMSOURCE}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{source-directories}{\categoryglobalparameter}{source-directories}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of \scheme{source-directories} must be a list of strings, each
|
||
|
of which names a directory path.
|
||
|
\scheme{source-directories} determines the set of directories searched
|
||
|
for source or object files when a file is loaded via \scheme{load}, \scheme{load-library},
|
||
|
\scheme{load-program}, \scheme{include},
|
||
|
\scheme{visit}, or \scheme{revisit},
|
||
|
when a syntax error occurs, or when a source
|
||
|
file is opened in the interactive inspector.
|
||
|
|
||
|
The default value is the list \scheme{(".")}, which means source files
|
||
|
will be found only in or relative to the current directory, unless named
|
||
|
with an absolute path.
|
||
|
|
||
|
This parameter is never altered by the system, with one exception.
|
||
|
The expander temporarily adds (via \scheme{parameterize}) the directory
|
||
|
in which a library file resides to the front of the \scheme{source-directories}
|
||
|
list when it compiles (when \scheme{compile-imported-libraries} is true) or loads the library from source, which it does
|
||
|
only if the library is not already defined.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{with-source-path}{\categoryprocedure}{(with-source-path \var{who} \var{name} \var{procedure})}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The procedure \scheme{with-source-path} searches through the current
|
||
|
source-directories path, in order, for a file with the specified
|
||
|
\var{name} and invokes \var{procedure} on the result.
|
||
|
If no such file is found, an exception is raised with condition types
|
||
|
\scheme{&assertion} and \scheme{&who} with \var{who} as
|
||
|
who value.
|
||
|
|
||
|
If \var{name} is an absolute pathname or one beginning with \scheme{./}
|
||
|
(or \scheme{.\} under Windows) or \scheme{../} (or \scheme{..\} under
|
||
|
Windows), or if the list of source directories
|
||
|
contains only \scheme{"."}, the default, or \scheme{""}, which is
|
||
|
equivalent to \scheme{"."}, no searching is performed and \var{name} is
|
||
|
returned.
|
||
|
|
||
|
\var{who} must be a symbol, \var{name} must be a string, and
|
||
|
\var{procedure} should accept one argument.
|
||
|
|
||
|
The following examples assumes that the file ``pie'' exists
|
||
|
in the directory ``../spam'' but not in ``../ham'' or the current
|
||
|
directory.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define find-file
|
||
|
(lambda (fn)
|
||
|
(with-source-path 'find-file fn values)))
|
||
|
|
||
|
(find-file "pie") ;=> "pie"
|
||
|
|
||
|
(source-directories '("." "../ham"))
|
||
|
(find-file "pie") ;=> \var{exception in find-file: pie not found}
|
||
|
|
||
|
(source-directories '("." "../spam"))
|
||
|
(find-file "pie") ;=> "../spam/pie"
|
||
|
|
||
|
(source-directories '("." "../ham"))
|
||
|
(find-file "/pie") ;=> "/pie"
|
||
|
|
||
|
(source-directories '("." "../ham"))
|
||
|
(find-file "./pie") ;=> "./pie"
|
||
|
|
||
|
(source-directories '("." "../spam"))
|
||
|
(find-file "../pie") ;=> "../ham/pie"
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Compiler Controls\label{SECTMISCOPTIMIZE}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{optimize-level}{\categorythreadparameter}{optimize-level}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
This parameter can take on one of the four values 0, 1, 2, and 3.
|
||
|
|
||
|
In theory, this parameter controls the amount of optimization
|
||
|
performed by the compiler.
|
||
|
In practice, it does so only indirectly, and the only difference
|
||
|
is between optimize level 3, at which the compiler generates
|
||
|
``unsafe'' code, and optimize levels 0--2, at which the compiler
|
||
|
generates ``safe'' code.
|
||
|
Safe code performs full type and bounds checking so that, for example,
|
||
|
an attempt to apply a non-procedure, an attempt to take the car of a
|
||
|
non-pair, or an attempt to reference beyond the end of a vector each
|
||
|
result in an exception being raised.
|
||
|
With unsafe code, the same situations may result in invalid memory
|
||
|
references, corruption of the Scheme heap (which may cause
|
||
|
seemingly unrelated problems later), system crashes, or other undesirable
|
||
|
behaviors.
|
||
|
Unsafe code is typically faster, but optimize-level 3 should be used with
|
||
|
caution and only on sections of well-tested code that must run as quickly
|
||
|
as possible.
|
||
|
|
||
|
While the compiler produces the same code for optimize levels 0--2,
|
||
|
user-defined macro transformers can differentiate among the different
|
||
|
levels if desired.
|
||
|
|
||
|
One way to use optimize levels is on a per-file
|
||
|
basis, using \index{\scheme{eval-when}}\scheme{eval-when} to force the use of a particular
|
||
|
optimize level at compile time.
|
||
|
For example, placing:
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile) (optimize-level 3))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
at the front of a file will cause all of the forms in the file to be
|
||
|
compiled at optimize level 3 when the file is compiled (using
|
||
|
\index{\scheme{compile-file}}\scheme{compile-file}) but does not affect the optimize level used
|
||
|
when the file is loaded from source.
|
||
|
Since \scheme{compile-file} parameterizes \scheme{optimize-level} (see \scheme{parameterize}),
|
||
|
the above
|
||
|
expression does not permanently alter the optimize level in the
|
||
|
system in which the \scheme{compile-file} is performed.
|
||
|
|
||
|
The optimize level can also be set via the
|
||
|
\index{\scheme{--optimize-level} command-line option}\scheme{--optimize-level}
|
||
|
command-line option (Section~\ref{SECTUSECOMMANDLINE}).
|
||
|
This option is particularly useful for running RNRS top-level programs
|
||
|
at optimize-level~3 via the
|
||
|
\index{\scheme{--program} command-line option}\scheme{--program} command-line option,
|
||
|
since \scheme{eval-when} is ineffective for RNRS top-level programs as described
|
||
|
on page~\pageref{eval-when-tlp}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:hash-primitive}
|
||
|
\xformdef{$primitive (~#%~)}{$primitive (~#%~)@\scheme{$primitive} (~\scheme{#%}~)}{\categorysyntax}{($primitive \var{variable})}
|
||
|
\xformdef{!L#% ($primitive)}{#% ($primitive)@\scheme{#%} (\scheme{$primitive})}{\categorysyntax}{#%\var{variable}}
|
||
|
\xformdef{$primitive (~#2%~)}{$primitive (~#2%~)@\scheme{$primitive} (~\scheme{#2%}~)}{\categorysyntax}{($primitive 2 \var{variable})}
|
||
|
\xformdef{!M#2% ($primitive)}{#% ($primitive)@\scheme{#2%} (\scheme{$primitive})}{\categorysyntax}{#2%\var{variable}}
|
||
|
\xformdef{$primitive (~#3%~)}{$primitive (~#3%~)@\scheme{$primitive} (~\scheme{#3%}~)}{\categorysyntax}{($primitive 3 \var{variable})}
|
||
|
\xformdef{!N#3% ($primitive)}{#% ($primitive)@\scheme{#3%} (\scheme{$primitive})}{\categorysyntax}{#3%\var{variable}}
|
||
|
\returns the primitive value for \var{variable}
|
||
|
\libraryexport{$primitive}\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{variable} must name a primitive procedure.
|
||
|
The \scheme{$primitive} syntactic form allows control over the
|
||
|
optimize level at the granularity of individual primitive references,
|
||
|
and it can be used to access the original value
|
||
|
of a primitive, regardless of the lexical context or the current
|
||
|
top-level binding for the variable originally bound to the primitive.
|
||
|
|
||
|
The expression \scheme{($primitive \var{variable})} may
|
||
|
be abbreviated as \scheme{#%\var{variable}}.
|
||
|
The reader expands \scheme{#%} followed by an object
|
||
|
into a \scheme{$primitive} expression, much as it expands \scheme{'\var{object}}
|
||
|
into a \scheme{quote} expression.
|
||
|
|
||
|
If a \scheme{2} or \scheme{3} appears in the form or between the
|
||
|
\scheme{#} and \scheme{%} in the abbreviated form, the compiler treats
|
||
|
an application of the primitive as if it were compiled
|
||
|
at the corresponding optimize level (see the \scheme{optimize-level}
|
||
|
parameter).
|
||
|
If no number appears in the form, an application of the primitive is
|
||
|
treated as an optimize-level 3 application if the current optimize
|
||
|
level is 3;
|
||
|
otherwise, it is treated as an optimize-level 2 application.
|
||
|
|
||
|
\schemedisplay
|
||
|
(#%car '(a b c)) ;=> a
|
||
|
(let ([car cdr]) (car '(a b c))) ;=> (b c)
|
||
|
(let ([car cdr]) (#%car '(a b c))) ;=> a
|
||
|
(begin (set! car cdr) (#%car '(a b c))) ;=> a
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{debug-level}{\categorythreadparameter}{debug-level}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
This parameter can take on one of the four values 0, 1, 2, and 3.
|
||
|
It is used to tell the compiler how important the preservation of
|
||
|
debugging information is, with 0 being least important and 3 being
|
||
|
most important.
|
||
|
The default value is 1.
|
||
|
As of Version~9.0, it is used solely to determine whether an
|
||
|
error-causing call encountered in nontail position is treated as
|
||
|
if it were in tail position (thus causing the caller's frame not
|
||
|
to appear in a stack backtrace); this occurs at debug levels below~2.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{generate-interrupt-trap}{\categorythreadparameter}{generate-interrupt-trap}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
To support interrupts, including keyboard, timer, and collect request
|
||
|
interrupts, the compiler inserts a short sequence of instructions at the
|
||
|
entry to each nonleaf procedure (Section~\ref{SECTSYSTEMINTERRUPTS}).
|
||
|
This small overhead may be eliminated by setting
|
||
|
\scheme{generate-interrupt-trap} to \scheme{#f}.
|
||
|
The default value of this parameter is \scheme{#t}.
|
||
|
|
||
|
It is rarely a good idea to compile code without interrupt trap
|
||
|
generation, since a tight loop in the generated code may completely
|
||
|
prevent interrupts from being serviced, including the collect request
|
||
|
interrupt that causes garbage collections to occur automatically.
|
||
|
Disabling trap generation may be useful, however, for routines that act
|
||
|
simply as ``wrappers'' for other routines for which code is presumably
|
||
|
generated with interrupt trap generation enabled.
|
||
|
It may also be useful for short performance-critical routines with
|
||
|
embedded loops or recursions that are known to be short running and
|
||
|
that make no other calls.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-interpret-simple}{\categorythreadparameter}{compile-interpret-simple}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
At all optimize levels, when the value of
|
||
|
\scheme{compile-interpret-simple} is set to a true value (the default),
|
||
|
\index{\scheme{compile}}\scheme{compile} interprets simple
|
||
|
expressions.
|
||
|
A simple expression is one that creates no procedures.
|
||
|
This can save a significant amount of time over the course of many
|
||
|
calls to \scheme{compile} or \scheme{eval} (with \scheme{current-eval}
|
||
|
set to \scheme{compile}, its default value).
|
||
|
When set to false, \scheme{compile} compiles all expressions.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:generate-inspector-information}
|
||
|
\formdef{generate-inspector-information}{\categorythreadparameter}{generate-inspector-information}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
When this parameter is set to a true value (the default), information
|
||
|
about the source and contents of procedures and continuations is
|
||
|
generated during compilation and retained in tables associated with
|
||
|
each code segment.
|
||
|
This information allows the inspector to provide more complete
|
||
|
information, at the expense of using more memory and producing
|
||
|
larger object files (via \scheme{compile-file}).
|
||
|
Although compilation and loading may be slower when inspector
|
||
|
information is generated, the speed of the compiled code is not
|
||
|
affected.
|
||
|
If this parameter is changed during the compilation of a file, the
|
||
|
original value will be restored.
|
||
|
For example, if:
|
||
|
|
||
|
\schemedisplay
|
||
|
(eval-when (compile) (generate-inspector-information #f))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
is included in a file, generation of inspector information will be
|
||
|
disabled only for the remainder of that particular file.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:generate-procedure-source-information}
|
||
|
\formdef{generate-procedure-source-information}{\categorythreadparameter}{generate-procedure-source-information}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
When \scheme{generate-inspector-information} is set to \scheme{#f} and
|
||
|
this parameter is set to \scheme{#t}, then a source location is preserved
|
||
|
for a procedure, even though other inspector information is not preserved.
|
||
|
Source information provides a small amount of debugging support at a
|
||
|
much lower cost in memory and object-file size than full inspector information.
|
||
|
If this parameter is changed during the compilation of a file, the
|
||
|
original value will be restored.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{enable-cross-library-optimization}{\categorythreadparameter}{enable-cross-library-optimization}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This parameter controls whether information is included with the
|
||
|
object code for a compiled library to enable propagation of constants
|
||
|
and inlining of procedures defined in the library into dependent
|
||
|
libraries.
|
||
|
When set to \scheme{#t} (the default), this information is included;
|
||
|
when set to \scheme{#f}, the information is not included.
|
||
|
Setting the parameter to \scheme{#f} potentially reduces the sizes
|
||
|
of the resulting object files and the exposure of near-source
|
||
|
information via the object file.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{generate-wpo-files}{\categorythreadparameter}{generate-wpo-files}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\index{\scheme{compile-whole-program}}%
|
||
|
When this parameter is set to \scheme{#t} (the default is \scheme{#f}),
|
||
|
\scheme{compile-file}, \scheme{compile-library}, \scheme{compile-program},
|
||
|
and \scheme{compile-script} produce whole-program optimization (wpo)
|
||
|
files for use by \scheme{compile-whole-program}.
|
||
|
The name of the \scheme{wpo} file is derived from the output-file
|
||
|
name by replacing the object-file extension (normally \scheme{.so})
|
||
|
with \scheme{.wpo}, or adding the extension \scheme{.wpo} if the
|
||
|
object filename has no extension or has the extension \scheme{.wpo}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-file-message}{\categorythreadparameter}{compile-file-message}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
When this parameter is set to true, the default, \scheme{compile-file},
|
||
|
\scheme{compile-library}, \scheme{compile-program}, and
|
||
|
\scheme{compile-script} print a message of the form:
|
||
|
|
||
|
\schemedisplay
|
||
|
compiling \var{input-path} with output to \var{output-path}
|
||
|
\endschemedisplay
|
||
|
|
||
|
When the parameter is set to \scheme{#f}, the message is not printed.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:run-cp0}
|
||
|
\formdef{run-cp0}{\categorythreadparameter}{run-cp0}
|
||
|
\formdef{cp0-effort-limit}{\categorythreadparameter}{cp0-effort-limit}
|
||
|
\formdef{cp0-score-limit}{\categorythreadparameter}{cp0-score-limit}
|
||
|
\formdef{cp0-outer-unroll-limit}{\categorythreadparameter}{cp0-outer-unroll-limit}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
These parameters control the operation of \scheme{cp0}, a source
|
||
|
optimization pass that runs after macro expansion and prior
|
||
|
to most other compiler passes.
|
||
|
\scheme{cp0} performs procedure inlining, in which the code of one
|
||
|
procedure is inlined at points where it is called by other procedures,
|
||
|
as well as copy propagation, constant folding, useless code
|
||
|
elimination, and several related optimizations.
|
||
|
The algorithm used by the optimizer is described in detail in the paper
|
||
|
``Fast and effective procedure inlining''~\cite{waddell:sas97}.
|
||
|
|
||
|
When \scheme{cp0} is enabled, the programmer can count on the compiler
|
||
|
to fold constants, eliminate unnecessary \scheme{let} bindings, and
|
||
|
eliminate unnecessary and inaccessible code.
|
||
|
This is particularly useful when writing macros, since the programmer
|
||
|
can usually handle only the general case and let the compiler simplify
|
||
|
the code when possible.
|
||
|
For example, the programmer can define \scheme{case} as follows:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax case
|
||
|
(syntax-rules ()
|
||
|
[(_ e [(k ...) a1 a2 ...] ... [else b1 b2 ...])
|
||
|
(let ([t e])
|
||
|
(cond
|
||
|
[(memv t '(k ...)) a1 a2 ...]
|
||
|
...
|
||
|
[else b1 b2 ...]))]
|
||
|
[(_ e [(k ...) a1 a2 ...] ...)
|
||
|
(let ([t e])
|
||
|
(cond
|
||
|
[(memv t '(k ...)) a1 a2 ...]
|
||
|
...))]))
|
||
|
\endschemedisplay
|
||
|
|
||
|
and count on the introduce \scheme{let} expression to be eliminated
|
||
|
if \scheme{e} turns out to be an unassigned variable, and count on
|
||
|
the entire \scheme{case} expression to be folded if \scheme{e} turns
|
||
|
out to be a constant.
|
||
|
|
||
|
It is possible to see what \scheme{cp0} does with an expression
|
||
|
via the procedure \index{\scheme{expand/optimize}}\scheme{expand/optimize},
|
||
|
which expands its argument and passes the result through \scheme{cp0}, as
|
||
|
illustrated by the following transcript.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (print-gensym #f)
|
||
|
> (expand/optimize
|
||
|
'(lambda (x)
|
||
|
(case x [(a) 1] [(b c) 2] [(d) 3] [else 4])))
|
||
|
(lambda (x)
|
||
|
(if (#2%memv x '(a))
|
||
|
1
|
||
|
(if (#2%memv x '(b c)) 2 (if (#2%memv x '(d)) 3 4))))
|
||
|
> (expand/optimize
|
||
|
'(+ (let ([f (lambda (x)
|
||
|
(case x [(a) 1] [(b c) 2] [(d) 3] [else 4]))])
|
||
|
(f 'b))
|
||
|
15))
|
||
|
17
|
||
|
\endschemedisplay
|
||
|
|
||
|
In the first example, the \scheme{let} expression produced by \scheme{case}
|
||
|
is eliminated, and in the second, the entire expression is optimized down
|
||
|
to the constant \scheme{17}.
|
||
|
Although not shown by \scheme{expand/optimize}, the \scheme{memv} calls
|
||
|
in the output code for the first example will be replaced by calls to the
|
||
|
less expensive \scheme{eq?} by a later pass of the compiler.
|
||
|
Additional examples are given in the description
|
||
|
of \scheme{expand/optimize}.
|
||
|
|
||
|
The value of \scheme{run-cp0} must be a procedure.
|
||
|
Whenever the compiler is invoked on a Scheme form, the value \var{p}
|
||
|
of this parameter is called to determine whether and how
|
||
|
\scheme{cp0} is run.
|
||
|
\var{p} receives two arguments: \var{cp0}, the entry point into
|
||
|
\scheme{cp0}, and \var{x}, the form being compiled.
|
||
|
The default value of \scheme{run-cp0} simply invokes \var{cp0} on
|
||
|
\var{x}, then \var{cp0} again on the result.
|
||
|
The second run is useful in some cases because the first run
|
||
|
may not eliminate bindings for certain variables that appear to be
|
||
|
referenced but are not actually referenced after inlining.
|
||
|
The marginal benefit of the second run is usually minimal, but so is the
|
||
|
cost.
|
||
|
|
||
|
\noindent
|
||
|
Interesting variants include
|
||
|
|
||
|
\schemedisplay
|
||
|
(run-cp0 (lambda (cp0 x) x))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
which bypasses (disables) \scheme{cp0}, and
|
||
|
|
||
|
\schemedisplay
|
||
|
(run-cp0 (lambda (cp0 x) (cp0 x)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
which runs \scheme{cp0} just once.
|
||
|
|
||
|
The value of \scheme{cp0-effort-limit} determines the maximum amount
|
||
|
of effort spent on each inlining attempt.
|
||
|
The time spent optimizing a program is a linear function of this limit and the
|
||
|
number of calls in the program's source, so small values for this parameter
|
||
|
enforce a tighter bound on compile time.
|
||
|
When set to zero, inlining is disabled except when the name of a procedure
|
||
|
is referenced only once.
|
||
|
The value of \scheme{cp0-score-limit} determines the maximum amount of
|
||
|
code produced per inlining attempt.
|
||
|
Small values for this parameter limit the amount of overall code expansion.
|
||
|
These parameters must be set to nonnegative fixnum values.
|
||
|
|
||
|
The parameter \scheme{cp0-outer-unroll-limit}
|
||
|
controls the amount of inlining performed by the optimizer for
|
||
|
recursive procedures.
|
||
|
With the parameter's value set to the default value of \scheme{0}, recursive
|
||
|
procedures are not inlined.
|
||
|
A nonzero value for the outer unroll limit allows calls external to
|
||
|
a recursive procedure to be inlined.
|
||
|
For example, the expression
|
||
|
|
||
|
\schemedisplay
|
||
|
(letrec ([fact (lambda (x) (if (zero? x) 1 (* x (fact (- x 1)))))])
|
||
|
(fact 10))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
would be left unchanged with the outer unroll limit set to zero, but would
|
||
|
be converted into
|
||
|
|
||
|
\schemedisplay
|
||
|
(letrec ([fact (lambda (x) (if (zero? x) 1 (* x (fact (- x 1)))))])
|
||
|
(* 10 (fact 9)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
with the outer unroll limit set to one.
|
||
|
|
||
|
Interesting effects can be had by varying several of these parameters at
|
||
|
once.
|
||
|
For example, setting the
|
||
|
effort and outer unroll limits to large values and the score limit
|
||
|
to \scheme{1} has the effect of inlining even complex recursive procedures
|
||
|
whose values turn out to be constant at compile time without risking
|
||
|
any code expansion.
|
||
|
For example,
|
||
|
|
||
|
\schemedisplay
|
||
|
(letrec ([fact (lambda (x) (if (zero? x) 1 (* x (fact (- x 1)))))])
|
||
|
(fact 10))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
would be reduced to \scheme{3628800}, but
|
||
|
|
||
|
\schemedisplay
|
||
|
(letrec ([fact (lambda (x) (if (zero? x) 1 (* x (fact (- x 1)))))])
|
||
|
(fact z))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
would be left unchanged, although the optimizer may take a while to
|
||
|
reach this decision if the effort and outer unroll limits are large.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{commonization-level}{\categorythreadparameter}{commonization-level}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
After running the main source optimization pass (cp0) for the last time, the
|
||
|
compiler optionally runs a \emph{commonization} pass.
|
||
|
The pass commonizes the code for lambda expressions that have
|
||
|
identical structure by abstracting differences at certain leaves
|
||
|
of the program, namely constants, references to unassigned variables,
|
||
|
and references to primitives.
|
||
|
The parameter \scheme{commonization-level} controls whether commonization
|
||
|
is run and, if so, how aggressive it is.
|
||
|
Its value must be a nonnegative exact integer ranging from 0 through 9.
|
||
|
When the parameter is set to 0, the default, commonization is not run.
|
||
|
Otherwise, higher values result in more commonization.
|
||
|
|
||
|
Commonization can undo some of the effects of cp0's inlining, can
|
||
|
add run-time overhead, and can complicate debugging, particularly
|
||
|
at higher commonization levels, which is why it is disabled by
|
||
|
default.
|
||
|
On the other hand, for macros or other meta programs that can
|
||
|
generate large, mostly similar lambda expressions, enabling
|
||
|
commonization can result in significant savings in object-code size
|
||
|
and even reduce run-time overhead by making more efficient use of
|
||
|
instruction caches.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{undefined-variable-warnings}{\categorythreadparameter}{undefined-variable-warnings}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When \scheme{undefined-variable-warnings} is set to \scheme{#t}, the
|
||
|
compiler issues a warning message whenever it cannot determine that
|
||
|
a variable bound by \scheme{letrec}, \scheme{letrec*}, or an internal
|
||
|
definition will not be referenced before it is defined.
|
||
|
The default value is \scheme{#f}.
|
||
|
|
||
|
Regardless of the setting of this parameter, the compiler inserts code
|
||
|
to check for the error, except at optimize level 3.
|
||
|
The check is fairly inexpensive and does not typically inhibit inlining
|
||
|
or other optimizations.
|
||
|
In code that must be carefully tuned, however, it is sometimes useful
|
||
|
to reorder bindings or make other changes to eliminate the checks.
|
||
|
Enabling undefined-variable warnings can facilitate this process.
|
||
|
|
||
|
The checks are also visible in the output of \scheme{expand/optimize}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:expand-output}\label{desc:expand/optimize-output}
|
||
|
\formdef{expand-output}{\categorythreadparameter}{expand-output}
|
||
|
\formdef{expand/optimize-output}{\categorythreadparameter}{expand/optimize-output}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The parameters \scheme{expand-output} and \scheme{expand/optimize-output}
|
||
|
can be used to request that the compiler and interpreter print
|
||
|
expander and source-optimizer output produced during the compilation or
|
||
|
interpretation process.
|
||
|
Each parameter must be set to either \scheme{#f} (the default) or a
|
||
|
textual output port.
|
||
|
|
||
|
When \scheme{expand-output} is set to a textual output port, the output
|
||
|
of the expander is printed to the port as a side effect of running
|
||
|
\scheme{compile}, \scheme{interpret}, or any of the file compiling
|
||
|
primitives, e.g., \scheme{compile-file} or \scheme{compile-library}.
|
||
|
Similarly, when \scheme{expand/optimize-output} is set to a textual
|
||
|
output port, the output of the source optimizer is printed.
|
||
|
|
||
|
\index{\scheme{expand}}\index{\scheme{expand/optimize}}%
|
||
|
See also \scheme{expand} (page~\pageref{desc:expand}) and
|
||
|
\scheme{expand-optimize} (page~\pageref{desc:expand/optimize}), which
|
||
|
can be used to run the expander or the expander and source optimizer
|
||
|
directly on an individual form.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{pariah}{\categorysyntax}{(pariah \var{expr_1} \var{expr_2} \dots)}
|
||
|
\returns the values of the last subexpression
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
A \scheme{pariah} expression is just like a \scheme{begin} expression
|
||
|
except that it informs the compiler that the code is expected to
|
||
|
be executed infrequently.
|
||
|
The compiler uses this information to optimize code layout, register
|
||
|
assignments, and other aspects of the generated code.
|
||
|
The \scheme{pariah} form can be used in performance-critical code
|
||
|
to mark the branches of a conditional (e.g., \scheme{if}, \scheme{cond},
|
||
|
or \scheme{case}) that are less likely to be executed than the
|
||
|
others.
|
||
|
|
||
|
|
||
|
\section{Profiling\label{SECTMISCPROFILE}}
|
||
|
|
||
|
\index{profiling}\index{block profiling}\index{source profiling}%
|
||
|
{ChezScheme} supports two forms of profiling: source profiling and
|
||
|
block profiling.
|
||
|
With source profiling enabled, the compiler instruments the code
|
||
|
it produces to count the number of times each source-code expression
|
||
|
is executed.
|
||
|
This information can be
|
||
|
displayed in HTML format, or it can be packaged in a list or
|
||
|
source table for arbitrary user-defined processing.
|
||
|
It can also be dumped to a file to be loaded subsequently into the
|
||
|
compiler's database of profile information for use in source-level
|
||
|
optimizations, such as reordering the clauses of a \scheme{case}
|
||
|
or \scheme{exclusive-cond} form.
|
||
|
In connection with coverage-information (covin) files generated by the
|
||
|
compiler when
|
||
|
\index{\scheme{generate-covin-files}}\scheme{generate-covin-files}
|
||
|
is \scheme{#t}, profile information can also be used to gauge coverage
|
||
|
of a source-code base by a set of tests.
|
||
|
|
||
|
The association between source-code expressions and profile counts
|
||
|
is usually established via annotations produced by the reader and
|
||
|
present in the input to the expander (Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
It is also possible to explicitly identify source positions
|
||
|
to be assigned profile counts via \scheme{profile} expressions.
|
||
|
A \scheme{profile} expression has one subform, a source object, and
|
||
|
returns an unspecified value.
|
||
|
Its only effect is to cause the number of times the expression is
|
||
|
executed to be accounted to the source object.
|
||
|
|
||
|
In cases where source positions explicitly identified by \scheme{profile}
|
||
|
forms are the only ones whose execution counts should be tracked,
|
||
|
the parameter \scheme{generate-profile-forms} can be set to \scheme{#f}
|
||
|
to inhibit the expander's implicit generation of \scheme{profile} forms
|
||
|
for all annotated source expressions.
|
||
|
It is also possible to obtain finer control over implicit generation of
|
||
|
\scheme{profile} forms by marking which annotations that should and
|
||
|
should not be used for profiling (Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
|
||
|
With block profiling enabled, the compiler similarly instruments the
|
||
|
code it produces to count the number of times each ``basic block''
|
||
|
in the code it produces is executed.
|
||
|
Basic blocks are the building blocks of the code produced by many
|
||
|
compilers, including {\ChezScheme}'s compiler, and are sequences
|
||
|
of straight-line code entered only at the top and exited only at
|
||
|
the bottom.
|
||
|
Counting the number of times each basic block is executed is
|
||
|
equivalent to counting the number of times each instruction is
|
||
|
executed, but more efficient.
|
||
|
Block-profile information cannot be viewed, but it can be dumped
|
||
|
to a file to be loaded subsequently into the compiler's database of
|
||
|
profile information for use in block- and instruction-level
|
||
|
optimizations.
|
||
|
These optimizations include reordering blocks to push less frequently
|
||
|
used sequences of code out-of-line, so they will not occupy space
|
||
|
in the instruction cache, and giving registers to variables that are
|
||
|
used in more frequently executed instructions.
|
||
|
|
||
|
Source profiling involves at least the following steps:
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item compile the code with source profiling enabled,
|
||
|
\item run the compiled code to generate source-profile information, and
|
||
|
\item dump the profile information.
|
||
|
\end{itemize}
|
||
|
|
||
|
\index{\scheme{compile-profile}}%
|
||
|
Source profiling is enabled by setting the parameter
|
||
|
\scheme{compile-profile} to the symbol \scheme{source}
|
||
|
or to the boolean value \scheme{#t}.
|
||
|
The profile information can be dumped via:
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{profile-dump-html}]\index{\scheme{profile-dump-html}}
|
||
|
in HTML format to allow the programmer to visualize how
|
||
|
often each expression is executed using a color-coding system that
|
||
|
makes it easy to spot ``hot spots,''
|
||
|
\item[\scheme{profile-dump-list}]\index{\scheme{profile-dump-list}}
|
||
|
in a form suitable for user-defined post-processing,
|
||
|
\item[\scheme{profile-dump}]\index{\scheme{profile-dump}}
|
||
|
in a form suitable for off-line processing by one of the methods
|
||
|
above or by some custom means, or
|
||
|
\item[\scheme{profile-dump-data}]\index{\scheme{profile-dump-data}}
|
||
|
in a form suitable for loading into the compiler's database.
|
||
|
\end{description}
|
||
|
|
||
|
If the information is intended to be fed back into the compiler for
|
||
|
optimization, the following additional steps are required, either
|
||
|
in the same or a different Scheme process:
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item load the profile information into the compiler's profile
|
||
|
database, and
|
||
|
\item recompile the code.
|
||
|
\end{itemize}
|
||
|
|
||
|
\index{\scheme{profile-load-data}}%
|
||
|
Profile information dumped by \scheme{profile-dump-data} is loaded
|
||
|
into the compiler's profile database via \scheme{profile-load-data}.
|
||
|
Profiling information is \emph{not} available to the compiler unless
|
||
|
it is explicitly dumped via \scheme{profile-dump-data} and loaded
|
||
|
via \scheme{profile-load-data}.
|
||
|
|
||
|
When block-profile information is to be used for optimization,
|
||
|
the steps are similar:
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item compile the code with block profiling enabled,
|
||
|
\item run the code to generate block-profile information,
|
||
|
\item dump the profile information,
|
||
|
\item load the profile information, and
|
||
|
\item recompile the code.
|
||
|
\end{itemize}
|
||
|
|
||
|
\index{\scheme{profile-dump-data}}%
|
||
|
\index{\scheme{profile-load-data}}%
|
||
|
Block profiling is enabled by setting the parameter
|
||
|
\scheme{compile-profile} to the symbol \scheme{block}
|
||
|
or to the boolean value \scheme{#t}.
|
||
|
The profile information must be dumped via \scheme{profile-dump-data}
|
||
|
and loaded via \scheme{profile-load-data}.
|
||
|
As with source profile information, block profile information can be
|
||
|
loaded in the same or in a different Scheme process as the one that
|
||
|
dumped the information.
|
||
|
|
||
|
For block optimization, the code to be recompiled must be identical.
|
||
|
In general, this means the files involved must not have been modified,
|
||
|
and nothing else can change that indirectly affects the code produced
|
||
|
by the compiler, e.g., settings for compiler parameters such as
|
||
|
\scheme{optimize-level} or the contents of configuration files read
|
||
|
by macros at compile time.
|
||
|
Otherwise, the set of blocks or the instructions within them might
|
||
|
be different, in which case the block profile information will not
|
||
|
line up properly and the compiler will raise an exception.
|
||
|
|
||
|
For the same reason, when both source profiling and block profiling
|
||
|
information is to be used for optimization, the source information
|
||
|
must be gathered first and loaded before both the first and second
|
||
|
compilation runs involved in block profiling.
|
||
|
That is, the following steps must be used:
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item[1] compile the code with source profiling enabled,
|
||
|
\item[2] run the code to generate source-profile information,
|
||
|
\item[2] dump the source-profile information,
|
||
|
\item[3] load the source-profile information,
|
||
|
\item[3] recompile the code with block profiling enabled,
|
||
|
\item[4] run the code to generate block-profile information,
|
||
|
\item[4] dump the block-profile information,
|
||
|
\item[5] load the source- and block-profile information, and
|
||
|
\item[5] recompile the code.
|
||
|
\end{itemize}
|
||
|
|
||
|
The numbers labeling each step indicate both the order of the steps
|
||
|
and those that must be performed in the same Scheme process.
|
||
|
(All of the steps can be performed in the same Scheme process, if
|
||
|
desired.)
|
||
|
|
||
|
Both source and block profiling are disabled when \scheme{compile-profile}
|
||
|
is set to \scheme{#f}, its default value.
|
||
|
|
||
|
The following example highlights the use of source profiling for
|
||
|
identifying hot spots in the code.
|
||
|
Let's assume that the file /tmp/fatfib/fatfib.ss contains the
|
||
|
following source code.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define fat+
|
||
|
(lambda (x y)
|
||
|
(if (zero? y)
|
||
|
x
|
||
|
(fat+ (1+ x) (1- y)))))
|
||
|
|
||
|
(define fatfib
|
||
|
(lambda (x)
|
||
|
(if (< x 2)
|
||
|
1
|
||
|
(fat+ (fatfib (1- x)) (fatfib (1- (1- x)))))))
|
||
|
\endschemedisplay
|
||
|
|
||
|
We can load fatfib.ss with profiling enabled as follows.
|
||
|
|
||
|
\schemedisplay
|
||
|
(parameterize ([compile-profile 'source])
|
||
|
(load "/tmp/fatfib/fatfib.ss"))
|
||
|
\endschemedisplay
|
||
|
|
||
|
We then run the application as usual.
|
||
|
|
||
|
\schemedisplay
|
||
|
(fatfib 20) ;=> 10946
|
||
|
\endschemedisplay
|
||
|
|
||
|
After the run (or multiple runs), we
|
||
|
dump the profile information as a set of html files using
|
||
|
\scheme{profile-dump-html}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(profile-dump-html)
|
||
|
\endschemedisplay
|
||
|
|
||
|
This creates a file named profile.html containing a summary of the profile
|
||
|
information gathered during the run.
|
||
|
If we view this file in a browser, we should see something like the
|
||
|
following.
|
||
|
|
||
|
\iflatex
|
||
|
\begin{center}
|
||
|
\includegraphics[width=.9\textwidth]{canned/profilehtml}
|
||
|
\end{center}
|
||
|
\fi
|
||
|
\ifhtml
|
||
|
\raw{\raw{<img src="canned/profilehtml.png" alt="profile.html listing">}}
|
||
|
\fi
|
||
|
|
||
|
The most frequently executed code is highlighted in colors closer to
|
||
|
red in the visible spectrum, while
|
||
|
the least frequently executed code is highlighted in colors closer to
|
||
|
violet.
|
||
|
Each of the entries in the lists of files and hot spots are links into
|
||
|
additional generated files, one per source file (provided
|
||
|
\scheme{profile-dump-html} was able to locate an unmodified copy of
|
||
|
the source file).
|
||
|
In this case, there is only one, fatfib.ss.html.
|
||
|
If we move to that file, we should see something like this:
|
||
|
|
||
|
\iflatex
|
||
|
\begin{center}
|
||
|
\includegraphics[width=.9\textwidth]{canned/fatfibhtml}
|
||
|
\end{center}
|
||
|
\fi
|
||
|
\ifhtml
|
||
|
\raw{\raw{<img src="canned/fatfibhtml.png" alt="fatfib.html listing">}}
|
||
|
\fi
|
||
|
|
||
|
As in the summary, the code is color-coded according to frequency
|
||
|
of execution.
|
||
|
Hovering over a color-coded section of code should cause a pop-up
|
||
|
box to appear with the starting position and count of the source
|
||
|
expression.
|
||
|
If a portion of source code is not color-coded or is identified
|
||
|
via the starting position as having inherited its color from some
|
||
|
enclosing expression, it may have been recognized as dead code by
|
||
|
the compiler or garbage collector and discarded, or the expander
|
||
|
might not have been able to track it through the macro-expansion
|
||
|
process.
|
||
|
|
||
|
\scheme{profile-dump} and \scheme{profile-dump-list} may be used to
|
||
|
generate a list of profile entries, which may then be analyzed manually
|
||
|
or via a custom profile-viewing application.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{compile-profile}{\categorythreadparameter}{compile-profile}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When this parameter is set to the symbol \scheme{source} or the
|
||
|
boolean value \scheme{#t}, the compiler instruments the code it
|
||
|
generates with instructions that count the number of times each
|
||
|
section of source code is executed.
|
||
|
When set to the symbol \scheme{block}, the compiler similarly
|
||
|
instruments the code it generates with instructions that count the
|
||
|
number of times each block of code is executed.
|
||
|
When set to \scheme{#f} (the default), the compiler does not insert
|
||
|
these instructions.
|
||
|
|
||
|
The general description of profiling above describes how the source
|
||
|
and block profile information can be viewed or used for optimization.
|
||
|
|
||
|
The code generated when \scheme{compile-profile} is non-false is
|
||
|
larger and less efficient, so this parameter should be set only
|
||
|
when profile information is needed.
|
||
|
|
||
|
The profile counters for code compiled when profile instrumentation
|
||
|
is enabled are retained indefinitely, even if the code with which
|
||
|
they are associated is reclaimed by the garbage collector.
|
||
|
This results in more complete and accurate profile data but can lead
|
||
|
to space leaks in programs that dynamically generate or load code.
|
||
|
Such programs can avoid the potential space leak by releasing the
|
||
|
counters explicitly via the procedure
|
||
|
\index{\scheme{profile-release-counters}}\scheme{profile-release-counters}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{generate-covin-files}{\categorythreadparameter}{generate-covin-files}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When this parameter is set to \scheme{#t}, the compiler generates
|
||
|
``coverage-information'' (covin) files that can be used in connection with
|
||
|
profile information to measure coverage of a source-code base by a
|
||
|
set of tests.
|
||
|
One covin file is created for each object file, with the object-file
|
||
|
extension replaced by the extension \scheme{.covin}.
|
||
|
Each covin file contains the printed representation of a source table
|
||
|
(Section~\ref{SECTSYNTAXSOURCETABLES}), compressed using the compression
|
||
|
format and level specified by \scheme{compress-format} and
|
||
|
\scheme{compress-level}.
|
||
|
This information can be read via
|
||
|
\index{\scheme{get-source-table!}}\scheme{get-source-table!} and used
|
||
|
as a universe of source expressions to identify source expressions
|
||
|
that are not evaluated during the running of a set of tests.
|
||
|
|
||
|
|
||
|
\entryheader
|
||
|
\formdef{profile}{\categorysyntax}{(profile \var{source-object})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
A \scheme{profile} form has the effect of accounting to the source
|
||
|
position identified by \var{source-object} the number of times the
|
||
|
\scheme{profile} form is executed.
|
||
|
Profile forms are generated implicitly by the expander for source
|
||
|
expressions in annotated input, e.g., input read by the compiler or
|
||
|
interpreter from a Scheme source file, so this form is typically
|
||
|
useful only when unannotated source code is produced by the front
|
||
|
end for some language that targets Scheme.
|
||
|
|
||
|
\entryheader
|
||
|
\formdef{generate-profile-forms}{\categorythreadparameter}{(generate-profile-forms)}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
When this parameter is set to \scheme{#t}, the default, the expander
|
||
|
implicitly introduces \scheme{profile} forms for each annotated input
|
||
|
expression, unless the annotation has not been marked for use in
|
||
|
profiling (Section~\ref{SECTSYNTAXANNOTATIONS}).
|
||
|
It can be set to \scheme{#f} to inhibit the expander's implicit
|
||
|
generation of \scheme{profile} forms, typically when explicit
|
||
|
\scheme{profile} forms are already present for all source positions
|
||
|
that should be profiled.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-clear}{\categoryprocedure}{(profile-clear)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Calling this procedure causes profile information to be cleared, i.e.,
|
||
|
the counts associated with each section of code are set to zero.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-release-counters}{\categoryprocedure}{(profile-release-counters)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Calling this procedure causes profile information associated with reclaimed
|
||
|
code objects to be dropped.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-dump}{\categoryprocedure}{(profile-dump)}
|
||
|
\returns a list of pairs of source-object and count
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure produces a dump of all
|
||
|
profile information gathered since startup or the last call to
|
||
|
\scheme{profile-clear}.
|
||
|
It returns a list of pairs, where the car of each pair
|
||
|
is a source object (Section~\ref{SECTSYNTAXANNOTATIONS}) and the
|
||
|
cdr is an exact nonnegative integer count.
|
||
|
|
||
|
The list might contain more than one entry per source object due
|
||
|
to macro expansion and procedure inlining, and it might contain
|
||
|
more than one (non-eq) source object per file and source position
|
||
|
due to separate compilation.
|
||
|
In such cases, the counts are not overlapping and can be summed
|
||
|
together to obtain the full count.
|
||
|
|
||
|
The advantage of \scheme{profile-dump} over \scheme{profile-dump-list}
|
||
|
is that \scheme{profile-dump} performs only minimal processing and
|
||
|
preserves complete source objects, including their embedded source-file
|
||
|
descriptors.
|
||
|
It might be used, for example, to dump profile information to a
|
||
|
fasl file on one machine for subsequent processing on another.
|
||
|
|
||
|
\index{\scheme{with-profile-tracker}}\scheme{with-profile-tracker}
|
||
|
can be used to obtain the same set of counts as a source table.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{with-profile-tracker}{\categoryprocedure}{(with-profile-tracker \var{thunk})}
|
||
|
\formdef{with-profile-tracker}{\categoryprocedure}{(with-profile-tracker \var{preserve-existing?} \var{thunk})}
|
||
|
\returns a source table and the values returned by \var{thunk}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{thunk} must be a procedure and should accept zero arguments.
|
||
|
It may return any number of values.
|
||
|
|
||
|
\scheme{with-profile-tracker} invokes \var{thunk} without arguments.
|
||
|
If \var{thunk} returns $n$ values \scheme{\var{x_1}, \var{x_2}, \dots, \var{x_n}}, \scheme{with-profile-tracker}
|
||
|
returns $n+1$ values \scheme{\var{st}, \var{x_1}, \var{x_2}, \dots, \var{x_n}}, where \var{st} is a
|
||
|
source table associating source objects with profile counts.
|
||
|
If \var{preserve-existing?} is absent or \scheme{#f}, each count
|
||
|
represents the number of times the source expression represented
|
||
|
by the associated source object is evaluated during the invocation
|
||
|
of \var{thunk}.
|
||
|
Otherwise, each count represents the number of times the source
|
||
|
expression represented by the associated source object is evaluated
|
||
|
before or during the invocation of \var{thunk}.
|
||
|
|
||
|
Profile data otherwise cleared by a call to
|
||
|
\index{\scheme{profile-clear}}\scheme{profile-clear} or
|
||
|
\index{\scheme{profile-release-counters}}\scheme{profile-release-counters}
|
||
|
during the invocation of \var{thunk} is included in the
|
||
|
resulting table.
|
||
|
That is, invoking these procedures while \var{thunk} is running has
|
||
|
no effect on the resulting counts.
|
||
|
On the other hand, profile data cleared before \scheme{with-profile-tracker}
|
||
|
is invoked is not included in the resulting table.
|
||
|
|
||
|
The idiom \scheme{(with-profile-tracker #t values)} can be used to obtain
|
||
|
the current set of profile counts as a source table.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{source-table-dump}{\categoryprocedure}{(source-table-dump \var{source-table})}
|
||
|
\returns a list of pairs of source objects and their associated values in \var{source-table}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure can be used to convert a source-table produced by
|
||
|
\index{\scheme{with-profile-tracker}}\scheme{with-profile-tracker} or some other mechanism into the form returned
|
||
|
by \index{\scheme{profile-dump}}\scheme{profile-dump} for use as an argument to
|
||
|
\index{\scheme{profile-dump-html}}\scheme{profile-dump-html},
|
||
|
\index{\scheme{profile-dump-list}}\scheme{profile-dump-list},
|
||
|
or
|
||
|
\index{\scheme{profile-dump-data}}\scheme{profile-dump-data}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-dump-html}{\categoryprocedure}{(profile-dump-html)}
|
||
|
\formdef{profile-dump-html}{\categoryprocedure}{(profile-dump-html \var{prefix})}
|
||
|
\formdef{profile-dump-html}{\categoryprocedure}{(profile-dump-html \var{prefix} \var{dump})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure produces one or more HTML files, including
|
||
|
profile.html, which contains color-coded summary information,
|
||
|
and one file \var{source}.html for each source
|
||
|
file \var{source} containing a color-coded copy of the
|
||
|
source code, as described in the lead-in to this section.
|
||
|
If \var{prefix} is specified, it must be a string and is prepended
|
||
|
to the names of the generated HTML files.
|
||
|
For example, if \var{prefix} is \scheme{"/tmp/"}, the generated
|
||
|
files are placed in the directory /tmp.
|
||
|
The raw profile information is obtained from \var{dump}, which
|
||
|
defaults to the value returned by \scheme{profile-dump}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-palette}{\categorythreadparameter}{(profile-palette)}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This value of this parameter must be a nonempty vector of at least
|
||
|
three pairs.
|
||
|
The car of each pair is a background color and the cdr is a foreground
|
||
|
(text) color.
|
||
|
Each color must be a string, and each string should contain an HTML
|
||
|
cascading style sheet (CSS) color specifier.
|
||
|
The first pair is used for unprofiled code, and the second is used
|
||
|
for unexecuted profiled code.
|
||
|
The third is used for code that is executed least frequently, the fourth
|
||
|
for code executed next-least frequently, and so on, with the last
|
||
|
being used for code that is executed most frequently.
|
||
|
Programmers may wish to supply their own palette to enhance visibility
|
||
|
or to change the number of colors used.
|
||
|
|
||
|
By default, a black background is used for unprofiled code, and a gray
|
||
|
background is used for unexecuted profiled code.
|
||
|
Background colors ranging from purple to red are used for executed
|
||
|
profiled code, depending on frequency of execution, with red for the most
|
||
|
frequently executed code.
|
||
|
|
||
|
\schemedisplay
|
||
|
(profile-palette) ;=>
|
||
|
#(("#111111" . "white") ("#607D8B" . "white")
|
||
|
("#9C27B0" . "black") ("#673AB7" . "white")
|
||
|
("#3F51B5" . "white") ("#2196F3" . "black")
|
||
|
("#00BCD4" . "black") ("#4CAF50" . "black")
|
||
|
("#CDDC39" . "black") ("#FFEB3B" . "black")
|
||
|
("#FFC107" . "black") ("#FF9800" . "black")
|
||
|
("#F44336" . "white"))
|
||
|
(profile-palette
|
||
|
; set palette with rainbow colors and black text
|
||
|
; for all but unprofiled or unexecuted code
|
||
|
'#(("#000000" . "white") ; black
|
||
|
("#666666" . "white") ; gray
|
||
|
("#8B00FF" . "black") ; violet
|
||
|
("#6600FF" . "black") ; indigo
|
||
|
("#0000FF" . "black") ; blue
|
||
|
("#00FF00" . "black") ; green
|
||
|
("#FFFF00" . "black") ; yellow
|
||
|
("#FF7F00" . "black") ; orange
|
||
|
("#FF0000" . "black"))) ; red
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-line-number-color}{\categorythreadparameter}{(profile-line-number-color)}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This value of this parameter must be a string or \scheme{#f}.
|
||
|
If it is a string, the string should contain an HTML cascading style sheet (CSS)
|
||
|
color specifier.
|
||
|
If the parameter is set to a string, \scheme{profile-dump-html} includes line numbers
|
||
|
in its html rendering of each source file, using the specified color.
|
||
|
If the parameter is set to \scheme{#f}, no line numbers are included.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-dump-list}{\categoryprocedure}{(profile-dump-list)}
|
||
|
\formdef{profile-dump-list}{\categoryprocedure}{(profile-dump-list \var{warn?})}
|
||
|
\formdef{profile-dump-list}{\categoryprocedure}{(profile-dump-list \var{warn?} \var{dump})}
|
||
|
\returns a list of profile entries (see below)
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure produces a dump of all
|
||
|
profile information present in \var{dump}, which defaults to
|
||
|
the value returned by \scheme{profile-dump}.
|
||
|
It returns a list of entries, each of which is itself a list containing the
|
||
|
following elements identifying one block of code and how many times it
|
||
|
has been executed.
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item execution count
|
||
|
\item pathname
|
||
|
\item beginning file position in characters (inclusive)
|
||
|
\item ending file position in characters (exclusive)
|
||
|
\item line number of beginning file position
|
||
|
\item character position of beginning file position
|
||
|
\end{itemize}
|
||
|
|
||
|
\scheme{profile-dump-list} may be unable to locate an unmodified copy
|
||
|
of the file in the current source directories
|
||
|
or at the absolute address, if an absolute address was used when
|
||
|
the file was compiled or loaded.
|
||
|
If this happens, the line number and character position of the beginning
|
||
|
file position are \scheme{#f} and the pathname is the pathname originally
|
||
|
used.
|
||
|
A warning is also issued (an exception with condition type
|
||
|
\scheme{&warning} is raised) unless the \scheme{warn?} argument is provided
|
||
|
and is false.
|
||
|
|
||
|
Otherwise, the pathname is the path to an unmodified copy of the source
|
||
|
and the line and character positions are set to exact nonnegative integers.
|
||
|
|
||
|
In either case, the execution count, beginning file position, and ending
|
||
|
file position are all exact nonnegative integers, and the pathname is a string.
|
||
|
|
||
|
For source positions in files that cannot be found, the list might
|
||
|
contain more than one entry per position due to macro expansion,
|
||
|
procedure inlining, and separate compilation.
|
||
|
In such cases, the counts are not overlapping and can be summed
|
||
|
together to obtain the full count.
|
||
|
|
||
|
The information returned by \scheme{profile-dump-list} can be used to
|
||
|
implement a custom viewer or used as input for offline analysis of
|
||
|
profile information.
|
||
|
|
||
|
The advantage of \scheme{profile-dump-list} over \scheme{profile-dump}
|
||
|
is that it attempts to determine the line number and character
|
||
|
position for each source point and, if successful, aggregates
|
||
|
multiple counts for the source point into a single entry.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-dump-data}{\categoryprocedure}{(profile-dump-data \var{path})}
|
||
|
\formdef{profile-dump-data}{\categoryprocedure}{(profile-dump-data \var{path} \var{dump})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{path} must be a string.
|
||
|
|
||
|
This procedure writes, in a machine-readable form consumable by
|
||
|
\scheme{profile-load-data}, profile counts represented by \var{dump}
|
||
|
to the file named by \var{path}, replacing the file if it already exists.
|
||
|
\var{dump} defaults to the value returned by \scheme{profile-dump}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-load-data}{\categoryprocedure}{(profile-load-data \var{path} \dots)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
Each \var{path} must be a string.
|
||
|
|
||
|
This procedure reads profile information from the files named by
|
||
|
\scheme{\var{path} \dots} and stores it in the compiler's internal
|
||
|
database of profile information.
|
||
|
The contents of the files must have been created originally by
|
||
|
\scheme{profile-dump-data} using the same version of {\ChezScheme}.
|
||
|
|
||
|
The database stores a weight for each source expression or block
|
||
|
rather than the actual count.
|
||
|
When a single file is loaded into the database, the weight is the
|
||
|
proportion of the actual count over the maximum count for all
|
||
|
expressions or blocks represented in the file.
|
||
|
When more than one file is loaded, either by one or multiple calls
|
||
|
to \scheme{profile-load-data}, the weights are averaged.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-query-weight}{\categoryprocedure}{(profile-query-weight \var{obj})}
|
||
|
\returns \var{obj}'s profile weight, or \scheme{#f} if \var{obj} is not in the database
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The compiler's profile database maps source objects
|
||
|
(Section~\ref{SECTSYNTAXANNOTATIONS}) to weights.
|
||
|
If \var{obj} is a source object, the \scheme{profile-query-weight} returns
|
||
|
the weight associated with the source object or \scheme{#f} if the database
|
||
|
does not have a weight recorded for the source object.
|
||
|
\var{obj} can also be an annotation or syntax object, in which case
|
||
|
\scheme{profile-query-weight} first extracts the source object, if any,
|
||
|
using \scheme{syntax->annotation} and \scheme{annotation-source},
|
||
|
returning \scheme{#f} if no source-object is found.
|
||
|
|
||
|
A weight is a flonum in the range 0.0 to 1.0, inclusive, and denotes the
|
||
|
ratio of the actual count to the maximum count as described in the
|
||
|
description of \scheme{profile-load-data}.
|
||
|
|
||
|
\scheme{profile-query-weight} can be used by a macro to determine
|
||
|
the relative frequency with which its subexpressions were executed
|
||
|
in the run or runs that generated the information in the database.
|
||
|
This information can be used to guide the generation of code that
|
||
|
is likely to be more efficient.
|
||
|
For example, the \scheme{case} macro uses profile information, when
|
||
|
available, to order the clauses so that those whose keys matched
|
||
|
more frequently are tested before those whose keys matched less
|
||
|
frequently.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{profile-clear-database}{\categoryprocedure}{(profile-clear-database)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure clears the compiler's profile database.
|
||
|
It has no impact on the counts associated with individual sections
|
||
|
of instrumented code; \scheme{profile-clear} can be used to reset
|
||
|
those counts.
|
||
|
|
||
|
\section{Waiter Customization\label{SECTMISCWAITERS}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{new-cafe}{\categoryprocedure}{(new-cafe)}
|
||
|
\formdef{new-cafe}{\categoryprocedure}{(new-cafe \var{eval-proc})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
\index{waiter}\index{cafe@caf\'e}{\ChezScheme} interacts with the user
|
||
|
through a \emph{waiter}, or read-eval-print loop (REPL).
|
||
|
The waiter operates within a context called a \emph{caf\'e}.
|
||
|
When the system starts up, the user is placed in a caf\'e and
|
||
|
given a waiter.
|
||
|
\scheme{new-cafe} opens a new Scheme caf\'e, stacked on top of the old one.
|
||
|
In addition to starting the waiter, \scheme{new-cafe} sets up the caf\'e's
|
||
|
reset and exit handlers (see \scheme{reset-handler} and \scheme{exit-handler}).
|
||
|
Exiting a caf\'e resumes the continuation of the call
|
||
|
to \scheme{new-cafe} that created the caf\'e.
|
||
|
Exiting from the initial caf\'e leaves Scheme altogether.
|
||
|
A caf\'e may be exited from either by an explicit call to \scheme{exit} or
|
||
|
by receipt of end-of-file (``control-D'' on Unix systems) in response
|
||
|
to the waiter's prompt.
|
||
|
In the former case, any values passed to \scheme{exit} are returned from
|
||
|
\scheme{new-cafe}.
|
||
|
|
||
|
If the optional \var{eval-proc} argument is specified, \var{eval-proc}
|
||
|
is used to evaluate forms entered from the console.
|
||
|
Otherwise, the value of the parameter \scheme{current-eval} is used.
|
||
|
\var{eval-proc} must accept one argument, the expression to evaluate.
|
||
|
|
||
|
Interesting values for \var{eval-proc} include \index{\scheme{expand}}\scheme{expand},
|
||
|
which causes the macro expanded value of each expression entered to
|
||
|
be printed and \scheme{(lambda (x) x)}, which simply causes each expression
|
||
|
entered to be printed.
|
||
|
An arbitrary procedure of one argument may be used to facilitate
|
||
|
testing of a program on a series of input values.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (new-cafe (lambda (x) x))
|
||
|
>> 3
|
||
|
3
|
||
|
>> (a . (b . (c . ())))
|
||
|
(a b c)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\schemedisplay
|
||
|
(define sum
|
||
|
(lambda (ls)
|
||
|
(if (null? ls)
|
||
|
0
|
||
|
(+ (car ls) (sum (cdr ls))))))
|
||
|
> (new-cafe sum)
|
||
|
>> (1 2 3)
|
||
|
6
|
||
|
\endschemedisplay
|
||
|
|
||
|
The default waiter reader (see \scheme{waiter-prompt-and-read}) displays
|
||
|
the current waiter prompt (see \scheme{waiter-prompt-string})
|
||
|
to the current value of \index{\scheme{console-output-port}}\scheme{console-output-port} and
|
||
|
reads
|
||
|
from the current value of \index{\scheme{console-input-port}}\scheme{console-input-port}.
|
||
|
The default waiter printer (see \scheme{waiter-write}) sends output
|
||
|
to the current value of \index{\scheme{console-output-port}}\scheme{console-output-port}.
|
||
|
These parameters, along with \scheme{current-eval},
|
||
|
can be modified to change the behavior of the waiter.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{waiter-prompt-string}{\categorythreadparameter}{waiter-prompt-string}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of \scheme{waiter-prompt-string} must be a string.
|
||
|
It is used by the default waiter prompter (see the parameter
|
||
|
\scheme{waiter-prompt-and-read}) to print a prompt.
|
||
|
Nested caf\'es
|
||
|
are marked by repeating the prompt string once for each nesting level.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (waiter-prompt-string)
|
||
|
">"
|
||
|
> (waiter-prompt-string "%")
|
||
|
% (waiter-prompt-string)
|
||
|
"%"
|
||
|
% (new-cafe)
|
||
|
%% (waiter-prompt-string)
|
||
|
"%"
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{waiter-prompt-and-read}{\categorythreadparameter}{waiter-prompt-and-read}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{waiter-prompt-and-read} must be set to a procedure.
|
||
|
It is used by the waiter to
|
||
|
print a prompt and read an expression.
|
||
|
The value of \scheme{waiter-prompt-and-read} is called by the waiter with a
|
||
|
positive integer that indicates the caf\'e nesting level.
|
||
|
It should return an expression to be evaluated by the current
|
||
|
evaluator (see \scheme{new-cafe} and \scheme{current-eval}).
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{default-prompt-and-read}{\categoryprocedure}{(default-prompt-and-read \var{level})}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{level} must be a positive integer indicating the cafe\'e nesting
|
||
|
level as described above.
|
||
|
|
||
|
This procedure is the default value of the \scheme{waiter-prompt-and-read}
|
||
|
parameter whenever the expression editor
|
||
|
(Section~\ref{SECTUSEEXPEDITOR}, Chapter~\ref{CHPTEXPEDITOR}) is
|
||
|
\emph{not} enabled.
|
||
|
It might be defined as follows.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define default-prompt-and-read
|
||
|
(lambda (n)
|
||
|
(unless (and (integer? n) (>= n 0))
|
||
|
(assertion-violationf 'default-prompt-and-read
|
||
|
"~s is not a nonnegative integer"
|
||
|
n))
|
||
|
(let ([prompt (waiter-prompt-string)])
|
||
|
(unless (string=? prompt "")
|
||
|
(do ([n n (- n 1)])
|
||
|
((= n 0)
|
||
|
(write-char #\space (console-output-port))
|
||
|
(flush-output-port (console-output-port)))
|
||
|
(display prompt (console-output-port))))
|
||
|
(let ([x (read (console-input-port))])
|
||
|
(when (and (eof-object? x) (not (string=? prompt "")))
|
||
|
(newline (console-output-port))
|
||
|
(flush-output-port (console-output-port)))
|
||
|
x))))
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{waiter-write}{\categorythreadparameter}{waiter-write}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of \scheme{waiter-write} must be a procedure.
|
||
|
The waiter uses the value of \scheme{waiter-write} to print the results
|
||
|
of each expression read and evaluated by the waiter.
|
||
|
The following example installs a procedure equivalent to the default
|
||
|
\scheme{waiter-write}:
|
||
|
|
||
|
\schemedisplay
|
||
|
(waiter-write
|
||
|
(lambda (x)
|
||
|
(unless (eq? x (void))
|
||
|
(pretty-print x (console-output-port)))
|
||
|
(flush-output-port (console-output-port))))
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{reset}{\categoryprocedure}{(reset)}
|
||
|
\returns does not return
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{reset} invokes the current reset handler (see \scheme{reset-handler})
|
||
|
without arguments.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{reset-handler}{\categorythreadparameter}{reset-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter must be a procedure and should accept zero
|
||
|
arguments.
|
||
|
The current reset handler is called by \scheme{reset}.
|
||
|
The default reset handler resets to the current caf\'e.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{exit}{\categoryprocedure}{(exit \var{obj} \dots)}
|
||
|
\returns does not return
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{exit} invokes the current exit handler (see
|
||
|
\scheme{exit-handler}), passing along its arguments, if any.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{exit-handler}{\categorythreadparameter}{exit-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter must be a procedure and should accept any
|
||
|
number of arguments.
|
||
|
The current exit handler is called by \scheme{exit}.
|
||
|
|
||
|
The default exit handler exits from the current caf\'e,
|
||
|
returning its arguments as the values of the call to
|
||
|
\scheme{new-cafe} that created the current caf\'e.
|
||
|
If the current caf\'e is the original caf\'e, or if \scheme{exit}
|
||
|
is called from a script, \scheme{exit} exits from Scheme.
|
||
|
In this case, the exit code for the Scheme process is 0 if
|
||
|
no arguments were supplied or if the first argument is void,
|
||
|
the value of the first argument cast to a C int if
|
||
|
it is an exact integer of the host machine's bit width, and 1 otherwise.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{abort}{\categoryprocedure}{(abort)}
|
||
|
\formdef{abort}{\categoryprocedure}{(abort \var{obj})}
|
||
|
\returns does not return
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{abort} invokes the current abort handler (see \scheme{abort-handler}),
|
||
|
passing along its argument, if any.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{abort-handler}{\categorythreadparameter}{abort-handler}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter must be a procedure and should accept either
|
||
|
zero arguments or one argument.
|
||
|
The current abort handler is called by \scheme{abort}.
|
||
|
|
||
|
The default abort handler exits the Scheme process.
|
||
|
The exit code for the Scheme process is -1 if no arguments were supplied,
|
||
|
0 if the first argument is void, the value of the first argument if it is
|
||
|
a 32-bit exact integer, and -1 otherwise.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{scheme-start}{\categoryglobalparameter}{scheme-start}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of \scheme{scheme-start} is a procedure that determines the
|
||
|
system's action upon start-up.
|
||
|
The procedure receives zero or more arguments, which are strings
|
||
|
representing the file names (or command-line arguments not recognized
|
||
|
by the Scheme executable) after given on the command line.
|
||
|
The default value first loads the files named by the arguments, then
|
||
|
starts up the initial caf\'e:
|
||
|
|
||
|
\schemedisplay
|
||
|
(lambda fns
|
||
|
(for-each load fns)
|
||
|
(new-cafe))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
\scheme{scheme-start} may be altered to start up an application or to
|
||
|
perform customization prior to normal system start-up.
|
||
|
|
||
|
To have any effect, this parameter must be set within a boot file.
|
||
|
(See Chapter~\ref{CHPTUSE}.)
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{scheme-script}{\categoryglobalparameter}{scheme-script}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\index{\scheme{--script} command-line option}%
|
||
|
\index{\scheme{command-line}}%
|
||
|
\index{\scheme{command-line-arguments}}%
|
||
|
The value of \scheme{scheme-script} is a procedure that determines the
|
||
|
system's action upon start-up,
|
||
|
when the \scheme{--script} option is used.
|
||
|
The procedure receives one or more arguments.
|
||
|
The first is a string identifying the script filename and the remainder
|
||
|
are strings representing the remaining file names (or command-line
|
||
|
arguments not recognized by the Scheme executable) given on the command
|
||
|
line.
|
||
|
The default value of this parameter is a procedure that sets the
|
||
|
\scheme{command-line} and \scheme{command-line-arguments} parameters,
|
||
|
loads the script using \scheme{load}, and returns void, which is
|
||
|
translated into a 0 exit status for the script process.
|
||
|
|
||
|
\schemedisplay
|
||
|
(lambda (fn . fns)
|
||
|
(command-line (cons fn fns))
|
||
|
(command-line-arguments fns)
|
||
|
(load fn))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
\scheme{scheme-script} may be altered to start up an application or to
|
||
|
perform customization prior to normal system start-up.
|
||
|
|
||
|
To have any effect, this parameter must be set within a boot file.
|
||
|
(See Chapter~\ref{CHPTUSE}.)
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{scheme-program}{\categoryglobalparameter}{scheme-program}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\index{\scheme{--program} command-line option}%
|
||
|
\index{\scheme{command-line}}%
|
||
|
\index{\scheme{command-line-arguments}}%
|
||
|
The value of \scheme{scheme-program} is a procedure that determines the
|
||
|
system's action upon start-up
|
||
|
when the \scheme{--program} (RNRS top-level program) option is used.
|
||
|
The procedure receives one or more arguments.
|
||
|
The first is a string identifying the program filename and the remainder
|
||
|
are strings representing the remaining file names (or command-line
|
||
|
arguments not recognized by the Scheme executable) given on the command
|
||
|
line.
|
||
|
The default value of this parameter is a procedure that sets the
|
||
|
\scheme{command-line} and \scheme{command-line-arguments} parameters,
|
||
|
loads the program using \scheme{load-program}, and returns void, which is
|
||
|
translated into a 0 exit status for the script process.
|
||
|
|
||
|
\schemedisplay
|
||
|
(lambda (fn . fns)
|
||
|
(command-line (cons fn fns))
|
||
|
(command-line-arguments fns)
|
||
|
(load-program fn))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\noindent
|
||
|
\scheme{scheme-program} may be altered to start up an application or to
|
||
|
perform customization prior to normal system start-up.
|
||
|
|
||
|
To have any effect, this parameter must be set within a boot file.
|
||
|
(See Chapter~\ref{CHPTUSE}.)
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{command-line}{\categoryglobalparameter}{command-line}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\index{\scheme{--script} command-line option}%
|
||
|
This parameter is set by the default values of \scheme{scheme-script}
|
||
|
and \scheme{scheme-program}
|
||
|
to a list representing the command line, with the script name followed
|
||
|
by the command-line arguments, when the \scheme{--script} or
|
||
|
\scheme{--program} option is used on system startup.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{command-line-arguments}{\categoryglobalparameter}{command-line-arguments}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\index{\scheme{--script} command-line option}%
|
||
|
This parameter is set by the default values of \scheme{scheme-script}
|
||
|
and \scheme{scheme-program}
|
||
|
to a list of the command-line arguments when the \scheme{--script}
|
||
|
or \scheme{--program} option is used on system startup.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{suppress-greeting}{\categoryglobalparameter}{suppress-greeting}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of \scheme{suppress-greeting} is a boolean value that determines
|
||
|
whether {\ChezScheme} prints an identifying banner and copyright notice.
|
||
|
The parameter defaults to \scheme{#f} but may be set to \scheme{#t} for
|
||
|
use in batch processing applications where the banner would be disruptive.
|
||
|
|
||
|
To have any effect, this parameter must be set within a boot file.
|
||
|
(See Chapter~\ref{CHPTUSE}.)
|
||
|
|
||
|
|
||
|
\section{Transcript Files\label{SECTMISCTRANSCRIPTS}}
|
||
|
|
||
|
A \index{transcript}transcript file is a record of an interactive session.
|
||
|
It is also useful as a ``quick-and-dirty'' alternative to opening an
|
||
|
output file and using explicit output operations.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader\label{desc:transcript-on}
|
||
|
\formdef{transcript-on}{\categoryprocedure}{(transcript-on \var{path})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
|
||
|
\scheme{transcript-on} opens the file named by \var{path} for output,
|
||
|
and it copies to this file all input from the current input port and
|
||
|
all output to the current output port.
|
||
|
An exception is raised with condition-type \scheme{i/o-filename} if the
|
||
|
file cannot be opened for output.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{transcript-off}{\categoryprocedure}{(transcript-off)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{transcript-off} ends transcription and closes the transcript file.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{transcript-cafe}{\categoryprocedure}{(transcript-cafe \var{path})}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{path} must be a string.
|
||
|
\scheme{transcript-cafe} opens a transcript file as with
|
||
|
\scheme{transcript-on} and
|
||
|
enters a new caf\'e; exiting
|
||
|
from this caf\'e (see \scheme{exit}) also ends transcription and closes the
|
||
|
transcript file.
|
||
|
Invoking \scheme{transcript-off} while in a transcript caf\'e ends transcription
|
||
|
and closes the transcript file but does not cause an exit from the
|
||
|
caf\'e.
|
||
|
|
||
|
|
||
|
\section{Times and Dates\label{SECTSYSTEMTIMESNDATES}}
|
||
|
|
||
|
This section documents procedures for handling times and dates. Most of
|
||
|
the procedures described here are proposed in
|
||
|
\hyperlink{http://srfi.schemers.org/srfi-19/srfi-19.html}{SRFI~19}:
|
||
|
Time Data Types and Procedures, by Will Fitzgerald.
|
||
|
|
||
|
Times are represented by time objects.
|
||
|
Time objects record the nanosecond and second of a particular time
|
||
|
or duration, along with a \emph{time type} that identifies the nature
|
||
|
of the time object.
|
||
|
The time type is one of the following symbols:
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{time-utc}:]
|
||
|
The time elapsed since the ``epoch:'' 00:00:00 UTC, January 1, 1970,
|
||
|
subject to adjustment, e.g., to correct for leap seconds.
|
||
|
|
||
|
\item[\scheme{time-monotonic}:]
|
||
|
The time elapsed since some arbitrary point in the past, ideally
|
||
|
not subject to adjustment.
|
||
|
|
||
|
\item[\scheme{time-duration}:]
|
||
|
The time elapsed between two times.
|
||
|
When used as an argument to \scheme{current-time}, it behaves like
|
||
|
\scheme{time-monotonic}, but may also used to represent the result
|
||
|
of subtracting two time objects.
|
||
|
|
||
|
\item[\scheme{time-process}:]
|
||
|
The amount of CPU time used by the current process.
|
||
|
|
||
|
\item[\scheme{time-thread}:]
|
||
|
The amount of CPU time used by the current thread.
|
||
|
It is the same as \scheme{time-process} if
|
||
|
not running threaded or if the system does not allow individual
|
||
|
thread times to be determined.
|
||
|
|
||
|
\item[\scheme{time-collector-cpu}:]
|
||
|
The portion of the current process's CPU time consumed by the
|
||
|
garbage collector.
|
||
|
|
||
|
\item[\scheme{time-collector-real}:]
|
||
|
The portion of the current process's real time consumed by the
|
||
|
garbage collector.
|
||
|
\end{description}
|
||
|
|
||
|
A time-object second is an exact integer (possibly negative),
|
||
|
and a nanosecond is an exact nonnegative integer less than $10^9$.
|
||
|
The second and nanosecond of a time object may be converted to
|
||
|
an aggregate nanosecond value by scaling the
|
||
|
seconds by $10^9$ and adding the nanoseconds.
|
||
|
Thus, if the second and nanosecond of a time object are 5 and 10,
|
||
|
the time object represents 5000000010 nanoseconds (5.000000010 seconds).
|
||
|
If the second and nanosecond are -5 and 10, the time object
|
||
|
represents -4999999990 nanoseconds (-4.999999990 seconds).
|
||
|
|
||
|
Dates are represented by date objects.
|
||
|
A date object records the nanosecond, second, minute, hour, day, month,
|
||
|
and year of a particular date, along with an offset that identifies the
|
||
|
time zone.
|
||
|
|
||
|
As for time objects, a nanosecond is an exact integer less than $10^9$.
|
||
|
A date-object second is, however, an exact nonnegative integer
|
||
|
less than 62.
|
||
|
(The values 61 and 62 allow for leap seconds.)
|
||
|
A minute is an exact nonnegative integer less than 60, and
|
||
|
an hour is an exact nonnegative integer less than 24.
|
||
|
A day is an exact nonnegative integer in ranging from 1 representing
|
||
|
the first day of the month to $n$, where $n$ is the number of
|
||
|
days in the date's month and year.
|
||
|
A month is an exact nonnegative integer ranging from 1 through 12,
|
||
|
where 1 represents January, 2 represents February, and so on.
|
||
|
A year must be an exact integer.
|
||
|
Years less than 1970 or greater than 2038 may not be supported
|
||
|
depending on limitations of the underlying implementation.
|
||
|
A time-zone offset represents the time-zone offset, in seconds, from UTC.
|
||
|
It is an exact integer in the range $-86400$ to $+86400$, inclusive.
|
||
|
For example, Eastern Standard Time (EST), which is 5 hours east, has
|
||
|
offset $5\times 3600 = -18000$.
|
||
|
The offset for Eastern Daylight Time (EDT) is $-14400$.
|
||
|
UTC is represented by offset zero.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-time}{\categoryprocedure}{(current-time)}
|
||
|
\formdef{current-time}{\categoryprocedure}{(current-time \var{time-type})}
|
||
|
\returns a time object representing the current time
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{time-type} must be one of the time-type symbols listed above
|
||
|
and defaults to \scheme{time-utc}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(current-time) ;=> #<time-utc 1198815722.473668000>
|
||
|
(current-time 'time-process) ;=> #<time-process 0.120534264>
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-time}{\categoryprocedure}{(make-time \var{type} \var{nsec} \var{sec})}
|
||
|
\returns a time object
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{type} must be one of the time-type symbols listed above.
|
||
|
\var{nsec} represents nanoseconds and must be an exact nonnegative
|
||
|
integer less than $10^9$.
|
||
|
\var{sec} represents seconds and must be an exact integer.
|
||
|
|
||
|
\schemedisplay
|
||
|
(make-time 'time-utc 787511000 1198783214)
|
||
|
(make-time 'time-duration 10 5)
|
||
|
(make-time 'time-duration 10 -5)
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time?}{\categoryprocedure}{(time? \var{obj})}
|
||
|
\returns \scheme{#t} if \var{obj} is a time object, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noskip\schemedisplay
|
||
|
(time? (current-time)) ;=> #t
|
||
|
(time? (make-time 'time-utc 0 0)) ;=> #t
|
||
|
(time? "1400 hours") ;=> #f
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time-type}{\categoryprocedure}{(time-type \var{time})}
|
||
|
\returns the time type of \var{time}
|
||
|
\formdef{time-nanosecond}{\categoryprocedure}{(time-nanosecond \var{time})}
|
||
|
\returns the nanosecond of \var{time}
|
||
|
\formdef{time-second}{\categoryprocedure}{(time-second \var{time})}
|
||
|
\returns the second of \var{time}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{time} must be a time object.
|
||
|
|
||
|
\schemedisplay
|
||
|
(time-type (current-time)) ;=> time-utc
|
||
|
(time-type (current-time 'time-process)) ;=> time-process
|
||
|
(time-type (make-time 'time-duration 0 50)) ;=> time-duration
|
||
|
(time-second (current-time)) ;=> 1198816497
|
||
|
(time-nanosecond (current-time)) ;=> 2399000
|
||
|
(time-second (make-time 'time-duration 10 -5)) ;=> -5
|
||
|
(time-nanosecond (make-time 'time-duration 10 -5)) ;=> 10
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{set-time-type!}{\categoryprocedure}{(set-time-type! \var{time} \var{type})}
|
||
|
\returns unspecified
|
||
|
\formdef{set-time-nanosecond!}{\categoryprocedure}{(set-time-nanosecond! \var{time} \var{nsec})}
|
||
|
\returns unspecified
|
||
|
\formdef{set-time-second!}{\categoryprocedure}{(set-time-second! \var{time} \var{sec})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{time} must be a time object.
|
||
|
\var{type} must be one of the time-type symbols listed above.
|
||
|
\var{nsec} represents nanoseconds and must be an exact nonnegative
|
||
|
integer less than $10^9$.
|
||
|
\var{sec} represents seconds and must be an exact integer.
|
||
|
|
||
|
Each of these procedures modifies the time object, changing one aspect
|
||
|
while leaving the others unaffected.
|
||
|
For example, \scheme{set-time-nanosecond!} changes the nanosecond of
|
||
|
\var{time} without changing the second or type.
|
||
|
In particular, no conversion of values is performed when the type of a time
|
||
|
object is changed.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time=?}{\categoryprocedure}{(time=? \var{time_1} \var{time_2})}
|
||
|
\formdef{time<?}{\categoryprocedure}{(time<? \var{time_1} \var{time_2})}
|
||
|
\formdef{time<=?}{\categoryprocedure}{(time<=? \var{time_1} \var{time_2})}
|
||
|
\formdef{time>=?}{\categoryprocedure}{(time>=? \var{time_1} \var{time_2})}
|
||
|
\formdef{time>?}{\categoryprocedure}{(time>? \var{time_1} \var{time_2})}
|
||
|
\returns \scheme{#t} if the relation holds, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{time_1} and \var{time_2} must be time objects and must have
|
||
|
the same type.
|
||
|
|
||
|
\schemedisplay
|
||
|
(let ([t (current-time)])
|
||
|
(time=? t t)) ;=> #t
|
||
|
(let ([t (current-time)])
|
||
|
(let loop ()
|
||
|
(when (time=? (current-time) t))
|
||
|
(loop))
|
||
|
(time>? (current-time) t)) ;=> #t
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{copy-time}{\categoryprocedure}{(copy-time \var{time})}
|
||
|
\returns a copy of \var{time}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\schemedisplay
|
||
|
(define t1 (current-time))
|
||
|
(define t2 (copy-time t1))
|
||
|
(eq? t2 t1) ;=> #f
|
||
|
(eqv? (time-second t2) (time-second t1)) ;=> #t
|
||
|
(eqv? (time-nanosecond t2) (time-nanosecond t1)) ;=> #t
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time-difference}{\categoryprocedure}{(time-difference \var{time_1} \var{time_2})}
|
||
|
\returns the result of subtracting \var{time_2} from \var{time_1}
|
||
|
\formdef{time-difference!}{\categoryprocedure}{(time-difference! \var{time_1} \var{time_2})}
|
||
|
\returns the result of subtracting \var{time_2} from \var{time_1}
|
||
|
\formdef{add-duration}{\categoryprocedure}{(add-duration \var{time} \var{time_d})}
|
||
|
\returns the result of adding \var{time_d} to \scheme{time}
|
||
|
\formdef{add-duration!}{\categoryprocedure}{(add-duration! \var{time} \var{time_d})}
|
||
|
\returns the result of adding \var{time_d} to \scheme{time}
|
||
|
\formdef{subtract-duration}{\categoryprocedure}{(subtract-duration \var{time} \var{time_d})}
|
||
|
\returns the result of subtracting \var{time_d} from \scheme{time}
|
||
|
\formdef{subtract-duration!}{\categoryprocedure}{(subtract-duration! \var{time} \var{time_d})}
|
||
|
\returns the result of subtracting \var{time_d} from \scheme{time}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
For \scheme{time-difference}, \var{time_1} and \var{time_2} must
|
||
|
have the same time type, and the result is a time object with
|
||
|
time type \scheme{time-duration}.
|
||
|
For \scheme{add-duration}, \scheme{add-duration!},
|
||
|
\scheme{subtract-duration}, and \scheme{subtract-duration!},
|
||
|
\var{time_d} must have time type \scheme{time-duration},
|
||
|
and the result is a time object with the same time type as
|
||
|
\var{time}.
|
||
|
\scheme{time-difference!}, \scheme{add-duration!}, and
|
||
|
\scheme{subtract-duration!} are potentially destructive, i.e., each
|
||
|
might modify and return its first argument, or it might allocate a
|
||
|
new time object.
|
||
|
|
||
|
\schemedisplay
|
||
|
(let ([delay (make-time 'time-duration 0 1)])
|
||
|
(let ([t1 (current-time 'time-monotonic)])
|
||
|
(sleep delay)
|
||
|
(let ([t2 (current-time 'time-monotonic)])
|
||
|
(let ([t3 (time-difference t2 t1)])
|
||
|
(and
|
||
|
(eq? (time-type t3) 'time-duration)
|
||
|
(time>=? t3 delay)
|
||
|
(time=? (add-duration t1 t3) t2)
|
||
|
(time=? (subtract-duration t2 t3) t1)))))) ;=> #t
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-date}{\categoryprocedure}{(current-date)}
|
||
|
\formdef{current-date}{\categoryprocedure}{(current-date \var{offset})}
|
||
|
\returns a date object representing the current date
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{offset} represents the time-zone offset in seconds east of UTC,
|
||
|
as described above.
|
||
|
It must be an exact integer in the range $-86400$ to
|
||
|
$+86400$, inclusive and defaults to the local time-zone offset.
|
||
|
UTC may be obtained by passing an offset of zero.
|
||
|
|
||
|
If \var{offset} is not provided, then the current time zone's offset
|
||
|
is used, and \scheme{date-dst?} and \scheme{date-zone-name} report
|
||
|
information about the time zone. If \var{offset} is provided, then
|
||
|
\scheme{date-dst?} and \scheme{date-zone-name} on the resulting date
|
||
|
object produce \scheme{#f}.
|
||
|
|
||
|
The following examples assume the local time zone is EST.
|
||
|
|
||
|
\schemedisplay
|
||
|
(current-date) ;=> #<date Thu Dec 27 23:23:20 2007>
|
||
|
(current-date 0) ;=> #<date Fri Dec 28 04:23:20 2007>
|
||
|
|
||
|
(date-zone-name (current-date)) ;=> "EST" \var{or other system-provided string}
|
||
|
(date-zone-name (current-date 0)) ;=> #f
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-date}{\categoryprocedure}{(make-date \var{nsec} \var{sec} \var{min} \var{hour} \var{day} \var{mon} \var{year})}
|
||
|
\formdef{make-date}{\categoryprocedure}{(make-date \var{nsec} \var{sec} \var{min} \var{hour} \var{day} \var{mon} \var{year} \var{offset})}
|
||
|
\returns a date object
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{nsec} represents nanoseconds and must be an exact nonnegative integer
|
||
|
less than $10^9$.
|
||
|
\var{sec} represents seconds and must be an exact nonnegative integer
|
||
|
less than 62.
|
||
|
\var{min} represents minutes and must be an exact nonnegative integer
|
||
|
less than 60.
|
||
|
\var{hour} must be an exact nonnegative integer less than 24.
|
||
|
\var{day} must be an exact integer, $1\leq day\leq 31$.
|
||
|
(The actual upper limit may be less depending on the month and year.)
|
||
|
\var{mon} represents the month must be an exact integer, $1\leq mon\leq 12$.
|
||
|
\var{year} must be an exact integer.
|
||
|
It should be at least 1970.
|
||
|
\var{offset} represents the time-zone offset in seconds east of UTC,
|
||
|
as described above.
|
||
|
It must be an exact integer in the range $-86400$ to $+86400$, inclusive.
|
||
|
UTC may be specified by passing an offset of zero.
|
||
|
|
||
|
If \var{offset} is not provided, then the current time zone's offset
|
||
|
is used, and \scheme{date-dst?} and \scheme{date-zone-name} report
|
||
|
information about the time zone. If \var{offset} is provided, then
|
||
|
\scheme{date-dst?} and \scheme{date-zone-name} on the resulting date
|
||
|
object produce \scheme{#f}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(make-date 0 0 0 0 1 1 1970 0) ;=> #<date Thu Jan 1 00:00:00 1970>
|
||
|
(make-date 0 30 7 9 23 9 2007 -14400) ;=> #<date Sun Sep 23 09:07:30 2007>
|
||
|
|
||
|
(date-zone-name (make-date 0 30 7 9 23 9 2007 -14400)) ;=> #f
|
||
|
(string? (date-zone-name (make-date 0 30 7 9 23 9 2007))) ;=> #t
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{date?}{\categoryprocedure}{(date? \var{obj})}
|
||
|
\returns \scheme{#t} if \var{obj} is a date object, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noskip\schemedisplay
|
||
|
(date? (current-date))
|
||
|
(date? (make-date 0 30 7 9 23 9 2007 -14400))
|
||
|
(date? "Sun Sep 23 09:07:30 2007") ;=> #f
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{date-nanosecond}{\categoryprocedure}{(date-nanosecond \var{date})}
|
||
|
\returns the nanosecond of \var{date}
|
||
|
\formdef{date-second}{\categoryprocedure}{(date-second \var{date})}
|
||
|
\returns the second of \var{date}
|
||
|
\formdef{date-minute}{\categoryprocedure}{(date-minute \var{date})}
|
||
|
\returns the minute of \var{date}
|
||
|
\formdef{date-hour}{\categoryprocedure}{(date-hour \var{date})}
|
||
|
\returns the hour of \var{date}
|
||
|
\formdef{date-day}{\categoryprocedure}{(date-day \var{date})}
|
||
|
\returns the day of \var{date}
|
||
|
\formdef{date-month}{\categoryprocedure}{(date-month \var{date})}
|
||
|
\returns the month of \var{date}
|
||
|
\formdef{date-year}{\categoryprocedure}{(date-year \var{date})}
|
||
|
\returns the year of \var{date}
|
||
|
\formdef{date-zone-offset}{\categoryprocedure}{(date-zone-offset \var{date})}
|
||
|
\returns the time-zone offset of \var{date}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{date} must be a date object.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define d (make-date 0 30 7 9 23 9 2007 -14400))
|
||
|
(date-nanosecond d) ;=> 0
|
||
|
(date-second d) ;=> 30
|
||
|
(date-minute d) ;=> 7
|
||
|
(date-hour d) ;=> 9
|
||
|
(date-day d) ;=> 23
|
||
|
(date-month d) ;=> 9
|
||
|
(date-year d) ;=> 2007
|
||
|
(date-zone-offset d) ;=> -14400
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{date-week-day}{\categoryprocedure}{(date-week-day \var{date})}
|
||
|
\returns the week-day of \var{date}
|
||
|
\formdef{date-year-day}{\categoryprocedure}{(date-year-day \var{date})}
|
||
|
\returns the year-day of \var{date}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
These procedures allow the day-of-week or day-of-year to be determined for
|
||
|
the date represented by \var{date}.
|
||
|
A week-day is an exact nonnegative integer less than 7, where
|
||
|
0 represents Sunday, 1 represents Monday, and so on.
|
||
|
A year-day is an exact nonnegative integer less than 367, where
|
||
|
0 represents the first day of the year (January 1), 1 the
|
||
|
second day, 2 the third, and so on.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define d1 (make-date 0 0 0 0 1 1 1970 -18000))
|
||
|
d1 ;=> #<date Thu Jan 1 00:00:00 1970>
|
||
|
(date-week-day d1) ;=> 4
|
||
|
(date-year-day d1) ;=> 0
|
||
|
|
||
|
(define d2 (make-date 0 30 7 9 23 9 2007 -14400))
|
||
|
d2 ;=> #<date Sun Sep 23 09:07:30 2007>
|
||
|
(date-week-day d2) ;=> 0
|
||
|
(date-year-day d2) ;=> 265
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{date-dst?}{\categoryprocedure}{(date-dst? \var{date})}
|
||
|
\returns whether \var{date} is in Daylight Saving Time
|
||
|
\formdef{date-zone-name}{\categoryprocedure}{(date-zone-name \var{date})}
|
||
|
\returns \scheme{#f} or a string naming the time zone of \var{date}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
These procedures report time-zone information for
|
||
|
the date represented by \var{date} for a date object that
|
||
|
is constructed without an explicit time-zone offset. When
|
||
|
a date object is created instead with explicit time-zone offset,
|
||
|
these procedures produce \scheme{#f}.
|
||
|
|
||
|
Daylight Saving Time status for the current time zone and a name
|
||
|
string for the time zone are computed using platform-specific routines.
|
||
|
In particular, the format of the zone name is platform-specific.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define d (make-date 0 30 7 9 23 9 2007))
|
||
|
(date-zone-offset d) ;=> -14400 \var{assuming Eastern U.S. time zone}
|
||
|
(date-dst? d) ;=> #t
|
||
|
(date-zone-name d) ;=> "EDT" \var{or some system-provided string}
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time-utc->date}{\categoryprocedure}{(time-utc->date \var{time})}
|
||
|
\formdef{time-utc->date}{\categoryprocedure}{(time-utc->date \var{time} \var{offset})}
|
||
|
\returns a date object corresponding to \var{time}
|
||
|
\formdef{date->time-utc}{\categoryprocedure}{(date->time-utc \var{date})}
|
||
|
\returns a time object corresponding to \var{date}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
These procedures are used to convert between time and date objects.
|
||
|
The \var{time} argument to \scheme{time-utc->date} must have time-type
|
||
|
\scheme{utc}, and \scheme{date->time-utc} always returns a time
|
||
|
object with time-type \scheme{utc}.
|
||
|
|
||
|
For \scheme{time-utc->date},
|
||
|
\var{offset} represents the time-zone offset in seconds east of UTC,
|
||
|
as described at the beginning of this section.
|
||
|
It must be an exact integer in the range $-86400$ to
|
||
|
$+86400$, inclusive and defaults to the local time-zone offset.
|
||
|
UTC may be obtained by passing an offset of zero.
|
||
|
|
||
|
If \var{offset} is not provided to \scheme{time-utc->date}, then the current time zone's offset
|
||
|
is used, and \scheme{date-dst?} and \scheme{date-zone-name} report
|
||
|
information about the time zone. If \var{offset} is provided, then
|
||
|
\scheme{date-dst?} and \scheme{date-zone-name} on the resulting date
|
||
|
object produce \scheme{#f}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define d (make-date 0 30 7 9 23 9 2007 -14400))
|
||
|
(date->time-utc d) ;=> #<time-utc 1190552850.000000000>
|
||
|
(define t (make-time 'time-utc 0 1190552850))
|
||
|
(time-utc->date t) ;=> #<date Sun Sep 23 09:07:30 2007>
|
||
|
(time-utc->date t 0) ;=> #<date Sun Sep 23 13:07:30 2007>
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{date-and-time}{\categoryprocedure}{(date-and-time)}
|
||
|
\formdef{date-and-time}{\categoryprocedure}{(date-and-time \var{date})}
|
||
|
\returns a string giving the current date and time
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
The string is always in the format illustrated by the examples below and
|
||
|
always has length 24.
|
||
|
|
||
|
\schemedisplay
|
||
|
(date-and-time) ;=> "Fri Jul 13 13:13:13 2001"
|
||
|
(define d (make-date 0 0 0 0 1 1 2007 0))
|
||
|
(date-and-time d) ;=> "Mon Jan 01 00:00:00 2007"
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sleep}{\categoryprocedure}{(sleep \var{time})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\var{time} must be a time object with type \scheme{time-duration}.
|
||
|
\var{sleep} causes the invoking thread to suspend operation for
|
||
|
approximately the amount of time indicated by the time object, unless
|
||
|
the process receives a signal that interrupts the sleep operation.
|
||
|
The actual time slept depends on the granularity of the system clock
|
||
|
and how busy the system is running other threads and processes.
|
||
|
|
||
|
|
||
|
\section{Timing and Statistics\label{SECTMISCSTATISTICS}}
|
||
|
|
||
|
This section documents procedures for timing computations.
|
||
|
The \scheme{current-time} procedure described in
|
||
|
Section~\ref{SECTSYSTEMTIMESNDATES} may also be used to
|
||
|
time computations.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{time}{\categorysyntax}{(time \var{expr})}
|
||
|
\returns the values of \var{expr}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{time} evaluates \var{expr} and, as a side-effect, prints (to the
|
||
|
console-output port) the amount of cpu time, the amount of real time,
|
||
|
the number of bytes allocated, and the amount of collection overhead
|
||
|
associated with evaluating \var{expr}.
|
||
|
|
||
|
\schemedisplay
|
||
|
> (time (collect))
|
||
|
(time (collect))
|
||
|
1 collection
|
||
|
1 ms elapsed cpu time, including 1 ms collecting
|
||
|
1 ms elapsed real time, including 1 ms collecting
|
||
|
160 bytes allocated, including 8184 bytes reclaimed
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{display-statistics}{\categoryprocedure}{(display-statistics)}
|
||
|
\formdef{display-statistics}{\categoryprocedure}{(display-statistics \var{textual-output-port})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
This procedure displays a running total of the amount of
|
||
|
cpu time, real time, bytes allocated, and collection overhead.
|
||
|
If \var{textual-output-port} is not supplied, it defaults to the current output port.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{cpu-time}{\categoryprocedure}{(cpu-time)}
|
||
|
\returns the amount of cpu time consumed since system start-up
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The amount is in milliseconds.
|
||
|
The amount includes ``system'' as well as ``user'' time, i.e., time
|
||
|
spent in the kernel on behalf of the process as well as time spent in
|
||
|
the process itself.
|
||
|
|
||
|
See also \scheme{current-time}, which returns more precise information.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{real-time}{\categoryprocedure}{(real-time)}
|
||
|
\returns the amount of real time that has elapsed since system start-up
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
The amount is in milliseconds.
|
||
|
|
||
|
See also \scheme{current-time}, which returns more precise information.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{bytes-allocated}{\categoryprocedure}{(bytes-allocated)}
|
||
|
\formdef{bytes-allocated}{\categoryprocedure}{(bytes-allocated \var{g})}
|
||
|
\returns the number of bytes currently allocated
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
If \var{g} is supplied, \scheme{bytes-allocated} returns the number of
|
||
|
bytes currently allocated for Scheme objects in the specified generation.
|
||
|
\var{g} must be a nonnegative exact integer no greater than the
|
||
|
maximum nonstatic generation, i.e., the
|
||
|
value returned by \scheme{collect-maximum-generation}, or the symbol
|
||
|
\scheme{static}.
|
||
|
If \var{g} is not supplied, \scheme{bytes-allocated} returns the total
|
||
|
number of bytes allocated in all generations.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{initial-bytes-allocated}{\categoryprocedure}{(initial-bytes-allocated)}
|
||
|
\returns the total number of bytes allocated after loading boot files
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{bytes-deallocated}{\categoryprocedure}{(bytes-deallocated)}
|
||
|
\returns the total number of bytes deallocated by the garbage collector
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The total number of bytes allocated by the current process, whether
|
||
|
still in use or not, can be obtained by summing
|
||
|
\scheme{(bytes-deallocated)} and \scheme{(bytes-allocated)}
|
||
|
and possibly subtracting \scheme{(initial-bytes-allocated)}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{current-memory-bytes}{\categoryprocedure}{(current-memory-bytes)}
|
||
|
\returns the total number of bytes currently allocated, including overhead
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{current-memory-bytes} returns the total size of the heap
|
||
|
in bytes, including not only the bytes occupied for Scheme objects
|
||
|
but also various forms of overhead, including fragmentation and
|
||
|
reserved but not currently occupied memory, and is thus an accurate
|
||
|
measure of the amount of heap memory currently reserved from the
|
||
|
operating system for the current process.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{maximum-memory-bytes}{\categoryprocedure}{(maximum-memory-bytes)}
|
||
|
\returns the maximum number of bytes ever allocated, including overhead
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{maximum-memory-bytes} returns the maximum size of the heap
|
||
|
in bytes, i.e., the maximum value that \scheme{current-memory-bytes}
|
||
|
returned or could have returned, since the last call to
|
||
|
\scheme{reset-maximum-memory-bytes!} or, if there has been no such
|
||
|
call, since the process started.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{reset-maximum-memory-bytes!}{\categoryprocedure}{(reset-maximum-memory-bytes!)}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{reset-maximum-memory-bytes!} resets the maximum recorded size
|
||
|
of the heap to the current size of the heap.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{collections}{\categoryprocedure}{(collections)}
|
||
|
\returns the number garbage collections so far
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{statistics}{\categoryprocedure}{(statistics)}
|
||
|
\returns a sstats record containing current statistics
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{statistics} packages together various timing and allocation
|
||
|
statistics into a single \scheme{sstats} record.
|
||
|
A \scheme{sstats} record has the following fields:
|
||
|
|
||
|
\begin{description}
|
||
|
\item[\scheme{cpu},] the cpu time consumed,
|
||
|
\item[\scheme{real},] the elapsed real time,
|
||
|
\item[\scheme{bytes},] the number of bytes allocated,
|
||
|
\item[\scheme{gc-count},] the number of collections,
|
||
|
\item[\scheme{gc-cpu},] the cpu time consumed during collections,
|
||
|
\item[\scheme{gc-real},] the elapsed real time during collections, and
|
||
|
\item[\scheme{gc-bytes},] the number of bytes reclaimed by the collector.
|
||
|
\end{description}
|
||
|
|
||
|
\noindent
|
||
|
All values are computed since system start-up.
|
||
|
The time values are time objects (Section~\ref{SECTSYSTEMTIMESNDATES}),
|
||
|
and the bytes and count values are exact integers.
|
||
|
|
||
|
\scheme{statistics} might be defined as follows:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define statistics
|
||
|
(lambda ()
|
||
|
(make-sstats
|
||
|
(current-time 'time-thread)
|
||
|
(current-time 'time-monotonic)
|
||
|
(- (+ (bytes-allocated) (bytes-deallocated))
|
||
|
(initial-bytes-allocated))
|
||
|
(collections)
|
||
|
(current-time 'time-collector-cpu)
|
||
|
(current-time 'time-collector-real)
|
||
|
(bytes-deallocated))))
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-sstats}{\categoryprocedure}{(make-sstats \var{cpu} \var{real} \var{bytes} \var{gc-count} \var{gc-cpu} \var{gc-real} \var{gc-bytes})}
|
||
|
\returns a sstats record
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The time arguments (\var{cpu}, \var{real}, \var{gc-cpu}, and \var{gc-real}) must be time objects.
|
||
|
The other arguments must be exact integers.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sstats?}{\categoryprocedure}{(sstats? \var{obj})}
|
||
|
\returns \scheme{#t} if \var{obj} is a sstats record, otherwise \scheme{#f}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sstats-cpu}{\categoryprocedure}{(sstats-cpu \var{s})}
|
||
|
\formdef{sstats-real}{\categoryprocedure}{(sstats-real \var{s})}
|
||
|
\formdef{sstats-bytes}{\categoryprocedure}{(sstats-bytes \var{s})}
|
||
|
\formdef{sstats-gc-count}{\categoryprocedure}{(sstats-gc-count \var{s})}
|
||
|
\formdef{sstats-gc-cpu}{\categoryprocedure}{(sstats-gc-cpu \var{s})}
|
||
|
\formdef{sstats-gc-real}{\categoryprocedure}{(sstats-gc-real \var{s})}
|
||
|
\formdef{sstats-gc-bytes}{\categoryprocedure}{(sstats-gc-bytes \var{s})}
|
||
|
\returns the value of the corresponding field of \var{s}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{s} must be a sstats record.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{set-sstats-cpu!}{\categoryprocedure}{(set-sstats-cpu! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-real!}{\categoryprocedure}{(set-sstats-real! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-bytes!}{\categoryprocedure}{(set-sstats-bytes! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-gc-count!}{\categoryprocedure}{(set-sstats-gc-count! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-gc-cpu!}{\categoryprocedure}{(set-sstats-gc-cpu! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-gc-real!}{\categoryprocedure}{(set-sstats-gc-real! \var{s} \var{new-value})}
|
||
|
\formdef{set-sstats-gc-bytes!}{\categoryprocedure}{(set-sstats-gc-bytes! \var{s} \var{new-value})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{s} must be a sstats record, the \var{new-value} arguments for the time fields
|
||
|
(\var{cpu}, \var{real}, \var{gc-cpu}, and \var{gc-real})
|
||
|
must be time objects, and
|
||
|
the other \var{new-value} arguments must be exact integers.
|
||
|
Each procedure sets the value of the corresponding field of \var{s} to
|
||
|
\var{new-value}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sstats-difference}{\categoryprocedure}{(sstats-difference \var{s_1} \var{s_2})}
|
||
|
\returns a sstats record representing the difference between \var{s_1} and \var{s_2}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{s_1} and \var{s_2} must be sstats records.
|
||
|
\scheme{sstats-difference} subtracts each field of \var{s_2} from the
|
||
|
corresponding field of \var{s_1} to produce the resulting \scheme{sstats}
|
||
|
record.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{sstats-print}{\categoryprocedure}{(sstats-print \var{s})}
|
||
|
\formdef{sstats-print}{\categoryprocedure}{(sstats-print \var{s} \var{textual-output-port})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{s} must be a \scheme{sstats} record.
|
||
|
If \var{textual-output-port} is not supplied, it defaults to the current output port.
|
||
|
\scheme{sstats-print} displays the fields of \scheme{s} in a manner similar
|
||
|
to \scheme{display-statistics} and \scheme{time}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
|
||
|
\entryheader
|
||
|
\formdef{enable-object-counts}{\categoryglobalparameter}{enable-object-counts}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The value of \scheme{enable-object-counts} is a boolean value that
|
||
|
determines whether the collector records object counts as it runs and
|
||
|
hence whether the object counts returned by the procedure
|
||
|
\scheme{object-counts} are accurate.
|
||
|
The parameter is set to \scheme{#f} by default, since enabling object
|
||
|
counts adds overhead to collection.
|
||
|
|
||
|
Counts for the static generation are always correct.
|
||
|
Counts for a nonstatic generation $n$ are correct immediately after a
|
||
|
collection of generation $m\ge n$ (regardless of whether the target
|
||
|
generation is $m$ or $m+1$) if \scheme{enable-object-counts}
|
||
|
was set to \scheme{#t} during the collection.
|
||
|
|
||
|
One strategy for collecting object counts with minimal overhead is
|
||
|
to enable object counts only while collecting the maximum nonstatic
|
||
|
generation and to obtain the object counts immediately after that
|
||
|
collection.
|
||
|
|
||
|
\entryheader
|
||
|
\formdef{object-counts}{\categoryprocedure}{(object-counts)}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The procedure \scheme{object-counts} returns a nested association list
|
||
|
representing object counts and bytes allocated for each heap-allocated
|
||
|
primitive type and record type with at least one live instance in one
|
||
|
or more generations.
|
||
|
(Heap-allocated primitive types include, e.g., pairs and vectors, but
|
||
|
not, e.g., fixnums or characters.)
|
||
|
Object counts are gathered by the collector only when
|
||
|
\scheme{enable-object-counts} is \scheme{#t}.
|
||
|
The description of \scheme{enable-object-counts} details the
|
||
|
circumstances under which the counts are accurate.
|
||
|
|
||
|
The association list returned by \scheme{object-counts} has the following
|
||
|
structure:
|
||
|
|
||
|
\schemedisplay
|
||
|
((\var{type} (\var{generation} \var{count} . \var{bytes}) \dots) \dots)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\var{type} is either the name of a primitive type, represented as a
|
||
|
symbol, e.g., \scheme{pair}, or a record-type descriptor (rtd).
|
||
|
\var{generation} is a nonnegative fixnum between 0 and the value
|
||
|
of \scheme{(collect-maximum-generation)}, inclusive, or the symbol
|
||
|
\scheme{static} representing the static generation.
|
||
|
\var{count} and \var{bytes} are nonnegative fixnums.
|
||
|
|
||
|
\schemedisplay
|
||
|
(collect-request-handler void)
|
||
|
(enable-object-counts #t)
|
||
|
(define-record-type frob (fields x))
|
||
|
(define x (make-frob (make-frob #f)))
|
||
|
(collect 3 3)
|
||
|
(cdr (assoc 3
|
||
|
(cdr (assoc (record-type-descriptor frob)
|
||
|
(object-counts))))) ;=> (2 . 16)
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Cost Centers\label{SECTMISCCOSTCENTERS}}
|
||
|
|
||
|
Cost centers are used to track the bytes allocated, instructions executed,
|
||
|
and/or cpu time elapsed while evaluating selected sections of code.
|
||
|
Cost centers are created via the procedure \scheme{make-cost-center}, and
|
||
|
costs are tracked via the procedure \scheme{with-cost-center}.
|
||
|
|
||
|
Allocation and instruction counts are tracked only for code instrumented
|
||
|
for that purpose.
|
||
|
This instrumentation is controlled by two parameters: \scheme{generate-allocation-counts}
|
||
|
and \scheme{generate-instruction-counts}.
|
||
|
Instrumentation is disabled by default.
|
||
|
Built in procedures are not instrumented, nor is interpreted code or
|
||
|
non-Scheme code.
|
||
|
Elapsed time is tracked only when the optional \scheme{timed?} argument to
|
||
|
\scheme{with-cost-center} is provided and is not false.
|
||
|
|
||
|
The \scheme{with-cost-center} procedure accurately tracks costs, subject
|
||
|
to the caveats above, even when reentered with the same cost center, used
|
||
|
simultaneously in multiple threads, and exited or reentered one or more
|
||
|
times via continuation invocation.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{generate-allocation-counts}{\categorythreadparameter}{generate-allocation-counts}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
When this parameter has a true value, the compiler inserts a short sequence of
|
||
|
instructions at each allocation point in generated code to track the amount of
|
||
|
allocation that occurs.
|
||
|
This parameter is initially false.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{generate-instruction-counts}{\categorythreadparameter}{generate-instruction-counts}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
When this parameter has a true value, the compiler inserts a short
|
||
|
sequence of instructions in each block of generated code to track the
|
||
|
number of instructions executed by that block.
|
||
|
This parameter is initially false.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-cost-center}{\categoryprocedure}{(make-cost-center)}
|
||
|
\returns a new cost center
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The recorded costs of the new cost center are initialized to zero.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{cost-center?}{\categoryprocedure}{(cost-center? \var{obj})}
|
||
|
\returns \scheme{#t} if \var{obj} is a cost center, otherwise \scheme{#f}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{with-cost-center}{\categoryprocedure}{(with-cost-center \var{cost-center} \var{thunk})}
|
||
|
\formdef{with-cost-center}{\categoryprocedure}{(with-cost-center \var{timed?} \var{cost-center} \var{thunk})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\var{thunk} must be a procedure that accepts zero arguments.
|
||
|
\scheme{with-cost-center} invokes \var{thunk} without arguments and
|
||
|
returns its values.
|
||
|
It also tracks, dynamically, the bytes allocated, instructions executed,
|
||
|
and cpu time elapsed while evaluating the invocation of \var{thunk} and
|
||
|
adds the tracked costs to the cost center's running record of these costs.
|
||
|
|
||
|
As described above, allocation counts are tracked only for code
|
||
|
compiled with the parameter \scheme{generate-allocation-counts} set
|
||
|
to true, and instruction counts are tracked only for code compiled
|
||
|
with \scheme{generate-instruction-counts} set to true.
|
||
|
Cpu time is tracked only if \var{timed?} is provided and not false and
|
||
|
includes cpu time spent in instrumented, uninstrumented, and non-Scheme
|
||
|
code.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{cost-center-instruction-count}{\categoryprocedure}{(cost-center-instruction-count \var{cost-center})}
|
||
|
\returns the number of instructions tracked by \var{cost-center}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{cost-center-allocation-count}{\categoryprocedure}{(cost-center-allocation-count \var{cost-center})}
|
||
|
\returns the number of allocated bytes tracked by \var{cost-center}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{cost-center-time}{\categoryprocedure}{(cost-center-time \var{cost-center})}
|
||
|
\returns the cpu time tracked by \var{cost-center}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The cpu time is returned as a time object with time-type \scheme{time-duration}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{reset-cost-center!}{\categoryprocedure}{(reset-cost-center! \var{cost-center})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This procedure resets the costs recorded by \var{cost-center} to zero.
|
||
|
|
||
|
|
||
|
\section{Parameters\label{SECTPARAMETERS}}
|
||
|
|
||
|
This section describes mechanisms for creating and manipulating parameters.
|
||
|
New parameters may be created conveniently with \scheme{make-parameter}.
|
||
|
Nothing distinguishes parameters from other
|
||
|
procedures, however, except for their behavior.
|
||
|
If more complicated actions must be taken when a parameter is invoked
|
||
|
than can be accommodated easily through the \scheme{make-parameter} mechanism,
|
||
|
the parameter may be defined directly with \scheme{case-lambda}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{make-parameter}{\categoryprocedure}{(make-parameter \var{object})}
|
||
|
\formdef{make-parameter}{\categoryprocedure}{(make-parameter \var{object} \var{procedure})}
|
||
|
\returns a parameter (procedure)
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\scheme{make-parameter} accepts one or two arguments.
|
||
|
The first argument is the initial value of the internal variable, and
|
||
|
the second, if present, is a \emph{filter} applied to the initial value
|
||
|
and all subsequent values.
|
||
|
The filter should accept one argument.
|
||
|
If the value is not appropriate, the filter should raise an exception or
|
||
|
convert the value into a more appropriate form.
|
||
|
|
||
|
For example, the default value of \scheme{print-length} is defined as
|
||
|
follows:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define print-length
|
||
|
(make-parameter
|
||
|
#f
|
||
|
(lambda (x)
|
||
|
(unless (or (not x) (and (fixnum? x) (fx>= x 0)))
|
||
|
(assertion-violationf 'print-length
|
||
|
"~s is not a positive fixnum or #f"
|
||
|
x))
|
||
|
x)))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\schemedisplay
|
||
|
(print-length) ;=> #f
|
||
|
(print-length 3)
|
||
|
(print-length) ;=> 3
|
||
|
(format "~s" '(1 2 3 4 5 6)) ;=> "(1 2 3 ...)"
|
||
|
(print-length #f)
|
||
|
(format "~s" '(1 2 3 4 5 6)) ;=> "(1 2 3 4 5 6)"
|
||
|
\endschemedisplay
|
||
|
|
||
|
The definition of \scheme{make-parameter} is straightforward using
|
||
|
\index{\scheme{case-lambda}}\scheme{case-lambda}:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define make-parameter
|
||
|
(case-lambda
|
||
|
[(init guard)
|
||
|
(let ([v (guard init)])
|
||
|
(case-lambda
|
||
|
[() v]
|
||
|
[(u) (set! v (guard u))]))]
|
||
|
[(init)
|
||
|
(make-parameter init (lambda (x) x))]))
|
||
|
\endschemedisplay
|
||
|
|
||
|
In threaded versions of {\ChezScheme}, \scheme{make-parameter} creates
|
||
|
global parameters.
|
||
|
The procedure \scheme{make-thread-parameter}, described in
|
||
|
Section~\ref{SECTTHREADPARAMETERS}, may be used to make thread
|
||
|
parameters.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{parameterize}{\categorysyntax}{(parameterize ((\var{param} \var{expr}) \dots) \var{body_1} \var{body_2} \dots)}
|
||
|
\returns the values of the body \scheme{\var{body_1} \var{body_2} \dots}
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
Using the syntactic form \scheme{parameterize}, the values of parameters can
|
||
|
be changed in a manner analogous to \scheme{fluid-let} for ordinary variables.
|
||
|
Each \var{param} is set to the value of the corresponding
|
||
|
\var{expr} while the body is evaluated.
|
||
|
When control leaves the body by normal return or by the invocation of a
|
||
|
continuation created outside of the body, the parameters are restored to
|
||
|
their original values.
|
||
|
If control returns to the body via a continuation created during the
|
||
|
execution of the body, the parameters are again set to their temporary
|
||
|
values.
|
||
|
|
||
|
\schemedisplay
|
||
|
(define test
|
||
|
(make-parameter 0))
|
||
|
(test) ;=> 0
|
||
|
(test 1)
|
||
|
(test) ;=> 1
|
||
|
(parameterize ([test 2])
|
||
|
(test)) ;=> 2
|
||
|
(test) ;=> 1
|
||
|
(parameterize ([test 2])
|
||
|
(test 3)
|
||
|
(test)) ;=> 3
|
||
|
(test) ;=> 1
|
||
|
(define k (lambda (x) x))
|
||
|
(begin (set! k (call/cc k))
|
||
|
'k) ;=> k
|
||
|
(parameterize ([test 2])
|
||
|
(test (call/cc k))
|
||
|
(test)) ;=> k
|
||
|
(test) ;=> 1
|
||
|
(k 3) ;=> 3
|
||
|
(test) ;=> 1
|
||
|
\endschemedisplay
|
||
|
|
||
|
The definition of \scheme{parameterize} is similar to the definition of
|
||
|
\scheme{fluid-let} (page~\pageref{defn:fluid-let}):
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax parameterize
|
||
|
(lambda (x)
|
||
|
(syntax-case x ()
|
||
|
[(_ () b1 b2 ...) #'(begin b1 b2 ...)]
|
||
|
[(_ ((x e) ...) b1 b2 ...)
|
||
|
(with-syntax ([(p ...) (generate-temporaries #'(x ...))]
|
||
|
[(y ...) (generate-temporaries #'(x ...))])
|
||
|
#'(let ([p x] ... [y e] ...)
|
||
|
(let ([swap (lambda ()
|
||
|
(let ([t (p)]) (p y) (set! y t))
|
||
|
...)])
|
||
|
(dynamic-wind swap (lambda () b1 b2 ...) swap))))])))
|
||
|
\endschemedisplay
|
||
|
|
||
|
\section{Virtual registers\label{SECTVIRTUALREGISTERS}}
|
||
|
|
||
|
A limited set of \emph{virtual registers} is supported by the compiler
|
||
|
for use by programs that require high-speed, global, and mutable storage
|
||
|
locations.
|
||
|
Referencing or assigning a virtual register is potentially faster and
|
||
|
never slower than accessing an assignable local or global variable,
|
||
|
and the code sequences for doing so are generally smaller.
|
||
|
Assignment is potentially significantly faster because there is no need
|
||
|
to track pointers from the virtual registers to young objects, as there
|
||
|
is for variable locations that might reside in older generations.
|
||
|
On threaded versions of the system, virtual registers are ``per thread''
|
||
|
and thus serve as thread-local storage in a manner that is less expensive
|
||
|
than thread parameters.
|
||
|
|
||
|
The interface consists of three procedures: \scheme{virtual-register-count},
|
||
|
which returns the number of virtual registers, \scheme{set-virtual-register!},
|
||
|
which sets the value of a specified virtual register, and
|
||
|
\scheme{virtual-register}, which retrieves the value of a specified
|
||
|
virtual register.
|
||
|
|
||
|
A virtual register is specified by a nonnegative fixnum index less than
|
||
|
the number of virtual registers.
|
||
|
To get optimal performance for \scheme{set-virtual-register!}
|
||
|
and \scheme{virtual-register}, the index should be a constant
|
||
|
embedded right in the call (or propagatable via optimization to the
|
||
|
call).
|
||
|
To avoid putting these constants in the source code, programmers should
|
||
|
consider using identifier macros to give names to virtual registers, e.g.:
|
||
|
|
||
|
\schemedisplay
|
||
|
(define-syntax current-state
|
||
|
(identifier-syntax
|
||
|
[id (virtual-register 0)]
|
||
|
[(set! id e) (set-virtual-register! 0 e)]))
|
||
|
(set! current-state 'start)
|
||
|
current-state ;=> start
|
||
|
\endschemedisplay
|
||
|
|
||
|
A more elaborate macro could dole out indices at compile time and complain
|
||
|
when no more indices are available.
|
||
|
|
||
|
Virtual-registers must be treated as an application-level resource, i.e.,
|
||
|
libraries intended to be used by multiple applications should generally
|
||
|
not use virtual registers to avoid conflicts with an application's use of
|
||
|
the registers.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{virtual-register-count}{\categoryprocedure}{(virtual-register-count)}
|
||
|
\returns the number of virtual registers
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
As of Version~9.0, the number of virtual registers is set at 16.
|
||
|
It cannot be changed except by recompiling {\ChezScheme} from
|
||
|
source.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{set-virtual-register!}{\categoryprocedure}{(set-virtual-register! \var{k} \var{x})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{set-virtual-register!} stores \var{x} in virtual register \var{k}.
|
||
|
\var{k} must be a nonnegative fixnum less than the value of
|
||
|
\scheme{(virtual-register-count)}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{virtual-register}{\categoryprocedure}{(virtual-register \var{k})}
|
||
|
\returns see below
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\scheme{virtual-register} returns the value most recently
|
||
|
stored in virtual register \var{k} (on the current thread, in
|
||
|
threaded versions of the system).
|
||
|
|
||
|
|
||
|
\section{Environmental Queries and Settings\label{SECTSYSTEMENV}}
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{scheme-version}{\categoryprocedure}{(scheme-version)}
|
||
|
\returns a version string
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The version string is in the form
|
||
|
|
||
|
\schemedisplay
|
||
|
"Chez Scheme Version \var{version}"
|
||
|
\endschemedisplay
|
||
|
|
||
|
for {\ChezScheme}, and
|
||
|
|
||
|
\schemedisplay
|
||
|
"Petite Chez Scheme Version \var{version}"
|
||
|
\endschemedisplay
|
||
|
|
||
|
for {\PetiteChezScheme}.
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{scheme-version-number}{\categoryprocedure}{(scheme-version-number)}
|
||
|
\returns three values: the major, minor, and sub-minor version numbers
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
Each of the three return values is a nonnegative fixnum.
|
||
|
|
||
|
In {\ChezScheme} Version 7.9.4:
|
||
|
|
||
|
\schemedisplay
|
||
|
(scheme-version-number) ;=> 7
|
||
|
;== 9
|
||
|
;== 4
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{petite?}{\categoryprocedure}{(petite?)}
|
||
|
\returns \scheme{#t} if called in {\PetiteChezScheme}, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
The only difference between {\PetiteChezScheme} and {\ChezScheme} is that
|
||
|
the compiler is not available in the former, so this predicate can serve as
|
||
|
a way to determine if the compiler is available.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{threaded?}{\categoryprocedure}{(threaded?)}
|
||
|
\returns \scheme{#t} if called in a threaded version of the system, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{interactive?}{\categoryprocedure}{(interactive?)}
|
||
|
\returns \scheme{#t} if system is run interactively, \scheme{#f} otherwise
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
This predicate returns \scheme{#t} if the Scheme process's
|
||
|
stdin and stdout are connected to a tty (Unix-based systems) or console
|
||
|
(Windows).
|
||
|
Otherwise, it returns \scheme{#f}.
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{get-process-id}{\categoryprocedure}{(get-process-id)}
|
||
|
\returns the operating system process id of the current process
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\noskipentryheader
|
||
|
\formdef{getenv}{\categoryprocedure}{(getenv \var{key})}
|
||
|
\returns environment value of \var{key} or \scheme{#f}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{key} must be a string.
|
||
|
\scheme{getenv} returns the operating system shell's environment value
|
||
|
associated with \var{key}, or \scheme{#f} if no environment value
|
||
|
is associated with \var{key}.
|
||
|
|
||
|
\schemedisplay
|
||
|
(getenv "HOME") ;=> "/u/freddy"
|
||
|
\endschemedisplay
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{putenv}{\categoryprocedure}{(putenv \var{key} \var{value})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{key} and \var{value} must be strings.
|
||
|
|
||
|
\scheme{putenv} stores the \var{key}, \var{value} pair in the
|
||
|
environment of the process,
|
||
|
where it is available to the current process (e.g., via \var{getenv})
|
||
|
and any spawned processes.
|
||
|
|
||
|
\schemedisplay
|
||
|
(putenv "SCHEME" "rocks!")
|
||
|
(getenv "SCHEME") ;=> "rocks!"
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
%----------------------------------------------------------------------------
|
||
|
\entryheader
|
||
|
\formdef{get-registry}{\categoryprocedure}{(get-registry \var{key})}
|
||
|
\returns registry value of \var{key} or \scheme{#f}
|
||
|
\formdef{put-registry!}{\categoryprocedure}{(put-registry! \var{key} \var{val})}
|
||
|
\formdef{remove-registry!}{\categoryprocedure}{(remove-registry! \var{key})}
|
||
|
\returns unspecified
|
||
|
\listlibraries
|
||
|
\endentryheader
|
||
|
|
||
|
\noindent
|
||
|
\var{key} and \var{val} must be strings.
|
||
|
|
||
|
\scheme{get-registry} returns a string containing the registry
|
||
|
value of \var{key} if the value exists.
|
||
|
If no registry value for \var{key} exists, \scheme{get-registry} returns
|
||
|
\scheme{#f}.
|
||
|
|
||
|
\scheme{put-registry!} sets the registry
|
||
|
value of \var{key} to \var{val}.
|
||
|
It raises an exception with condition type \scheme{&assertion} if the
|
||
|
value cannot be set, which may happen if
|
||
|
the user has insufficient access.
|
||
|
|
||
|
\scheme{remove-registry!} removes the registry
|
||
|
key or value named by \var{key}.
|
||
|
It raises an exception with condition type \scheme{&assertion} if the
|
||
|
value cannot be removed.
|
||
|
Reasons for failure include the key not being present, the user having
|
||
|
insufficient access, or \var{key} being a key with subkeys.
|
||
|
|
||
|
These routines are defined for Windows only.
|
||
|
|
||
|
\schemedisplay
|
||
|
(get-registry "hkey_local_machine\\Software\\North\\South") ;=> #f
|
||
|
(put-registry! "hkey_local_machine\\Software\\North\\South" "east")
|
||
|
(get-registry "hkey_local_machine\\Software\\North\\South") ;=> "east"
|
||
|
(remove-registry! "hkey_local_machine\\Software\\North")
|
||
|
(get-registry "hkey_local_machine\\Software\\North\\South") ;=> #f
|
||
|
\endschemedisplay
|
||
|
|
||
|
|
||
|
\section{Subset Modes\label{SECTMISCSUBSETMODE}}
|
||
|
|
||
|
\noskipentryheader
|
||
|
\formdef{subset-mode}{\categorythreadparameter}{subset-mode}
|
||
|
\listlibraries
|
||
|
\endnoskipentryheader
|
||
|
|
||
|
\noindent
|
||
|
The value of this parameter
|
||
|
must be \scheme{#f} (the default) or the symbol \scheme{system}.
|
||
|
Setting \scheme{subset-mode} to \scheme{system} allows the manipulation
|
||
|
of various undocumented system variables, data structures, and
|
||
|
settings.
|
||
|
It is typically used only for system debugging.
|