sicp.io
5.5.2 · Compiling expressions

Source forms become instruction tags before execution begins.

Compile values, variables, quotation, assignment, conditionals, lambdas, and applications into an instruction language, then execute the result.

Guiding question

What source-language decisions disappear from the execution loop after compilation?

  • Compile every core expression category to explicit instruction data
  • Preserve left-to-right operator and operand order in calls
  • Represent compiled closures with parameters, code, and lexical environment
  • Mutate definitions and assignments through explicit environment operations
  • Select one compiled branch without revisiting source syntax
  • Execute compiled code with a separate stack machine

compile-expression performs every source classification. The result contains only literal, load, closure, define, set, discard, branch, and call instructions. A lambda stores already compiled body code with its parameters. A begin inserts discard between nonfinal forms, and an application places operator code before operand code before one call instruction.

run-code dispatches on compiled instruction tags after compile-expression has classified the source forms. A compiled procedure extends the lexical environment captured at closure construction and runs its body code on a fresh operand stack. This lesson VM executes global definition, captured local assignment, quotation, branching, closures, and primitive application through the listed instruction set.

SICP code10,895 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 first compiled program returns ((18 large 15) (literal define discard closure define discard load literal call define discard load load literal call set discard load load literal call branch) 22). The stateful closure returns ((12 15 5 ok) (literal define discard closure define discard load literal call define discard load load literal call load literal call load literal call) 21).

    Trace focus

    First inspect the code tags and confirm that no source-form tags remain. During execution, follow closure creation before make-adder or make-counter is called, the fresh call frame for each compiled application, the captured start record changing across counter calls, and the branch selecting exactly one nested code list.

    Try it yourself

    Change the program and compare the result.

    Add a recursive compiled procedure or a second nested closure. Predict the top-level code tags, then identify which procedure environment each load and set instruction must search.

    Show hint

    Definition installs the compiled closure in the shared global frame after the closure has captured that frame object, so later recursive lookup can find the installed name.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%