aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Comeaux <jacquesrcomeaux@protonmail.com>2023-10-26 12:57:20 -0500
committerJacques Comeaux <jacquesrcomeaux@protonmail.com>2023-10-26 12:57:20 -0500
commit3f7404aad0301123e490d6eb6da5591cae96a7c9 (patch)
tree2cc5af6c3c7c9f39738cab77aea53a7af11b4996
parentb3c0a8d1303fc166886f753f036f863761580a05 (diff)
Finish chapter 4 part 1
-rw-r--r--chap4/part1.rkt289
1 files changed, 284 insertions, 5 deletions
diff --git a/chap4/part1.rkt b/chap4/part1.rkt
index 9fa3057..5a327fe 100644
--- a/chap4/part1.rkt
+++ b/chap4/part1.rkt
@@ -32,6 +32,7 @@
((or? exp) (eval-or (or-disjuncts exp) env))
((let? exp) (eval (let->combination exp) env))
((let*? exp) (eval (let*->nested-lets exp) env))
+ ((letrec? exp) (eval (letrec->let exp) env))
((application? exp)
(apply-
(eval (operator exp) env)
@@ -137,6 +138,7 @@
(cadr exp)
(caadr exp)))
+(#%provide definition-value)
(define (definition-value exp)
(if (symbol? (cadr exp))
(caddr exp)
@@ -148,6 +150,7 @@
(define (lambda-parameters exp) (cadr exp))
+(#%provide lambda-body)
(define (lambda-body exp) (cddr exp))
(define (make-lambda parameters body)
@@ -344,7 +347,7 @@
(if (null? (cdr (let-body-extended exp)))
(car (let-body-extended exp))
(cons 'begin (let-body-extended exp)))
- (list
+ (cons
(cons
'lambda
(cons
@@ -448,15 +451,19 @@
(eq? x false))
(define (make-procedure parameters body env)
+ #| (list 'procedure parameters (scan-out-defines body) env)) |#
(list 'procedure parameters body env))
(define (compound-procedure? p)
(tagged-list? p 'procedure))
+(#%provide procedure-parameters)
(define (procedure-parameters p) (cadr p))
+(#%provide procedure-body)
(define (procedure-body p) (caddr p))
+(#%provide procedure-environment)
(define (procedure-environment p) (cadddr p))
(#%provide enclosing-environment)
@@ -499,7 +506,10 @@
((null? vars)
(env-loop (enclosing-environment env)))
((eq? var (car vars))
- (car vals))
+ #| (car vals)) |#
+ (if (eq? (car vals) '*unassigned*)
+ (error "Unassigned variable" var)
+ (car vals)))
(else (scan (cdr vars) (cdr vals)))))
(if (eq? env the-empty-environment)
(error "Unbound variable" var)
@@ -737,17 +747,286 @@
#| 4.15 |#
+(define (run-forever) (run-forever))
+
+#| (define (try p) |#
+#| (if (halts? p p) |#
+#| (run-forever) |#
+#| 'halted)) |#
+
+#| (try try) |#
+
;; Internal Definitions
+#| (define (f x) |#
+#| (define (even? n) |#
+#| (if (= n 0) |#
+#| true |#
+#| (odd? (- n 1)))) |#
+#| (define (odd? n) |#
+#| (if (= n 0) |#
+#| false |#
+#| (even? (- n 1)))) |#
+#| (even? 6)) |#
+
#| 4.16 |#
-#| 4.17 |#
-#| 4.18 |#
-#| 4.19 |#
+
+(#%provide lookup-variable-value---)
+(define (lookup-variable-value--- var env)
+ (define (env-loop env)
+ (define (scan vars vals)
+ (cond
+ ((null? vars)
+ (env-loop (enclosing-environment env)))
+ ((eq? var (car vars))
+ (if (eq? (car vals) '*unassigned*)
+ (error "Unassigned variable" var)
+ (car vals)))
+ (else (scan (cdr vars) (cdr vals)))))
+ (if (eq? env the-empty-environment)
+ (error "Unbound variable" var)
+ (let ((frame (first-frame env)))
+ (scan
+ (frame-variables frame)
+ (frame-values frame)))))
+ (env-loop env))
+
+(define (filter predicate xs)
+ (if (null? xs)
+ '()
+ (if (predicate (car xs))
+ (cons (car xs) (filter predicate (cdr xs)))
+ (filter predicate (cdr xs)))))
+
+(#%provide scan-out-defines)
+(define (scan-out-defines body)
+ (let
+ ((not-defs (filter (lambda (exp) (not (definition? exp))) body))
+ (defs (filter definition? body)))
+ (if (null? defs)
+ body
+ (list
+ (make-let
+ (map
+ (lambda (def)
+ (list (definition-variable def) ''*unassigned*))
+ defs)
+ (append
+ (map
+ (lambda (def)
+ (list
+ 'set!
+ (definition-variable def)
+ (definition-value def)))
+ defs)
+ not-defs))))))
+
#| 4.20 |#
+
+(#%provide letrec?)
+(define (letrec? exp) (tagged-list? exp 'letrec))
+
+(#%provide letrec->let)
+(define (letrec->let exp)
+ (make-let
+ (map
+ (lambda (bind)
+ (list (binding-var bind) ''*unassigned*))
+ (let-bindings exp))
+ (append
+ (map
+ (lambda (bind)
+ (list
+ 'set!
+ (binding-var bind)
+ (binding-exp bind)))
+ (let-bindings exp))
+ (let-body exp))))
+
#| 4.21 |#
+(#%provide factorial)
+(define factorial
+ (lambda (n)
+ ((lambda (fact)
+ (fact fact n))
+ (lambda (ft k)
+ (if (= k 1)
+ 1
+ (* k (ft ft (- k 1))))))))
+
+(#%provide qfactorial)
+(define qfactorial
+ '(lambda (n)
+ ((lambda (fact)
+ (fact fact n))
+ (lambda (ft k)
+ (if (= k 1)
+ 1
+ (* k (ft ft (- k 1))))))))
+
+(#%provide fibonacci)
+(define fibonacci
+ (lambda (n)
+ ((lambda (fib) (fib fib 1 0 n))
+ (lambda (ft a b k)
+ (if (= k 0)
+ b
+ (ft ft (+ a b) a (- k 1)))))))
+
+(#%provide qfibonacci)
+(define qfibonacci
+ '(lambda (n)
+ ((lambda (fib) (fib fib 1 0 n))
+ (lambda (ft a b k)
+ (if (= k 0)
+ b
+ (ft ft (+ a b) a (- k 1)))))))
+
+(#%provide even-odd)
+(define (even-odd x)
+ ((lambda (even? odd?)
+ (even? even? odd? x))
+ (lambda (ev? od? n)
+ (if (= n 0) true (od? ev? od? (- n 1))))
+ (lambda (ev? od? n)
+ (if (= n 0) false (ev? ev? od? (- n 1))))))
+
;; Separating Syntactic Analysis from Execution
+(#%provide eval-)
+(define (eval- exp env)
+ ((analyze exp) env))
+
+(#%provide analyze)
+(define (analyze exp)
+ (cond
+ ((self-evaluating? exp)
+ (analyze-self-evaluating exp))
+ ((quoted? exp) (analyze-quoted exp))
+ ((variable? exp) (analyze-variable exp))
+ ((assignment? exp) (analyze-assignment exp))
+ ((definition? exp) (analyze-definition exp))
+ ((if? exp) (analyze-if exp))
+ ((lambda? exp) (analyze-lambda exp))
+ ((begin? exp) (analyze-sequence (begin-actions exp)))
+ ((cond? exp) (analyze (cond->if exp)))
+ ((let? exp) (analyze (let->combination exp)))
+ ((application? exp) (analyze-application exp))
+ (else
+ (error "Unknown expression type -- ANALYZE" exp))))
+
+(define (analyze-self-evaluating exp)
+ (lambda (env) exp))
+
+(define (analyze-quoted exp)
+ (let ((qval (text-of-quotation exp)))
+ (lambda (env) qval)))
+
+(define (analyze-variable exp)
+ (lambda (env) (lookup-variable-value exp env)))
+
+(define (analyze-assignment exp)
+ (let
+ ((var (assignment-variable exp))
+ (vproc (analyze (assignment-value exp))))
+ (lambda (env)
+ (set-variable-value! var (vproc env) env)
+ 'ok)))
+
+(define (analyze-definition exp)
+ (let
+ ((var (definition-variable exp))
+ (vproc (analyze (definition-value exp))))
+ (lambda (env)
+ (define-variable! var (vproc env) env)
+ 'ok)))
+
+(define (analyze-if exp)
+ (let
+ ((pproc (analyze (if-predicate exp)))
+ (cproc (analyze (if-consequent exp)))
+ (aproc (analyze (if-alternative exp))))
+ (lambda (env)
+ (if (true? (pproc env))
+ (cproc env)
+ (aproc env)))))
+
+(#%provide analyze-lambda)
+(define (analyze-lambda exp)
+ (let
+ ((vars (lambda-parameters exp))
+ (bproc (analyze-sequence (lambda-body exp))))
+ (lambda (env) (make-procedure vars bproc env))))
+
+(define (analyze-sequence exps)
+ (define (sequentially proc1 proc2)
+ (lambda (env) (proc1 env) (proc2 env)))
+ (define (loop first-proc rest-procs)
+ (if (null? rest-procs)
+ first-proc
+ (loop
+ (sequentially first-proc (car rest-procs))
+ (cdr rest-procs))))
+ (let
+ ((procs (map analyze exps)))
+ (if (null? procs)
+ (error "Empty sequence -- ANALYZE"))
+ (loop (car procs) (cdr procs))))
+
+(define (analyze-application exp)
+ (let
+ ((fproc (analyze (operator exp)))
+ (aprocs (map analyze (operands exp))))
+ (lambda (env)
+ (execute-application
+ (fproc env)
+ (map
+ (lambda (aproc) (aproc env))
+ aprocs)))))
+
+(define (execute-application proc args)
+ (cond
+ ((primitive-procedure? proc)
+ (apply-primitive-procedure proc args))
+ ((compound-procedure? proc)
+ ((procedure-body proc)
+ (extend-environment
+ (procedure-parameters proc)
+ args
+ (procedure-environment proc))))
+ (else
+ (error
+ "Unknown procedure type -- EXECUTE-APPLICATION"
+ proc))))
+
#| 4.22 |#
+
+#| ((let? exp) (analyze (let->combination exp))) |#
+
#| 4.23 |#
+
+(define (analyze-sequence-bad exps)
+ (define (execute-sequence procs env)
+ (cond
+ ((null? (cdr procs)) ((car procs) env))
+ (else
+ ((car procs) env)
+ (execute-sequence (cdr procs) env))))
+ (let ((procs (map analyze exps)))
+ (if (null? procs)
+ (error "Empty sequence -- ANALYZE"))
+ (lambda (env) (execute-sequence procs env))))
+
#| 4.24 |#
+
+(#%provide timed)
+(define (timed f)
+ (lambda args
+ (let
+ ((start (runtime))
+ (result (apply f args))
+ (end (runtime)))
+ (display (- end start))
+ (newline)
+ result)))