sicp-ex-5.36



<< Previous exercise (5.35) | Index | Next exercise (5.37) >>


meteorgan

  
  
  
 right to left, this is because in construct-arglist, compiler first reverse operand-code, then evaluate the parameters from left to right. 
 To change the order, we can first evaluate the operands from left to right to get the arglist from right to left, then reverse the arglist. 
  
 (define (construct-arglist operand-codes) 
   (let ((operand-codes 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 
           (tack-on-instruction-sequence 
             (preserving '(env) 
               code-to-get-last-arg 
               (code-to-get-rest-args 
                 (cdr operand-codes))) 
             (make-instruction-sequence '() '() 
               '((assign argl (op reverse) (reg argl)))))))))) 

donald

  
  
  
 ;;no need to reverse 
 (define (construct-arglist 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) 
                       ;;now use append instead of cons 
                       '((assign argl (op append) (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)))))) 

poly

By the way, there is a bug in the above solution.



    ;;now use append instead of cons
    '((assign argl (op append) (reg val) (reg argl)))))))
.......

the val should be included in the arglist, which means the code shoule be

    '((assign val (op list) (reg val))
      (assign argl (op append) (reg argl) (reg val)))))))
.....

codybartfast

I don't think there is any need to reverse argl.

If we don't reverse operand-codes (as above) we will evaluate arguments left-to-right (instead of right-to-left). This will then result in argl being in 'reverse' order. But we can leave it like this because argl is only used by extend-environment and apply-primitive-procedure and these already expect argl in 'reverse' order because of how the ec-evcaluator constructs argl.