sicp.io
4.1.7 · Running the evaluator as a program

The evaluator can read a finite program and preserve its environment.

An explicit eval/apply system evaluates quoted top-level forms in one mutable global environment and returns a transcript of definitions and values.

Guiding question

What turns a collection of evaluator procedures into a program that can run a sequence of user forms?

  • Separate host Lispex execution from the guest expressions represented as data
  • Dispatch self-evaluating values, variables, special forms, and applications
  • Apply host primitive procedures and represented compound procedures
  • Preserve definitions and assignments in one explicit global environment
  • Observe lexical closure capture across later global changes
  • Report a complete or truncated finite top-level driver run
  • Keep the top-level form budget distinct from work inside one form

The evaluator represents environments as lists of mutable frames. A guest variable lookup searches those frames; define changes the first frame; set! searches for an existing binding and changes that record. A guest lambda becomes a compound-procedure record containing parameters, body expressions, and the environment where the lambda was evaluated. apply-procedure either applies a host primitive or evaluates a compound body in a new frame.

run-program is the driver. It receives quoted top-level forms, one explicit global environment, and a form budget. Every completed form contributes one transcript value while definitions and assignments remain visible to later forms. The full run defines square, make-adder, add-five, and base; add-five keeps the local x value 5 even after the global base changes. The second run stops after five forms and reports four forms still pending. This form budget does not bound recursion or work inside a single form; the packaged browser runtime still supplies the lower-level execution limits.

SICP code7,837 of 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Execution trace0 / 0 events
    Programs run in the browser with their result and execution trace.
    Expected result

    The complete run returns (complete ((defined square) (defined make-adder) (defined add-five) (defined base) 49 12 (assigned base) 81 6) 0). The five-form-budget run returns (truncated ((defined square) (defined make-adder) (defined add-five) (defined base) 49) 4).

    Trace focus

    Separate host calls that implement evaluate and apply-procedure from guest expressions stored in guest-program. Follow global frame mutation across define and set!, the new frame created for each compound application, and the environment captured by add-five. In run-program, one budget unit is spent only after one top-level form returns; this counter does not measure recursive guest work inside that form.

    Try it yourself

    Change the program and compare the result.

    Add a guest definition (define (twice procedure value) (procedure (procedure value))) and evaluate (twice add-five 1). Predict the new transcript value and the remaining-form count when the form budget stays at 5.

    Show hint

    The complete run applies add-five twice, so the guest result is 11. In the five-form-budget run, inserting another form after the existing definitions changes which expression becomes the fifth completed form.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%