Implement 5.38
parent
ce6ed4603b
commit
016d35bc87
|
@ -74,7 +74,7 @@ ev-appl-did-operator-no-restore
|
||||||
(display (car xs) port)
|
(display (car xs) port)
|
||||||
(display "\n" port)
|
(display "\n" port)
|
||||||
(write-list-to-port (cdr xs) 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))
|
(let* ((compile-result (compile code target linkage))
|
||||||
(assembly-insts (statements compile-result))
|
(assembly-insts (statements compile-result))
|
||||||
(port (open-output-file file-name)))
|
(port (open-output-file file-name)))
|
||||||
|
@ -391,13 +391,6 @@ ev-appl-did-operator-no-restore
|
||||||
|
|
||||||
(display "\nex-5.38 - optimize-procedure-application\n")
|
(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 (spread-arguments operand-list)
|
||||||
(define (compile-operands operand-list operand-number)
|
(define (compile-operands operand-list operand-number)
|
||||||
(cond
|
(cond
|
||||||
|
@ -414,33 +407,45 @@ ev-appl-did-operator-no-restore
|
||||||
(compile-operands (cdr operand-list) (+ operand-number 1))))
|
(compile-operands (cdr operand-list) (+ operand-number 1))))
|
||||||
(else
|
(else
|
||||||
(error "Only two arg registers supported -- SPREAD-ARGUMENTS"))))
|
(error "Only two arg registers supported -- SPREAD-ARGUMENTS"))))
|
||||||
|
|
||||||
(let ((operand-codes (compile-operands operand-list 1)))
|
(let ((operand-codes (compile-operands operand-list 1)))
|
||||||
operand-codes))
|
operand-codes))
|
||||||
|
|
||||||
(define (display-lines xs)
|
(define (primitive-procedure? exp)
|
||||||
(define (display-line x)
|
(define primitive-procedures '(= * - +))
|
||||||
(display x) (newline))
|
(and (pair? exp)
|
||||||
(map display-line xs))
|
(= (length exp) 3) ;; only support two args for now
|
||||||
|
(memq (car exp) primitive-procedures)
|
||||||
|
))
|
||||||
|
|
||||||
(display-lines (third (spread-arguments '(1 1))))
|
(define (compile-primitive-call op target linkage)
|
||||||
(newline)
|
(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
|
(compile-to-file
|
||||||
; generator that takes a combination with that operator, together with a target
|
'(define (factorial n)
|
||||||
; and a linkage descriptor, and produces code to spread the arguments into the
|
(if (= n 1)
|
||||||
; registers and then perform the operation targeted to the given target with
|
1
|
||||||
; the given linkage. You need only handle expressions with two operands. Make
|
(* (factorial (- n 1)) n)))
|
||||||
; compile dispatch to these code generators.
|
'val 'next "factorial-opt.sicp-asm")
|
||||||
|
|
||||||
; c. Try your new compiler on the factorial example. Compare the resulting
|
; c. The optimization saves 39 instructions
|
||||||
; code with the result produced without open coding.
|
; λ 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
|
(display "[answered]\n")
|
||||||
; 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 "\nex-5.39\n")
|
(display "\nex-5.39\n")
|
||||||
|
|
||||||
|
(display "\nex-5.40\n")
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
target
|
target
|
||||||
linkage))
|
linkage))
|
||||||
((cond? exp) (compile (cond->if exp) target linkage))
|
((cond? exp) (compile (cond->if exp) target linkage))
|
||||||
|
((primitive-procedure? exp)
|
||||||
|
(compile-primitive exp target linkage))
|
||||||
((application? exp)
|
((application? exp)
|
||||||
(compile-application exp target linkage))
|
(compile-application exp target linkage))
|
||||||
(else
|
(else
|
||||||
|
@ -46,6 +48,8 @@
|
||||||
(define (empty-instruction-sequence)
|
(define (empty-instruction-sequence)
|
||||||
(make-instruction-sequence '() '() '()))
|
(make-instruction-sequence '() '() '()))
|
||||||
|
|
||||||
|
;; Implemented in 5.38.
|
||||||
|
(define (primitive-procedure? exp) #f)
|
||||||
|
|
||||||
;;;SECTION 5.5.2
|
;;;SECTION 5.5.2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue