Implement 5.38
parent
ce6ed4603b
commit
016d35bc87
|
@ -74,7 +74,7 @@ ev-appl-did-operator-no-restore
|
|||
(display (car xs) port)
|
||||
(display "\n" port)
|
||||
(write-list-to-port (cdr xs) port))))
|
||||
(if #f ; #t means write to file; #f means don't write to file
|
||||
(if #t ; #t means write to file; #f means don't write to file
|
||||
(let* ((compile-result (compile code target linkage))
|
||||
(assembly-insts (statements compile-result))
|
||||
(port (open-output-file file-name)))
|
||||
|
@ -391,13 +391,6 @@ ev-appl-did-operator-no-restore
|
|||
|
||||
(display "\nex-5.38 - optimize-procedure-application\n")
|
||||
|
||||
; a. The open-coded primitives, unlike the special forms, all need their
|
||||
; operands evaluated. Write a code generator spread-arguments for use by all
|
||||
; the open-coding code generators. Spread-arguments should take an operand list
|
||||
; and compile the given operands targeted to successive argument registers.
|
||||
; Note that an operand may contain a call to an open-coded primitive, so
|
||||
; argument registers will have to be preserved during operand evaluation.
|
||||
|
||||
(define (spread-arguments operand-list)
|
||||
(define (compile-operands operand-list operand-number)
|
||||
(cond
|
||||
|
@ -414,33 +407,45 @@ ev-appl-did-operator-no-restore
|
|||
(compile-operands (cdr operand-list) (+ operand-number 1))))
|
||||
(else
|
||||
(error "Only two arg registers supported -- SPREAD-ARGUMENTS"))))
|
||||
|
||||
(let ((operand-codes (compile-operands operand-list 1)))
|
||||
operand-codes))
|
||||
|
||||
(define (display-lines xs)
|
||||
(define (display-line x)
|
||||
(display x) (newline))
|
||||
(map display-line xs))
|
||||
(define (primitive-procedure? exp)
|
||||
(define primitive-procedures '(= * - +))
|
||||
(and (pair? exp)
|
||||
(= (length exp) 3) ;; only support two args for now
|
||||
(memq (car exp) primitive-procedures)
|
||||
))
|
||||
|
||||
(display-lines (third (spread-arguments '(1 1))))
|
||||
(newline)
|
||||
(define (compile-primitive-call op target linkage)
|
||||
(end-with-linkage linkage
|
||||
(make-instruction-sequence
|
||||
'(arg1 arg2)
|
||||
`(,target)
|
||||
`((assign ,target (op ,op) (reg arg1) (reg arg2))))))
|
||||
|
||||
(display "b. CONTINUE HERE\n")
|
||||
(define (compile-primitive exp target linkage)
|
||||
(let ((proc-code (compile-primitive-call (operator exp) target linkage))
|
||||
(operand-codes (spread-arguments (operands exp))))
|
||||
(preserving '(env continue)
|
||||
operand-codes
|
||||
proc-code)))
|
||||
|
||||
; b. For each of the primitive procedures =, *, -, and +, write a code
|
||||
; generator that takes a combination with that operator, together with a target
|
||||
; and a linkage descriptor, and produces code to spread the arguments into the
|
||||
; registers and then perform the operation targeted to the given target with
|
||||
; the given linkage. You need only handle expressions with two operands. Make
|
||||
; compile dispatch to these code generators.
|
||||
(compile-to-file
|
||||
'(define (factorial n)
|
||||
(if (= n 1)
|
||||
1
|
||||
(* (factorial (- n 1)) n)))
|
||||
'val 'next "factorial-opt.sicp-asm")
|
||||
|
||||
; c. Try your new compiler on the factorial example. Compare the resulting
|
||||
; code with the result produced without open coding.
|
||||
; c. The optimization saves 39 instructions
|
||||
; λ symposium sicp → λ git master* → wc -l factorial.sicp-asm factorial-opt.sicp-asm
|
||||
; 79 factorial.sicp-asm
|
||||
; 40 factorial-opt.sicp-asm
|
||||
; 119 total
|
||||
|
||||
; d. Extend your code generators for + and * so that they can handle
|
||||
; expressions with arbitrary numbers of operands. An expression with more than
|
||||
; two operands will have to be compiled into a sequence of operations, each
|
||||
; with only two inputs.
|
||||
(display "[answered]\n")
|
||||
|
||||
(display "\nex-5.39\n")
|
||||
|
||||
(display "\nex-5.40\n")
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
target
|
||||
linkage))
|
||||
((cond? exp) (compile (cond->if exp) target linkage))
|
||||
((primitive-procedure? exp)
|
||||
(compile-primitive exp target linkage))
|
||||
((application? exp)
|
||||
(compile-application exp target linkage))
|
||||
(else
|
||||
|
@ -46,6 +48,8 @@
|
|||
(define (empty-instruction-sequence)
|
||||
(make-instruction-sequence '() '() '()))
|
||||
|
||||
;; Implemented in 5.38.
|
||||
(define (primitive-procedure? exp) #f)
|
||||
|
||||
;;;SECTION 5.5.2
|
||||
|
||||
|
|
Loading…
Reference in New Issue