Exercise 5.36. What order of evaluation does our compiler produce for operands of a combination? Is it left-to-right, right-to-left, or some other order? Where in the compiler is this order determined? Modify the compiler so that it produces some other order of evaluation. (See the discussion of order of evaluation for the explicit-control evaluator in section 5.4.1.) How does changing the order of operand evaluation affect the efficiency of the code that constructs the argument list? ———————————————————————————————————————————————————————————————————————— They are evaluated right-to-left. The reason is in construct-arglist: (define (construct-arglist operand-codes) (let ((operand-codes (reverse operand-codes))) (if (null? operand-codes) (make-instruction-sequence '() '(argl) '((assign argl (const ())))) (let ((code-to-get-last-arg (append-instruction-sequences (car operand-codes) (make-instruction-sequence '(val) '(argl) '((assign argl (op list) (reg val))))))) (if (null? (cdr operand-codes)) code-to-get-last-arg (preserving '(env) code-to-get-last-arg (code-to-get-rest-args (cdr operand-codes)))))))) (define (code-to-get-rest-args operand-codes) (let ((code-for-next-arg (preserving '(argl) (car operand-codes) (make-instruction-sequence '(val argl) '(argl) '((assign argl (op cons) (reg val) (reg argl))))))) (if (null? (cdr operand-codes)) code-for-next-arg (preserving '(env) code-for-next-arg (code-to-get-rest-args (cdr operand-codes)))))) This code treats the no-operand case and the last operand specially. To evaluate operands left-to-right, first we can make a simple change to construct-arglist: we simply remove the (reverse operand-codes) call, and rename code-to-get-last-arg as code-to-get-first-arg: (define (construct-arglist operand-codes) (if (null? operand-codes) ;; don't reverse the operands (make-instruction-sequence '() '(argl) '((assign argl (const ())))) (let ((code-to-get-first-arg ;; changed variable name (append-instruction-sequences (car operand-codes) -- the rest as above, with the variable name change -- This gives code that evaluates the operands in source order, but then uses cons each time to compose argl, so argl will end up with the values in reverse order. One way to fix this is to make the machine use append! to append each value onto argl, but this is less efficient, and if this was a hardware design, would perhaps complicate the design. A more clever way would be to compile every compiled procedure, and define every primitive procedure, to expect argl in the reverse order of its formal parameters. This would work only for procedures that take a fixed number of parameters.