@c This file is part of the MIT/GNU Scheme Reference Manual.
@c $Id: environments.texi,v 1.4 2008/01/30 20:06:11 cph Exp $

@c Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
@c     1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
@c     2005, 2006, 2007, 2008 Massachusetts Institute of Technology
@c See file scheme.texinfo for copying conditions.

@node Environments, Input/Output, Procedures, Top
@chapter Environments

@menu
* Environment Operations::      
* Environment Variables::       
* REPL Environment::            
* Top-level Environments::      
@end menu

@node Environment Operations, Environment Variables, Environments, Environments
@section Environment Operations

Environments are first-class objects in MIT/GNU Scheme.  An environment
consists of some bindings and possibly a parent environment, from which
other bindings are inherited.  The operations in this section reveal the
frame-like structure of environments by permitting you to examine the
bindings of a particular environment separately from those of its
parent.

@cindex variable binding
@cindex binding, variable
@cindex unassigned binding
@cindex binding, unassigned
@findex condition-type:unassigned-variable
There are several types of bindings that can occur in an environment.
The most common is the simple variable binding, which associates a value
(any Scheme object) with an identifier (a symbol).  A variable binding
can also be @dfn{unassigned}, which means that it has no value.  An
unassigned variable is bound, in that is will shadow other bindings of
the same name in ancestor environments, but a reference to that variable
will signal an error of type @code{condition-type:unassigned-variable}.
An unassigned variable can be @dfn{assigned} (using @code{set!} or
@code{environment-assign!}) to give it a value.

@cindex keyword binding
@cindex syntactic keyword binding
@cindex binding, syntactic keyword
@findex condition-type:macro-binding
In addition to variable bindings, an environment can also have
@dfn{keyword bindings}.  A keyword binding associates a syntactic
keyword (usually a macro transformer) with an identifier.  Keyword
bindings are special in that they are considered ``bound'', but ordinary
variable references don't work on them.  So an attempt to reference or
assign a keyword binding results in an error of type
@code{condition-type:macro-binding}.  However, keyword bindings can be
redefined using @code{define} or @code{environment-define}.

@deffn procedure environment? object
@cindex type predicate, for environment
Returns @code{#t} if @var{object} is an environment; otherwise returns
@code{#f}.
@end deffn

@deffn procedure environment-has-parent? environment
Returns @code{#t} if @var{environment} has a parent environment;
otherwise returns @code{#f}.
@end deffn

@deffn procedure environment-parent environment
Returns the parent environment of @var{environment}.  It is an error if
@var{environment} has no parent.
@end deffn

@deffn procedure environment-bound-names environment
Returns a newly allocated list of the names (symbols) that are bound by
@var{environment}.  This does not include the names that are bound by
the parent environment of @var{environment}.  It does include names that
are unassigned or keywords in @var{environment}.
@end deffn

@deffn procedure environment-macro-names environment
Returns a newly allocated list of the names (symbols) that are bound to
syntactic keywords in @var{environment}.
@end deffn

@deffn procedure environment-bindings environment
Returns a newly allocated list of the bindings of @var{environment};
does not include the bindings of the parent environment.  Each element
of this list takes one of two forms: @code{(@var{symbol})} indicates
that @var{symbol} is bound but unassigned, while @code{(@var{symbol}
@var{object})} indicates that @var{symbol} is bound, and its value is
@var{object}.
@end deffn

@deffn procedure environment-reference-type environment symbol
Returns a symbol describing the @dfn{reference type} of @var{symbol} in
@var{environment} or one of its ancestor environments.  The result is
one of the following:

@table @code
@item normal
means @var{symbol} is a variable binding with a normal value.

@item unassigned
means @var{symbol} is a variable binding with no value.

@item macro
means @var{symbol} is a keyword binding.

@item unbound
means @var{symbol} has no associated binding.
@end table
@end deffn

@deffn procedure environment-bound? environment symbol
Returns @code{#t} if @var{symbol} is bound in @var{environment} or one
of its ancestor environments; otherwise returns @code{#f}.  This is
equivalent to

@example
(not (eq? 'unbound
          (environment-reference-type @var{environment} @var{symbol})))
@end example
@end deffn

@deffn procedure environment-assigned? environment symbol
Returns @code{#t} if @var{symbol} is bound in @var{environment} or one
of its ancestor environments, and has a normal value.  Returns @code{#f}
if it is bound but unassigned.  Signals an error if it is unbound or is
bound to a keyword.
@end deffn

@deffn procedure environment-lookup environment symbol
@var{Symbol} must be bound to a normal value in @var{environment} or one
of its ancestor environments.  Returns the value to which it is bound.
Signals an error if unbound, unassigned, or a keyword.
@end deffn

@deffn procedure environment-lookup-macro environment symbol
If @var{symbol} is a keyword binding in @var{environment} or one of its
ancestor environments, returns the value of the binding.  Otherwise,
returns @code{#f}.  Does not signal any errors other than argument-type
errors.
@end deffn

@deffn procedure environment-assignable? environment symbol
@var{Symbol} must be bound in @var{environment} or one of its ancestor
environments.  Returns @code{#t} if the binding may be modified by side
effect.
@end deffn

@deffn procedure environment-assign! environment symbol object
@var{Symbol} must be bound in @var{environment} or one of its ancestor
environments, and must be assignable.  Modifies the binding to have
@var{object} as its value, and returns an unspecified result.
@end deffn

@deffn procedure environment-definable? environment symbol
Returns @code{#t} if @var{symbol} is definable in @var{environment}, and
@code{#f} otherwise.  At present, this is false for environments
generated by application of compiled procedures, and true for all other
environments.
@end deffn

@deffn procedure environment-define environment symbol object
Defines @var{symbol} to be bound to @var{object} in @var{environment},
and returns an unspecified value.  Signals an error if @var{symbol}
isn't definable in @var{environment}.
@end deffn

@deffn procedure environment-define-macro environment symbol transformer
Defines @var{symbol} to be a keyword bound to @var{transformer} in
@var{environment}, and returns an unspecified value.  Signals an error
if @var{symbol} isn't definable in @var{environment}.  The type of
@var{transformer} is defined by the syntax engine and is not checked by
this procedure.  If the type is incorrect this will subsequently signal
an error during syntax expansion.
@end deffn

@deffn procedure eval expression environment
@cindex s-expression
@cindex evaluation, of s-expression
Evaluates @var{expression}, a list-structure representation (sometimes
called s-expression representation) of a Scheme expression, in
@var{environment}.  You rarely need @code{eval} in ordinary programs; it
is useful mostly for evaluating expressions that have been created ``on
the fly'' by a program.  @code{eval} is relatively expensive because it
must convert @var{expression} to an internal form before it is executed.

@example
@group
(define foo (list '+ 1 2))
(eval foo (the-environment))            @result{}  3
@end group
@end example
@end deffn

@node Environment Variables, REPL Environment, Environment Operations, Environments
@section Environment Variables

@findex define
The @code{user-initial-environment} is where the top-level
read-eval-print (@acronym{REP}) loop evaluates expressions and binds
definitions.  It is a child of @code{system-global-environment}, which
is where all of the Scheme system definitions are bound.  All of the
bindings in @code{system-global-environment} are available when the
current environment is @code{user-initial-environment}.  However, any
new bindings that you create in the @acronym{REP} loop (with
@code{define} forms or by loading files containing @code{define} forms)
occur in @code{user-initial-environment}.

@defvr variable system-global-environment
The variable @code{system-global-environment} is bound to the
distinguished environment that's the ancestor of most other environments
(except for those created by @code{make-root-top-level-environment}).
It is the parent environment of @code{user-initial-environment}.
Primitives, system procedures, and most syntactic keywords are bound
(and sometimes closed) in this environment.
@end defvr

@defvr variable user-initial-environment
The variable @code{user-initial-environment} is bound to the default
environment in which typed expressions are evaluated by the top-level
@acronym{REP} loop.

Although all bindings in @code{system-global-environment} are visible to
the @acronym{REP} loop, definitions that are typed at, or loaded by, the
@acronym{REP} loop occur in the @code{user-initial-environment}.  This
is partly a safety measure: if you enter a definition that happens to
have the same name as a critical system procedure, your definition will
be visible only to the procedures you define in the
@code{user-initial-environment}; the MIT/GNU Scheme system procedures, which
are defined in @code{system-global-environment}, will continue to see
the original definition.
@end defvr

@node REPL Environment, Top-level Environments, Environment Variables, Environments
@section REPL Environment

@deffn procedure nearest-repl/environment
@findex user-initial-environment
Returns the current @acronym{REP} loop environment (i.e.@: the current
environment of the closest enclosing @acronym{REP} loop).  When Scheme
first starts up, this is the same as @code{user-initial-environment}.
@end deffn

@deffn procedure ge environment
Changes the current @acronym{REP} loop environment to @var{environment}.
@var{Environment} can be either an environment or a procedure object.
If it's a procedure, the environment in which that procedure was closed
is the new environment.
@end deffn

@node Top-level Environments,  , REPL Environment, Environments
@section Top-level Environments

@cindex top-level environment
@cindex interpreter environment
@cindex environment, top-level
@cindex environment, interpreter
The operations in this section manipulate @dfn{top-level environments},
as opposed to environments created by the application of procedures.
For historical reasons, top-level environments are referred to as
@dfn{interpreter environments}.

@deffn {special form} the-environment
@cindex current environment
@cindex environment, current
Returns the current environment.  This form may only be evaluated in a
top-level environment.  An error is signalled if it appears elsewhere.
@end deffn

@deffn procedure top-level-environment? object
@deffnx procedure interpreter-environment? object
@cindex type predicate, for top-level environment
Returns @code{#t} if @var{object} is an top-level environment; otherwise
returns @code{#f}.

@code{interpreter-environment?} is an alias for
@code{top-level-environment?}.
@end deffn

@deffn procedure extend-top-level-environment environment [names [values]]
@deffnx procedure make-top-level-environment [names [values]]
@deffnx procedure make-root-top-level-environment [names [values]]
Returns a newly allocated top-level environment.
@code{extend-top-level-environment} creates an environment that has
parent @var{environment}, @code{make-top-level-environment} creates an
environment that has parent @code{system-global-environment}, and
@code{make-root-top-level-environment} creates an environment that has
no parent.

The optional arguments @var{names} and @var{values} are used to specify
initial bindings in the new environment.  If specified, @var{names} must
be a list of symbols, and @var{values} must be a list of objects.  If
only @var{names} is specified, each name in @var{names} will be bound in
the environment, but unassigned.  If @var{names} and @var{values} are
both specified, they must be the same length, and each name in
@var{names} will be bound to the corresponding value in @var{values}.
If neither @var{names} nor @var{values} is specified, the environment
will have no initial bindings.
@end deffn

@deffn procedure link-variables environment1 symbol1 environment2 symbol2
Defines @var{symbol1} in @var{environment1} to have the same binding as
@var{symbol2} in @var{environment2}, and returns an unspecified value.
Prior to the call, @var{symbol2} must be bound in @var{environment2},
but the type of binding is irrelevant; it may be a normal binding, an
unassigned binding, or a keyword binding.  Signals an error if
@var{symbol1} isn't definable in @var{environment1}, or if @var{symbol2}
is unbound in @var{environment2}.

By ``the same binding'', we mean that the value cell is shared between
the two environments.  If a value is assigned to @var{symbol1} in
@var{environment1}, a subsequent reference to @var{symbol2} in
@var{environment2} will see that value, and vice versa.
@end deffn

@deffn procedure unbind-variable environment symbol
If @var{symbol} is bound in @var{environment} or one of its ancestor
environments, removes the binding, so that subsequent accesses to that
symbol behave as if the binding never existed.  Returns @code{#t} if there
was a binding prior to the call, and @code{#f} if there wasn't.
@end deffn
