sicp.io
5.5.3 · Compiling combinations

Compile the operator first, preserve argument order, cross one apply boundary.

Inspect the exact instruction order for a nested combination and route primitive, interpreted, and compiled procedures through one application convention.

Guiding question

Which ordering and representation contracts must compiled application code preserve?

  • Compile an operator before its operand expressions
  • Compile operands from left to right while preserving argument order
  • Emit one call instruction after the complete combination state is ready
  • Observe source-order effects without relying on an unspecified schedule
  • Share one lexical environment and argument convention across procedure representations
  • Keep primitive, interpreted, and compiled dispatch visibly distinct

The lesson compiler emits load for the subtraction operator, then the entire code for the left record call, then the entire code for the right record call, and finally one outer call. The stateful record procedure appends labels to observations, so the returned (left right) list confirms that execution follows the emitted source order. The subtraction value also confirms the argument order.

The second program broadens the call boundary. Evaluator code calls a compiled add-three closure, and compiled code calls an interpreted double procedure. Both paths pass an ordered argument list through apply-any, while dispatch-log retains the actual primitive, interpreted, and compiled tags. This records the calling convention used by the lesson.

SICP code11,199 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 ordering program returns ((17 (left right)) (load load literal literal call load literal literal call call)). The interface program returns ((evaluator-to-compiled 8 (compiled primitive)) (compiled-to-evaluator 14 (interpreted primitive) #t) (representations #t #t)).

    Trace focus

    In the first run, follow the outer operator load, every instruction of the left record call, every instruction of the right record call, and only then the subtraction call. In the interface run, separate argument preparation from apply-any representation dispatch and confirm that each body receives arguments in its declared parameter order.

    Try it yourself

    Change the program and compare the result.

    Compile a three-operand list call whose operands each record a distinct label, then wrap one operand in a compiled closure call. Predict both the instruction tags and the chronological dispatch log.

    Show hint

    Finish the operator code first. Each operand contributes its complete code in source order, while the final call consumes the resulting ordered argument list.

    Complete this lesson

    0 of 23 lessons complete in this chapter0%