#lang scribble/doc @(require "utils.ss") @title{Evaluation} A Scheme S-expression is evaluated by calling @cppi{scheme_eval}. This function takes an S-expression (as a @cpp{Scheme_Object*}) and a namespace and returns the value of the expression in that namespace. The function @cppi{scheme_apply} takes a @cpp{Scheme_Object*} that is a procedure, the number of arguments to pass to the procedure, and an array of @cpp{Scheme_Object *} arguments. The return value is the result of the application. There is also a function @cppi{scheme_apply_to_list}, which takes a procedure and a list (constructed with @cppi{scheme_make_pair}) and performs the Scheme @scheme[apply] operation. The @cppi{scheme_eval} function actually calls @cppi{scheme_compile} followed by @cppi{scheme_eval_compiled}. @; ---------------------------------------------------------------------- @section[#:tag "topleveleval"]{Top-level Evaluation Functions} The functions @cpp{scheme_eval}, @cpp{scheme_apply}, etc., are @defterm{top-level evaluation functions}. Continuation invocations are confined to jumps within a top-level evaluation. The functions @cppi{_scheme_eval_compiled}, @cppi{_scheme_apply}, etc. (with a leading underscore) provide the same functionality without starting a new top-level evaluation; these functions should only be used within new primitive procedures. Since these functions allow full continuation hops, calls to non-top-level evaluation functions can return zero or multiple times. Currently, escape continuations and primitive error escapes can jump out of all evaluation and application functions. For more information, see @secref["exceptions"]. @; ---------------------------------------------------------------------- @section{Tail Evaluation} @section-index{tail recursion} All of Scheme's built-in functions and syntax support proper tail-recursion. When a new primitive procedure or syntax is added to Scheme, special care must be taken to ensure that tail recursion is handled properly. Specifically, when the final return value of a function is the result of an application, then @cppi{scheme_tail_apply} should be used instead of @cppi{scheme_apply}. When @cppi{scheme_tail_apply} is called, it postpones the procedure application until control returns to the Scheme evaluation loop. For example, consider the following implementation of a @scheme[thunk-or] primitive, which takes any number of thunks and performs @scheme[or] on the results of the thunks, evaluating only as many thunks as necessary. @verbatim{ static Scheme_Object * thunk_or (int argc, Scheme_Object **argv) { int i; Scheme_Object *v; if (!argc) return scheme_false; for (i = 0; i < argc - 1; i++) if (SCHEME_FALSEP((v = _scheme_apply(argv[i], 0, NULL)))) return v; return scheme_tail_apply(argv[argc - 1], 0, NULL); } } This @scheme[thunk-or] properly implements tail-recursion: if the final thunk is applied, then the result of @scheme[thunk-or] is the result of that application, so @cppi{scheme_tail_apply} is used for the final application. @; ---------------------------------------------------------------------- @section[#:tag "multiple"]{Multiple Values} A primitive procedure can return multiple values by returning the result of calling @cppi{scheme_values}. The functions @cppi{scheme_eval_compiled_multi}, @cppi{scheme_apply_multi}, @cppi{_scheme_eval_compiled_multi}, and @cppi{_scheme_apply_multi} potentially return multiple values; all other evaluation and applications procedures return a single value or raise an exception. Multiple return values are represented by the @cppi{scheme_multiple_values} ``value.'' This quasi-value has the type @cpp{Scheme_Object*}, but it is not a pointer or a fixnum. When the result of an evaluation or application is @cppi{scheme_multiple_values}, the number of actual values can be obtained as @cppi{scheme_multiple_count}, and the array of @cpp{Scheme_Object*} values as @cppi{scheme_multiple_array}. (Both of those identifiers are actually macros.) A garbage collection must not occur between the return of a @cppi{scheme_multiple_values} ``value'' and the receipt of the values through @cppi{scheme_multiple_count} @cppi{scheme_multiple_array}. Furthermore, if @cpp{scheme_multiple_array} is to be used across a potential garbage collection, then it must be specifically received by calling @cpp{scheme_detach_multiple_array}; otherwise, a garbage collection or further evaluation may change the content of the array. Otherwise, if any application or evaluation procedure is called, the @cpp{scheme_multiple_count} and @cpp{scheme_multiple_array} variables may be modified (but the array previously referenced by @cpp{scheme_multiple_array} is never re-used if @cpp{scheme_detatch_multiple_array} is called). The @cpp{scheme_multiple_count} and @cpp{scheme_multiple_array} variables only contain meaningful values when @cpp{scheme_multiple_values} is returned. @; ---------------------------------------------------------------------- @section{Evaluation Functions} @function[(Scheme_Object* scheme_eval [Scheme_Object* expr] [Scheme_Env* env])]{ Evaluates the (uncompiled) S-expression @var{expr} in the namespace @var{env}.} @function[(Scheme_Object* scheme_eval_compiled [Scheme_Object* obj] [Scheme_Env* env])]{ Evaluates the compiled expression @var{obj}, which was previously returned from @cpp{scheme_compile}, first linking to the namespace @var{env}.} @function[(Scheme_Object* scheme_eval_compiled_multi [Scheme_Object* obj] [Scheme_Env* env])]{ Evaluates the compiled expression @var{obj}, possibly returning multiple values (see @secref["multiple"]).} @function[(Scheme_Object* _scheme_eval_compiled [Scheme_Object* obj] [Scheme_Env* env])]{ Non-top-level version of @cpp{scheme_eval_compiled}. (See @secref["topleveleval"].)} @function[(Scheme_Object* _scheme_eval_compiled_multi [Scheme_Object* obj] [Scheme_Env* env])]{ Non-top-level version of @cpp{scheme_eval_compiled_multi}. (See @secref["topleveleval"].)} @function[(Scheme_Env* scheme_basic_env)]{ Creates the main namespace for an embedded PLT Scheme. This procedure must be called before other Scheme library function (except @cpp{scheme_make_param}). Extensions to Scheme cannot call this function. If it is called more than once, this function resets all threads (replacing the main thread), parameters, ports, namespaces, and finalizations.} @function[(Scheme_Object* scheme_make_namespace [int argc] [Scheme_Object** argv])]{ Creates and returns a new namespace. This values can be cast to @scheme[Scheme\_Env *]. It can also be installed in a parameterization using @cppi{scheme_set_param} with @cppi{MZCONFIG_ENV}. When PLT Scheme is embedded in an application, create the initial namespace with @cppi{scheme_basic_env} before calling this procedure to create new namespaces.} @function[(Scheme_Object* scheme_apply [Scheme_Object* f] [int c] [Scheme_Object** args])]{ Applies the procedure @var{f} to the given arguments.} @function[(Scheme_Object* scheme_apply_multi [Scheme_Object* f] [int c] [Scheme_Object** args])]{ Applies the procedure @var{f} to the given arguments, possibly returning multiple values (see @secref["multiple"]).} @function[(Scheme_Object* _scheme_apply [Scheme_Object* f] [int c] [Scheme_Object** args])]{ Non-top-level version of @cpp{scheme_apply}. (See @secref["topleveleval"].)} @function[(Scheme_Object* _scheme_apply_multi [Scheme_Object* f] [int c] [Scheme_Object** args])]{ Non-top-level version of @cpp{scheme_apply_multi}. (See @secref["topleveleval"].)} @function[(Scheme_Object* scheme_apply_to_list [Scheme_Object* f] [Scheme_Object* args])]{ Applies the procedure @var{f} to the list of arguments in @var{args}.} @function[(Scheme_Object* scheme_eval_string [char* str] [Scheme_Env* env])]{ Reads a single S-expression from @var{str} and evaluates it in the given namespace; the expression must return a single value, otherwise an exception is raised. The @var{str} argument is parsed as a UTF-8-encoded string of Unicode characters (so plain ASCII is fine).} @function[(Scheme_Object* scheme_eval_string_multi [char* str] [Scheme_Env* env])]{ Like @cpp{scheme_eval_string}, but returns @cpp{scheme_multiple_values} when the expression returns multiple values.} @function[(Scheme_Object* scheme_eval_string_all [char* str] [Scheme_Env* env] [int all])]{ Like @cpp{scheme_eval_string}, but if @var{all} is not @cpp{0}, then expressions are read and evaluated from @var{str} until the end of the string is reached.} @function[(Scheme_Object* scheme_tail_apply [Scheme_Object* f] [int n] [Scheme_Object** args])]{ Applies the procedure as a tail-call. Actually, this function just registers the given application to be invoked when control returns to the evaluation loop. (Hence, this function is only useful within a primitive procedure that is returning to its caller.)} @function[(Scheme_Object* scheme_tail_apply_no_copy [Scheme_Object* f] [int n] [Scheme_Object** args])]{ Like @cpp{scheme_tail_apply}, but the array @var{args} is not copied. Use this only when @var{args} has infinite extent and will not be used again, or when @var{args} will certainly not be used again until the called procedure has returned.} @function[(Scheme_Object* scheme_tail_apply_to_list [Scheme_Object* f] [Scheme_Object* l])]{ Applies the procedure as a tail-call.} @function[(Scheme_Object* scheme_compile [Scheme_Object* form] [Scheme_Env* env] [int writable])]{ Compiles the S-expression @var{form} in the given namespace. The returned value can be used with @cpp{scheme_eval_compiled} et al. Provide a non-zero value fo @var{writable} if the resulting compiled object will be marshalled via @scheme[write] instead of evaluated.} @function[(Scheme_Object* scheme_expand [Scheme_Object* form] [Scheme_Env* env])]{ Expands all macros in the S-expression @var{form} using the given namespace.} @function[(Scheme_Object* scheme_values [int n] [Scheme_Object** args])]{ Returns the given values together as multiple return values. Unless @var{n} is @cpp{1}, the result will always be @cpp{scheme_multiple_values}.} @function[(void scheme_detach_multiple_array [Scheme_Object** args])]{ Called to receive multiple-value results; see @secref["multiple"].}