14.2 Evaluation and Compilation
Reflection and Dynamic Evaluation in The Racket Guide introduces dynamic evaluation.
Racket provides programmatic control over evaluation through eval and related functions. See Controlling and Inspecting Compilation for information about extra-linguistic facilities related to the Racket compiler.
parameter
(current-eval) → (any/c . -> . any)
(current-eval proc) → void? proc : (any/c . -> . any)
The top-level-form provided to the handler can be a syntax object, a compiled form, a compiled form wrapped as a syntax object, or an arbitrary datum.
The default handler converts an arbitrary datum to a syntax object using datum->syntax, and then enriches its lexical information in the same way as eval. (If top-level-form is a syntax object, then its lexical information is not enriched.) The default evaluation handler partially expands the form to splice the body of top-level begin forms into the top level (see expand-to-top-form), and then individually compiles and evaluates each spliced form before continuing to expand, compile, and evaluate later forms.
procedure
top-level-form : any/c namespace : namespace? = (current-namespace)
See also Namespaces in The Racket Guide.
Calls the current evaluation handler to evaluate top-level-form. The evaluation handler is called in tail position with respect to the eval call, and parameterized to set current-namespace to namespace.
If top-level-form is a syntax object whose datum is not a compiled form, then its lexical information is enriched before it is sent to the evaluation handler:
If top-level-form is a pair whose car is a symbol or identifier, and if applying namespace-syntax-introduce to the (datum->syntax-converted) identifier produces an identifier bound to module in a phase level that corresponds to namespace’s base phase, then only that identifier is enriched.
For any other top-level-form, namespace-syntax-introduce is applied to the entire syntax object.
For interactive evaluation in the style of read-eval-print-loop and load, wrap each expression with #%top-interaction, which is normally bound to #%top-interaction, before passing it to eval.
procedure
(eval-syntax stx [namespace]) → any
stx : syntax? namespace : namespace? = (current-namespace)
parameter
→
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any) (current-load proc) → void?
proc :
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any)
A load handler takes two arguments: a path (see Paths) and an expected module name. The expected module name is a symbol or a list when the call is to load a module declaration in response to a require (in which case the file should contain a module declaration), or #f for any other load.
When loading a module from a stream that starts with a compiled module
that contains submodules, the load handler should load only the
requested module, where a symbol as the load handler’s indicates the
root module and a list indicates a submodule whose path relative to
the root module is given by the cdr of the list. The list
starts with #f when a submodule should be loaded only
if it can be loaded independently (i.e., from compiled form—
The default load handler reads forms from the file in read-syntax mode with line-counting enabled for the file port, unless the path has a ".zo" suffix. It also parameterizes each read to set read-accept-compiled, read-accept-reader, and read-accept-lang to #t. In addition, if load-on-demand-enabled is #t, then read-on-demand-source is set to the cleansed, absolute form of path during the read-syntax call. After reading a single form, the form is passed to the current evaluation handler, wrapping the evaluation in a continuation prompt (see call-with-continuation-prompt) for the default continuation prompt tag with handler that propagates the abort to the continuation of the load call.
If the second argument to the load handler is a symbol, then:
The read-syntax from the file is additionally parameterized as follows (to provide consistent reading of module source):
(current-readtable #f) (read-case-sensitive #t) (read-square-bracket-as-paren #t) (read-curly-brace-as-paren #t) (read-accept-box #t) (read-accept-compiled #t) (read-accept-bar-quote #t) (read-accept-graph #t) (read-decimal-as-inexact #t) (read-accept-dot #t) (read-accept-infix-dot #t) (read-accept-quasiquote #t) (read-accept-reader #t) (read-accept-lang #t) If the read result is not a module form, or if a second read-syntax does not produce an end-of-file, then the exn:fail exception is raised without evaluating the form that was read from the file. (In previous versions, the module declaration was checked to match the name given as the second argument to the load handler, but this check is no longer performed.)
The lexical information of the initial module identifier is enriched with a binding for module, so that the form corresponds to a module declaration independent of the current namespace’s bindings.
If the second argument to the load handler is #f, then each expression read from the file is wrapped with #%top-interaction, which is normally bound to #%top-interaction, before passing it to the evaluation handler.
The return value from the default load handler is the value of the last form from the loaded file, or #<void> if the file contains no forms. If the given path is a relative path, then it is resolved using the value of current-directory.
procedure
file : path-string?
See also Namespaces in The Racket Guide.
Calls the current load handler in tail position. The call is parameterized to set current-load-relative-directory to the directory of file, which is resolved relative to the value of current-directory.
procedure
(load-relative file) → any
file : path-string?
procedure
file : path-string?
parameter
→
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any) (current-load-extension proc) → void?
proc :
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any)
An extension-load handler takes the same arguments as a load handler, but the file should be a platform-specific dynamic extension, typically with the file suffix ".so" (Unix), ".dll" (Windows), or ".dylib" (Mac OS). The file is loaded using internal, OS-specific primitives. See Inside: Racket C API for more information on dynamic extensions.
Extensions are supported only when (system-type 'vm) returns 'racket.
procedure
(load-extension file) → any
file : path-string?
Extensions are supported only when (system-type 'vm) returns 'racket.
procedure
(load-relative-extension file) → any
file : path-string?
Extensions are supported only when (system-type 'vm) returns 'racket.
parameter
→
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any) (current-load/use-compiled proc) → void?
proc :
(path? (or/c #f symbol? (cons/c (or/c #f symbol?) (non-empty-listof symbol?))) . -> . any)
The protocol for a compiled-load handler is the same as for the load handler (see current-load), except that a compiled-load handler is expected to set current-load-relative-directory itself. Additionally, the default compiled-load handler does the following:
When the given path ends with ".rkt", no ".rkt" file exists, and when the handler’s second argument is not #f, the default compiled-load handler checks for a ".ss" file.
The default compiled-load handler checks for the opportunity to load from ".zo" (bytecode) files and, when (system-type 'vm) returns 'racket, for ".so" (native Unix), ".dll" (native Windows), or ".dylib" (native Mac OS) files.
When the default compiled-load handler needs to load from the given path, the given path does not exist, and when the handler’s second argument is not #f, the default compiled-load handler returns without raising an exception.
The check for a compiled file occurs whenever the given path file ends with any extension (e.g., ".rkt" or ".scrbl"), and the check consults the subdirectories indicated by the current-compiled-file-roots and use-compiled-file-paths parameters relative to file, where the former supplies “roots” for compiled files and the latter provides subdirectories. See also compiler/compilation-path. A “root” can be an absolute path, in which case file’s directory is combined with reroot-path and the root as the second argument; if the “root” is a relative path, then the relative path is instead suffixed onto the directory of file. The roots are tried in order, and the subdirectories are checked in order within each root. A ".zo" version of the file (whose name is formed by passing file and #".zo" to path-add-extension) is loaded if it exists directly in one of the indicated subdirectories, or when (system-type 'vm) returns 'racket, then a ".so"/".dll"/".dylib" version of the file is loaded if it exists within a "native" subdirectory of a use-compiled-file-paths directory, in an even deeper subdirectory as named by system-library-subpath. A compiled file is loaded only if it checks out according to (use-compiled-file-check); with the default parameter value of 'modify-seconds, a compiled file is used only if its modification date is not older than the date for file. If both ".zo" and ".so"/".dll"/".dylib" files are available when (system-type 'vm) returns 'racket, the ".so"/".dll"/".dylib" file is used. If file ends with ".rkt", no such file exists, the handler’s second argument is a symbol, and a ".ss" file exists, then ".zo" and ".so"/".dll"/".dylib" files are used only with names based on file with its suffixed replaced by ".ss".
While a ".zo", ".so", ".dll", or ".dylib" file is loaded, the current load-relative directory is set to the directory of the original file. If the file to be loaded has the suffix ".ss" while the requested file has the suffix ".rkt", then the current-module-declare-source parameter is set to the full path of the loaded file, otherwise the current-module-declare-source parameter is set to #f.
If the original file is loaded or a ".zo" variant is loaded, the load handler is called to load the file. If any other kind of file is loaded, the extension-load handler is called.
When the default compiled-load handler loads a module from a bytecode (i.e., ".zo") file, the handler records the bytecode file path in the current namespace’s module registry. More specifically, the handler records the path for the top-level module of the loaded module, which is an enclosing module if the loaded module is a submodule. Thereafter, loads via the default compiled-load handler for modules within the same top-level module use the recorded file, independent of the file that otherwise would be selected by the compiled-load handler (e.g., even if the use-compiled-file-paths parameter value changes). The default module name resolver transfers bytecode-file information when a module declaration is attached to a new namespace. This protocol supports independent but consistent loading of submodules from bytecode files.
procedure
(load/use-compiled file) → any
file : path-string?
parameter
→ (or/c (and/c path-string? complete-path?) #f) (current-load-relative-directory path) → void? path : (or/c (and/c path-string? complete-path?) #f)
When a new path or string is provided as the parameter’s value, it is immediately expanded (see Paths) and converted to a path. (The directory need not exist.)
parameter
→ (listof (and/c path? relative-path?)) (use-compiled-file-paths paths) → void? paths : (listof (and/c path-string? relative-path?))
If the PLT_ZO_PATH environment variable is set on startup, it supplies a path instead of "compiled" to use for the initial parameter value.
Changed in version 7.7.0.9 of package base: Added PLT_ZO_PATH.
parameter
(current-compiled-file-roots) → (listof (or/c path? 'same))
(current-compiled-file-roots paths) → void? paths : (listof (or/c path-string? 'same))
The parameter is normally initialized to (list 'same), but the parameter’s initial value can be adjusted by the installation configuration as reported by (find-compiled-file-roots), and it can be further adjusted by the PLTCOMPILEDROOTS environment variable or the --compiled or -R command-line flag for racket. If the environment variable is defined and not overridden by a command-line flag, it is parsed by first replacing any @(version) with the result of (version), then using path-list-string->path-list with a path list produced by (find-compiled-file-roots) to arrive at the parameter’s initial value.
procedure
(find-compiled-file-roots) → (listof (or/c path? 'same))
See also 'compiled-file-roots in Installation Configuration and Search Paths.
Added in version 8.0.0.9 of package base.
parameter
(use-compiled-file-check) → (or/c 'modify-seconds 'exists)
(use-compiled-file-check check) → void? check : (or/c 'modify-seconds 'exists)
If the PLT_COMPILED_FILE_CHECK environment variable is set to modify-seconds or exists, then the environment variable’s value configures the parameter when Racket starts.
Added in version 6.6.0.3 of package base.
procedure
The read-eval-print-loop procedure can be configured through the current-prompt-read, current-eval, and current-print parameters.
parameter
(current-prompt-read) → (-> any)
(current-prompt-read proc) → void? proc : (-> any)
The default prompt read handler prints > and returns the result of
(let ([in ((current-get-interaction-input-port))]) ((current-read-interaction) (object-name in) in))
If the input and output ports are both terminals (in the sense of terminal-port?) and if the output port appears to be counting lines (because port-next-location returns a non-#f line and column), then the output port’s line is incremented and its column is reset to 0 via set-port-next-location! before returning the read result.
parameter
(current-get-interaction-input-port proc) → void? proc : (-> input-port?)
The default interaction port handler returns the current input port. In addition, if that port is the initial current input port, the initial current output and error ports are flushed.
The racket/gui/base library adjusts this parameter’s value by extending the current value. The extension wraps the result port so that GUI events can be handled when reading from the port blocks.
parameter
(current-read-interaction proc) → void? proc : (any/c input-port? -> any)
The default read interaction handler accepts src and in and returns
(parameterize ([read-accept-reader #t] [read-accept-lang #f]) (read-syntax src in))
parameter
(current-print) → (any/c -> any)
(current-print proc) → void? proc : (any/c -> any)
The default print handler prints the value to the current output port (as determined by the current-output-port parameter) and then outputs a newline, except that it prints nothing when the value is #<void>.
parameter
→ (any/c boolean? . -> . compiled-expression?) (current-compile proc) → void? proc : (any/c boolean? . -> . compiled-expression?)
The compilation handler is called by compile, and indirectly by the default evaluation handler and the default load handler.
The handler’s second argument is #t if the compiled form will be used only for immediate evaluation, or #f if the compiled form may be saved for later use; the default compilation handler is optimized for the special case of immediate evaluation.
When a compiled form is written to an output port, the written form starts with #~. See Printing Compiled Code for more information.
For internal testing purposes, when the PLT_VALIDATE_COMPILE environment variable is set, the default compilation handler runs a bytecode validator immediately on its own compilation results (instead of relying only on validation when compiled bytecode is loaded).
procedure
(compile top-level-form) → compiled-expression?
top-level-form : any/c
procedure
(compile-syntax stx) → compiled-expression?
stx : syntax?
procedure
ce : compiled-expression?
Added in version 6.3 of package base.
procedure
(compiled-expression? v) → boolean?
v : any/c
parameter
(compile-enforce-module-constants on?) → void? on? : any/c
When constants are enforced, and when the macro-expanded body of a module contains no set! assignment to a particular variable defined within the module, then the variable is marked as constant when the definition is evaluated. Afterward, the variable’s value cannot be assigned or undefined through module->namespace, and it cannot be defined by redeclaring the module.
Enforcing constants allows the compiler to inline some variable values, and it allows the native-code just-in-time compiler to generate code that skips certain run-time checks.
parameter
(compile-allow-set!-undefined allow?) → void? allow? : any/c
parameter
(compile-context-preservation-enabled on?) → void? on? : any/c
parameter
→ (or/c #f (and/c symbol? compile-target-machine?)) (current-compile-target-machine target) → void? target : (or/c #f (and/c symbol? compile-target-machine?))
If the target is #f, the the compiled expression writes in a machine-independent format (usually in ".zo" files). Machine-independent compiled code works for any platform and any Racket virtual machine. When the machine-independent compiled expression is read back in, it is subject to further compilation for the current platform and virtual machine, which can be considerably slower than reading a format that is fully compiled for a platform and virtual machine.
The default is something other than #f, unless machine-independent mode is enabled through the -M/--compile-any command-line flag to stand-alone Racket (or GRacket) or through the PLT_COMPILE_ANY environment variable (set to any value).
Added in version 7.1.0.6 of package base.
procedure
(compile-target-machine? sym) → boolean?
sym : symbol?
When (system-type 'vm) reports 'racket, then the only target symbol is 'racket. When (system-type 'vm) reports 'chez-scheme, then a symbol corresponding to the current platform is a target, and other targets may also be supported. The 'target-machine mode of system-type reports the running Racket’s native target machine.
Added in version 7.1.0.6 of package base.
parameter
(eval-jit-enabled on?) → void? on? : any/c
A parameter that determines whether the native-code just-in-time compiler (JIT) is enabled for code (compiled or not) that is passed to the default evaluation handler. A true parameter value is effective only on platforms for which the JIT is supported and for Racket virtual machines that rely on a JIT.
The default is #t, unless the JIT is not supported by the current platform but is supported on the same virtual machine for other platforms, unless it is disabled through the -j/--no-jit command-line flag to stand-alone Racket (or GRacket), and unless it is disabled through the PLTNOMZJIT environment variable (set to any value).
parameter
(load-on-demand-enabled on?) → void? on? : any/c