Implement 5.42

main
Felix Martin 2021-04-23 21:29:05 -04:00
parent 54bc6725f3
commit ff4fa9e844
2 changed files with 74 additions and 37 deletions

View File

@ -73,28 +73,30 @@
(define (empty-compile-time-env) '()) (define (empty-compile-time-env) '())
(define (extend-compile-time-env parameters base-env) (define (extend-compile-time-env parameters base-env)
(display base-env) (newline)
(display parameters) (newline)
(cons parameters base-env)) (cons parameters base-env))
(compile-to-file (display "[done]\n")
'(let ((x 3) (y 4))
(lambda (a b c d e)
(let ((y (* a b x))
(z (+ c d x)))
(* x y z))))
'val 'next "f-lex-adr.scm")
(display "\nex-5.41 - find-variable\n") (display "\nex-5.41 - find-variable\n")
; Exercise 5.41. Write a procedure find-variable that takes as arguments a (define (find-variable var env)
; variable and a compile-time environment and returns the lexical address of (define (get-index frame current-index)
; the variable with respect to that environment. For example, in the program (cond
; fragment that is shown above, the compile-time environment during the ((null? frame) (error "var not found -- FIND-VARIABLE"))
; compilation of expression <e1> is ((y z) (a b c d e) (x y)). Find-variable ((eq? (car frame) var) current-index)
; should produce (else (get-index (cdr frame) (+ current-index 1)))))
(define (find-env i frames)
(define (find-variable var env) '9) (cond
((null? frames) 'not-found)
((memq var (car frames)) (cons i (car frames)))
(else (find-env (+ i 1) (cdr frames)))))
(let ((find-env-result (find-env 0 env)))
(if (eq? find-env-result 'not-found)
'not-found
(let* ((frame-number (car find-env-result))
(frame (cdr find-env-result))
(index-number (get-index frame 0)))
(make-address frame-number index-number)))))
(assert (find-variable 'c '((y z) (a b c d e) (x y))) (assert (find-variable 'c '((y z) (a b c d e) (x y)))
(make-address 1 2)) (make-address 1 2))
@ -105,6 +107,30 @@
(assert (find-variable 'w '((y z) (a b c d e) (x y))) (assert (find-variable 'w '((y z) (a b c d e) (x y)))
'not-found) 'not-found)
(display "\nex-5.42\n") (display "\nex-5.42 - compile-lexical-addressing\n")
; (display "\nex-5.43\n")
(compile-to-file
'(let ((x 3) (y 4))
(lambda (a b c d e)
(let ((y (* a b x))
(z (+ c d x)))
(set! y 3)
(* x y z))))
'val 'next "f-lex-adr.scm")
(display "[done]\n")
(display "\nex-5.43 - scan-out-defines\n")
; Exercise 5.43. We argued in section 4.1.6 that internal definitions for
; block structure should not be considered ``real'' defines. Rather, a
; procedure body should be interpreted as if the internal variables being
; defined were installed as ordinary lambda variables initialized to their
; correct values using set!. Section 4.1.6 and exercise 4.16 showed how to
; modify the metacircular interpreter to accomplish this by scanning out
; internal definitions. Modify the compiler to perform the same transformation
; before it compiles a procedure body.
(display "\nex-5.44\n")

View File

@ -88,26 +88,37 @@
`((assign ,target (const ,(text-of-quotation exp))))))) `((assign ,target (const ,(text-of-quotation exp)))))))
(define (compile-variable exp ct-env target linkage) (define (compile-variable exp ct-env target linkage)
(end-with-linkage linkage (let ((adr (find-variable exp ct-env)))
(make-instruction-sequence '(env) (list target) (if (eq? adr 'not-found)
`((assign ,target (end-with-linkage linkage
(op lookup-variable-value) (make-instruction-sequence '(env) (list target 'env)
(const ,exp) `((assign env (op get-global-environment) (reg env))
(reg env)))))) (assign ,target
(op lookup-variable-value)
(const ,exp)
(reg env)))))
(end-with-linkage linkage
(make-instruction-sequence '(env) (list target)
`((assign ,target
(op lexical-address-lookup)
(const ,adr)
(reg env))))))))
(define (compile-assignment exp ct-env target linkage) (define (compile-assignment exp ct-env target linkage)
(let ((var (assignment-variable exp)) (let* ((var (assignment-variable exp))
(get-value-code (get-value-code (compile (assignment-value exp) ct-env 'val 'next))
(compile (assignment-value exp) 'val 'next))) (adr (find-variable var ct-env)))
(end-with-linkage linkage (if (eq? adr 'not-found)
(preserving '(env) (error "var not found -- compile-assignment" var)
get-value-code (end-with-linkage linkage
(make-instruction-sequence '(env val) (list target) (preserving '(env)
`((perform (op set-variable-value!) get-value-code
(const ,var) (make-instruction-sequence '(env val) (list target)
(reg val) `((perform (op lexical-address-set!)
(reg env)) (const ,adr) ;; (const ,var) before
(assign ,target (const ok)))))))) (reg val)
(reg env))
(assign ,target (const ok)))))))))
(define (compile-definition exp ct-env target linkage) (define (compile-definition exp ct-env target linkage)
(let ((var (definition-variable exp)) (let ((var (definition-variable exp))