The overall specification of how the interpreter evaluates a combination function application remains the same as when we first introduced it in section 1.1.4:
| Original | Python | |
| Before applying these rules, we need to say in which environment the statements of a program are evaluated. It is not the built-in environment of section 3.2: that frame is reserved for Python's built-in functions and values, and a program never adds bindings to it. Instead, the interpreter evaluates a program in a global environment, which consists of a single global frame whose enclosing environment is the built-in environment. Every definition and assignment at the top level of a program adds or changes a binding in the global frame, whereas the built-in frame supplies the names that the program does not define itself. Looking up print in the global environment therefore finds no binding in the global frame and proceeds to the built-in frame, while a name defined by the program is found in the global frame itself. |
In the environment model of evaluation, a procedure function is always a pair consisting of some code and a pointer to an environment. Procedures are created in one way only: by evaluating a lambda expression. Functions are created in two ways: by evaluating a function definition or a lambda expression. This produces a procedure In both cases, the result is a function whose code is obtained from the text of the lambda expression program text and whose environment is the environment in which the lambda function definition or lambda expression was evaluated to produce the procedure. function. For example, consider the procedure definition function definition
| Original | Python |
| (define (square x) (* x x)) | def square(x): return x * x |
Figure 3.3 Figure 3.4 shows the result of evaluating this define expression. function definition. The procedure function object is a pair whose code specifies that the procedure function has one formal parameter, namely x, and a procedure function body (* x x). return x * x. The environment part of the procedure function is a pointer to the global environment, since that is the environment in which the lambda lambda expression was evaluated to produce the procedure. function. A new binding, which associates the procedure function object with the symbol name square, has been added to the global frame.
| Original | Python | |
| In general, define creates definitions by adding bindings to frames. |
| Original | Python | |
|
Figure 3.3
Environment structure produced by evaluating
(define (square x) (* x x)) in the global
environment.
|
Figure 3.4
Environment structure produced by evaluating
def square(x): return x * x
in the global environment.
|
Now that we have seen how procedures functions are created, we can describe how procedures functions are applied. So far, the environment model specifies: To apply a Here is the first version of a rule for applying a procedure function to arguments,: create a new environment containing a frame that binds the parameters to the values of the arguments. The enclosing environment of this frame is the environment specified by the procedure. function. Now, within Within this new environment, evaluate the procedure function body. (We will refine this in section 3.2.3.)
To show how this rule is followed, figure 3.5 figure 3.6 illustrates the environment structure created by evaluating the expression (square 5) square(5) in the global environment, where square is the procedure function generated in figure 3.3. figure 3.4. Applying the procedure function results in the creation of a new environment, labeled E1 in the figure, that begins with a frame in which x, the formal parameter for the procedure, function, is bound to the argument 5. The pointer leading upward from this frame shows that the frame's enclosing environment is the global environment. The global environment is chosen here, because this is the environment that is indicated as part of the square procedure function object. Within E1, we evaluate the body of the procedure, function, (* x x). return x * x. Since the value of x in E1 is 5, the result is (* 5 5), 5 * 5, or 25.
| Original | Python | |
|
Figure 3.5
Environment created by evaluating
(square 5) in the global environment.
|
Figure 3.6
Environment created by evaluating
square(5)
in the global environment.
|
The environment model of procedure function application can be summarized by two rules:
| Original | Python | |
| We also specify that defining a symbol using define creates a binding in the current environment frame and assigns to the symbol the indicated value.[3] |
| Original | Python | |
| Finally, we specify the behavior of set!, the operation that forced us to introduce the environment model in the first place. Evaluating the expression (set! ) | Finally, we specify the behavior of assignment (declaration assignment or reassignment). It was reassignment that forced us to introduce the environment model in the first place. Evaluating the assignment $name$ = $value$ |
| Original | Python | |
| , then set! signals an error. | and the environment is the global environment, the assignment adds a binding to the global environment. If the variable is unbound in the environment and the environment is not the global environment, then the assignment signals an error. |
These evaluation rules, though considerably more complex than the substitution model, are still reasonably straightforward. Moreover, the evaluation model, though abstract, provides a correct description of how the interpreter evaluates expressions. In chapter we shall see how this model can serve as a blueprint for implementing a working interpreter. The following sections elaborate the details of the model by analyzing some illustrative programs.