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
(begin(define(tagged-list?expressiontag)(and(pair?expression)(eq?(carexpression)tag)))(define(self-evaluating?expression)(or(number?expression)(string?expression)(boolean?expression)))(define(quoted?expression)(tagged-list?expression'quote))(define(assignment?expression)(tagged-list?expression'set!))(define(definition?expression)(tagged-list?expression'define))(define(if?expression)(tagged-list?expression'if))(define(lambda?expression)(tagged-list?expression'lambda))(define(begin?expression)(tagged-list?expression'begin))(define(definition-variableexpression)(if(symbol?(cadrexpression))(cadrexpression)(car(cadrexpression))))(define(definition-valueexpression)(if(symbol?(cadrexpression))(caddrexpression)(cons'lambda(cons(cdr(cadrexpression))(cddrexpression)))))(define(compile-sequenceexpressions)(cond((null?expressions)'((literalok)))((null?(cdrexpressions))(compile-expression(carexpressions)))(else(append(compile-expression(carexpressions))(cons'(discard)(compile-sequence(cdrexpressions)))))))(define(compile-operandsoperands)(if(null?operands)'()(append(compile-expression(caroperands))(compile-operands(cdroperands)))))(define(compile-expressionexpression)(cond((self-evaluating?expression)(list(list'literalexpression)))((symbol?expression)(list(list'loadexpression)))((quoted?expression)(list(list'literal(cadrexpression))))((assignment?expression)(append(compile-expression(caddrexpression))(list(list'set(cadrexpression)))))((definition?expression)(append(compile-expression(definition-valueexpression))(list(list'define(definition-variableexpression)))))((if?expression)(append(compile-expression(cadrexpression))(list(list'branch(compile-expression(caddrexpression))(compile-expression(cadddrexpression))))))((lambda?expression)(list(list'closure(cadrexpression)(compile-sequence(cddrexpression)))))((begin?expression)(compile-sequence(cdrexpression)))((pair?expression)(append(compile-expression(carexpression))(append(compile-operands(cdrexpression))(list(list'call(length(cdrexpression)))))))(else(error"unknown expression for compiler"expression))))(define(pair-bindingsvariablesvalues)(cond((and(null?variables)(null?values))'())((null?variables)(error"too many arguments"))((null?values)(error"too few arguments"))(else(cons(cons(carvariables)(carvalues))(pair-bindings(cdrvariables)(cdrvalues))))))(define(make-framevariablesvalues)(cons'*frame*(pair-bindingsvariablesvalues)))(define(frame-bindingsframe)(cdrframe))(define(extend-environmentvariablesvaluesenvironment)(cons(make-framevariablesvalues)environment))(define(lookup-variable-valuevariableenvironment)(if(null?environment)(error"unbound compiled variable"variable)(let((binding(assocvariable(frame-bindings(carenvironment)))))(ifbinding(cdrbinding)(lookup-variable-valuevariable(cdrenvironment))))))(define(define-variable!variablevalueenvironment)(let*((frame(carenvironment))(binding(assocvariable(frame-bindingsframe))))(ifbinding(set-cdr!bindingvalue)(set-cdr!frame(cons(consvariablevalue)(frame-bindingsframe)))))(list'definedvariable))(define(set-variable-value!variablevalueenvironment)(if(null?environment)(error"unbound compiled assignment"variable)(let((binding(assocvariable(frame-bindings(carenvironment)))))(ifbinding(begin(set-cdr!bindingvalue)(list'assignedvariable))(set-variable-value!variablevalue(cdrenvironment))))))(define(make-primitiveimplementation)(list'primitiveimplementation))(define(primitive?procedure)(tagged-list?procedure'primitive))(define(primitive-implementationprocedure)(cadrprocedure))(define(make-compiled-procedureparameterscodeenvironment)(list'compiledparameterscodeenvironment))(define(compiled-procedure?procedure)(tagged-list?procedure'compiled))(define(compiled-parametersprocedure)(cadrprocedure))(define(compiled-codeprocedure)(caddrprocedure))(define(compiled-environmentprocedure)(cadddrprocedure))(define(split-callstackcount)(define(loopremaining-stackremaining-countarguments)(if(=remaining-count0)(list(carremaining-stack)arguments(cdrremaining-stack))(loop(cdrremaining-stack)(-remaining-count1)(cons(carremaining-stack)arguments))))(loopstackcount'()))(define(run-codecodestackenvironment)(if(null?code)(liststackenvironment)(let*((instruction(carcode))(tag(carinstruction)))(cond((eq?tag'literal)(run-code(cdrcode)(cons(cadrinstruction)stack)environment))((eq?tag'load)(run-code(cdrcode)(cons(lookup-variable-value(cadrinstruction)environment)stack)environment))((eq?tag'closure)(run-code(cdrcode)(cons(make-compiled-procedure(cadrinstruction)(caddrinstruction)environment)stack)environment))((eq?tag'define)(let((result(define-variable!(cadrinstruction)(carstack)environment)))(run-code(cdrcode)(consresult(cdrstack))environment)))((eq?tag'set)(let((result(set-variable-value!(cadrinstruction)(carstack)environment)))(run-code(cdrcode)(consresult(cdrstack))environment)))((eq?tag'discard)(run-code(cdrcode)(cdrstack)environment))((eq?tag'branch)(let*((selected(if(carstack)(cadrinstruction)(caddrinstruction)))(branch-state(run-codeselected(cdrstack)environment)))(run-code(cdrcode)(carbranch-state)(cadrbranch-state))))((eq?tag'call)(let*((parts(split-callstack(cadrinstruction)))(procedure(carparts))(arguments(cadrparts))(caller-stack(caddrparts)))(if(primitive?procedure)(run-code(cdrcode)(cons(apply(primitive-implementationprocedure)arguments)caller-stack)environment)(if(compiled-procedure?procedure)(let*((call-environment(extend-environment(compiled-parametersprocedure)arguments(compiled-environmentprocedure)))(call-state(run-code(compiled-codeprocedure)'()call-environment))(value(car(carcall-state))))(run-code(cdrcode)(consvaluecaller-stack)environment))(error"not a compiled procedure"procedure)))))(else(error"unknown compiled instruction"instruction))))))(define(make-global-environment)(list(cons'*frame*(list(cons'+(make-primitive+))(cons'-(make-primitive-))(cons'*(make-primitive*))(cons'/(make-primitive/))(cons'=(make-primitive=))(cons'<(make-primitive<))(cons'>(make-primitive>))(cons'list(make-primitivelist))(cons'cons(make-primitivecons))(cons'car(make-primitivecar))(cons'cdr(make-primitivecdr))(cons'null?(make-primitivenull?))))))(define(compile-and-runexpression)(let*((code(compile-expressionexpression))(environment(make-global-environment))(state(run-codecode'()environment)))(list(car(carstate))codeenvironment)))(definecombination'(-(record(quoteleft)20)(record(quoteright)3)))(defineprogram'(begin(defineobservations(quote()))(define(append-listleftright)(if(null?left)right(cons(carleft)(append-list(cdrleft)right))))(define(recordlabelvalue)(begin(set!observations(append-listobservations(listlabel)))value))(defineresult(-(record(quoteleft)20)(record(quoteright)3)))(listresultobservations)))(defineresult(compile-and-runprogram))(list(carresult)(mapcar(compile-expressioncombination))))
Examples
Result—
Output
—
Value
—
Diagnostic
—
Execution trace0 / 0 events
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.