2021-01-14 13:35:46 +01:00
|
|
|
(load "util.scm")
|
2021-01-15 20:38:24 +01:00
|
|
|
(load "misc/evaluator.scm")
|
2021-01-14 13:35:46 +01:00
|
|
|
|
2021-01-15 20:38:24 +01:00
|
|
|
(display "\nex-4.1 - list-of-values\n")
|
|
|
|
|
|
|
|
(define (list-of-values-left-to-right exps env)
|
|
|
|
(if (no-operands? exps)
|
|
|
|
'()
|
|
|
|
(let ((first (eval (first-operand exps) env)))
|
|
|
|
(let ((rest ((list-of-values (rest-operands exps) env))))
|
|
|
|
(cons first rest)))))
|
|
|
|
|
|
|
|
(define (list-of-values-right-to-left exps env)
|
|
|
|
(if (no-operands? exps)
|
|
|
|
'()
|
|
|
|
(let ((rest ((list-of-values (rest-operands exps) env))))
|
|
|
|
(let ((first (eval (first-operand exps) env)))
|
|
|
|
(cons first rest)))))
|
|
|
|
|
|
|
|
(display "[done]\n")
|
|
|
|
|
2021-01-16 11:19:25 +01:00
|
|
|
(display "\nex-4.2 - explicite-call\n")
|
2021-01-15 20:38:24 +01:00
|
|
|
|
2021-01-16 11:19:25 +01:00
|
|
|
; Louis's plan does not work because the implementation would treat assignments
|
|
|
|
; and definitions as applications. That means define and set! would no longer be
|
|
|
|
; special forms.
|
|
|
|
|
|
|
|
(define (application?-call exp) (tagged-list exp 'call))
|
|
|
|
(define (operator-call exp) (cadr exp))
|
|
|
|
(define (operands-call exp) (cddr exp))
|
|
|
|
|
|
|
|
(display "[done]\n")
|
|
|
|
|
|
|
|
(display "\nex-4.3 - data-directed-eval\n")
|
|
|
|
|
|
|
|
(define *eval-table* (make-hash-table))
|
|
|
|
(define (put op proc)
|
|
|
|
(hash-table/put! *eval-table* (list op) proc))
|
|
|
|
(define (get op)
|
|
|
|
(hash-table/get *eval-table* (list op) #f))
|
|
|
|
|
|
|
|
(define (install-eval-package)
|
|
|
|
(put 'quote (lambda (exp env) (text-of-quotation exp)))
|
|
|
|
(put 'set! eval-assignment)
|
|
|
|
(put 'define eval-definition)
|
|
|
|
(put 'if eval-if)
|
|
|
|
(put 'lambda
|
|
|
|
(lambda (exp env)
|
|
|
|
(make-procedure (lambda-parameters exp)
|
|
|
|
(lambda-body exp)
|
|
|
|
env)))
|
|
|
|
(put 'begin (lambda (exp env) (eval-sequence (begin-actions exp) env)))
|
|
|
|
(put 'cond (lambda (exp env) (eval (cond->if exp) env)))
|
2021-01-18 14:19:32 +01:00
|
|
|
(put 'let (lambda (exp env) (eval (let->combination exp) env)))
|
2021-01-18 12:45:29 +01:00
|
|
|
(put 'let* (lambda (exp env) (eval (let*->nested-lets exp) env)))
|
2021-01-17 18:16:20 +01:00
|
|
|
(put 'and (lambda (exp env) (eval-and (clauses exp) env)))
|
|
|
|
(put 'or (lambda (exp env) (eval-or (clauses exp) env)))
|
2021-01-16 11:19:25 +01:00
|
|
|
(display "[install-eval-package]\n")
|
|
|
|
'done)
|
|
|
|
|
|
|
|
(install-eval-package)
|
|
|
|
|
|
|
|
(define (eval exp env)
|
2021-01-17 18:16:20 +01:00
|
|
|
; (display "(EVAL ") (display exp) (display ")") (newline)
|
2021-01-16 11:19:25 +01:00
|
|
|
(cond
|
|
|
|
((self-evaluating? exp) exp)
|
|
|
|
((variable? exp) (lookup-variable-value exp env))
|
2021-01-17 18:16:20 +01:00
|
|
|
((and (not (null? exp)) (get (car exp)))
|
|
|
|
((get (car exp)) exp env))
|
2021-01-16 11:19:25 +01:00
|
|
|
((application? exp)
|
|
|
|
(apply (eval (operator exp) env)
|
|
|
|
(list-of-values (operands exp) env)))
|
|
|
|
(else (error "Unknown expression type -- EVAL" exp))))
|
|
|
|
|
|
|
|
(display "[done]\n")
|
|
|
|
|
2021-01-17 18:16:20 +01:00
|
|
|
(display "\nex-4.4 - and/or\n")
|
|
|
|
|
|
|
|
(define (clauses exp) (cdr exp))
|
|
|
|
(define (no-clauses? exp) (null? exp))
|
|
|
|
(define (first-clause exp) (car exp))
|
|
|
|
(define (rest-clauses exp) (cdr exp))
|
|
|
|
|
|
|
|
(define (eval-and exp env)
|
|
|
|
(if (no-clauses? exp)
|
|
|
|
#t
|
|
|
|
(if (true? (eval (first-clause exp) env))
|
|
|
|
(eval-and (rest-clauses exp) env)
|
|
|
|
#f)))
|
|
|
|
|
|
|
|
(define (eval-or exp env)
|
|
|
|
(if (no-clauses? exp)
|
|
|
|
#f
|
|
|
|
(if (true? (eval (first-clause exp) env))
|
|
|
|
#t
|
|
|
|
(eval-or (rest-clauses exp) env))))
|
|
|
|
|
|
|
|
(define (true? a) a)
|
|
|
|
|
|
|
|
(assert (eval '(or) '()) #f)
|
|
|
|
(assert (eval '(and) '()) #t)
|
|
|
|
(assert (eval '(and 0 0 0 #f) '()) #f)
|
|
|
|
(assert (eval '(or #f #f #t) '()) #t)
|
|
|
|
|
|
|
|
(display "\nex-4.5 - modified-cond\n")
|
|
|
|
|
|
|
|
(define (cond-test exp) (car exp))
|
|
|
|
(define (cond-recipient exp) (caddr exp))
|
|
|
|
(define (cond-test-recipient-clause? exp)
|
|
|
|
(eq? (cadr exp) '=>))
|
|
|
|
|
|
|
|
(define (expand-clauses clauses)
|
|
|
|
(if (null? clauses)
|
|
|
|
'false ; no else clause
|
|
|
|
(let ((first (car clauses))
|
|
|
|
(rest (cdr clauses)))
|
|
|
|
(cond
|
|
|
|
((cond-else-clause? first)
|
|
|
|
(if (null? rest)
|
|
|
|
(sequence->exp (cond-actions first))
|
|
|
|
(error "ELSE clause isn't last -- COND->IF"
|
|
|
|
clauses)))
|
|
|
|
((cond-test-recipient-clause? first)
|
|
|
|
(let ((test-evaluated (eval (cond-test exp) env)))
|
2021-01-18 14:19:32 +01:00
|
|
|
(if (true? test-evaluated)
|
2021-01-17 18:16:20 +01:00
|
|
|
(eval (list (cond-recipient exp) test-evaluated) env)
|
|
|
|
(expand-clauses rest))))
|
|
|
|
(else
|
|
|
|
(make-if (cond-predicate first)
|
|
|
|
(sequence->exp (cond-actions first))
|
|
|
|
(expand-clauses rest)))))))
|
2021-01-16 11:19:25 +01:00
|
|
|
|
2021-01-17 18:16:20 +01:00
|
|
|
(display "[done]\n")
|
|
|
|
|
2021-01-18 12:45:29 +01:00
|
|
|
(display "\nex-4.6 - let\n")
|
|
|
|
|
|
|
|
(define (let? exp) (tagged-list exp 'let))
|
2021-01-18 14:19:32 +01:00
|
|
|
(define (let-bindings exp) (cadr exp))
|
2021-01-18 12:45:29 +01:00
|
|
|
(define (let-body exp) (cddr exp))
|
2021-01-18 14:19:32 +01:00
|
|
|
(define (let-binding-var binding) (car binding))
|
|
|
|
(define (let-binding-exp binding) (cadr binding))
|
|
|
|
(define (let-vars exp) (map let-binding-var (let-bindings exp)))
|
|
|
|
(define (let-exps exp) (map let-binding-exp (let-bindings exp)))
|
|
|
|
|
|
|
|
(define (let->combination exp)
|
|
|
|
(let ((let-variables (let-vars exp))
|
|
|
|
(let-expressions (let-exps exp)))
|
2021-01-18 12:45:29 +01:00
|
|
|
(cons (make-lambda let-variables (let-body exp))
|
|
|
|
let-expressions)))
|
|
|
|
|
2021-01-18 14:19:32 +01:00
|
|
|
(assert (let->combination '(let ((a 3) (b 4)) (* 3 a b)))
|
2021-01-18 12:45:29 +01:00
|
|
|
'((lambda (a b) (* 3 a b)) 3 4))
|
|
|
|
|
|
|
|
(display "\nex-4.7 - let*\n")
|
|
|
|
|
|
|
|
(define (let*? exp) (tagged-list exp 'let*))
|
|
|
|
(define (let*-inits exp) (cadr exp))
|
|
|
|
(define (let*-body exp) (cddr exp))
|
|
|
|
(define (let*-inits-empty? inits) (null? inits))
|
|
|
|
(define (let*-first-init inits) (car inits))
|
|
|
|
(define (let*-rest-init inits) (cdr inits))
|
2021-01-17 18:16:20 +01:00
|
|
|
|
2021-01-18 12:45:29 +01:00
|
|
|
(define (let*->nested-lets exp)
|
|
|
|
(define (nest-lets inits)
|
|
|
|
(if (let*-inits-empty? inits)
|
|
|
|
(sequence->exp (let*-body exp))
|
|
|
|
(list
|
|
|
|
'let
|
|
|
|
(list (let*-first-init inits))
|
|
|
|
(nest-lets (let*-rest-init inits)))))
|
|
|
|
(nest-lets (let*-inits exp)))
|
2021-01-17 18:16:20 +01:00
|
|
|
|
2021-01-18 12:45:29 +01:00
|
|
|
(assert (let*->nested-lets '(let* ((x 1) (y 2)) (* x y) (+ x y)))
|
|
|
|
'(let ((x 1)) (let ((y 2)) (begin (* x y) (+ x y)))))
|
2021-01-17 18:16:20 +01:00
|
|
|
|
2021-01-18 14:19:32 +01:00
|
|
|
|
2021-01-18 12:45:29 +01:00
|
|
|
(display "\nex-4.8 - named-let\n")
|
2021-01-17 18:16:20 +01:00
|
|
|
|
2021-01-18 14:19:32 +01:00
|
|
|
(define (simple-let? exp) (pair? (let-bindings exp)))
|
|
|
|
(define (named-let? exp) (symbol? (let-bindings exp)))
|
|
|
|
(define (named-let-var exp) (cadr exp))
|
|
|
|
(define (named-let-bindings exp) (caddr exp))
|
|
|
|
|
|
|
|
(define (named-let-var exp) (cadr exp))
|
|
|
|
(define (named-let-bindings exp) (caddr exp))
|
|
|
|
(define (named-let-body exp) (cdddr exp))
|
|
|
|
(define (named-let-vars exp) (map let-binding-var (named-let-bindings exp)))
|
|
|
|
(define (named-let-exps exp) (map let-binding-exp (named-let-bindings exp)))
|
|
|
|
|
|
|
|
(define (let->combination exp)
|
|
|
|
(cond
|
|
|
|
((simple-let? exp)
|
|
|
|
(let ((let-variables (let-vars exp))
|
|
|
|
(let-expressions (let-exps exp)))
|
|
|
|
(cons (make-lambda let-variables (let-body exp))
|
|
|
|
let-expressions)))
|
|
|
|
((named-let? exp)
|
|
|
|
(let ((let-name (named-let-var exp))
|
|
|
|
(let-variables (named-let-vars exp))
|
2021-01-18 14:48:59 +01:00
|
|
|
(let-expressions (named-let-exps exp))
|
|
|
|
(let-body (named-let-body exp)))
|
|
|
|
(list
|
|
|
|
'let
|
|
|
|
(cons (list let-name (make-lambda let-variables let-body))
|
|
|
|
(named-let-bindings exp))
|
|
|
|
(sequence->exp let-body))))
|
2021-01-18 14:19:32 +01:00
|
|
|
(else (error "Unsupported let expression -- LET->COMBINATION"))))
|
|
|
|
|
|
|
|
(assert (let->combination '(let ((a 3) (b 4)) (* 3 a b)))
|
|
|
|
'((lambda (a b) (* 3 a b)) 3 4))
|
|
|
|
|
2021-01-18 14:48:59 +01:00
|
|
|
(assert (let->combination '(let fib-iter ((a 1)) (fib-iter (+ a 1)) 3))
|
|
|
|
'(let ((fib-iter (lambda (a) (fib-iter (+ a 1)) 3)) (a 1)) (begin (fib-iter (+ a 1)) 3)))
|
2021-01-18 14:19:32 +01:00
|
|
|
|
|
|
|
(display "\nex-4.9 - iteration-constructs\n")
|
2021-01-17 18:16:20 +01:00
|
|
|
|
2021-01-19 19:25:35 +01:00
|
|
|
(define (repeat? exp) (tagged-list exp 'repeat))
|
|
|
|
(define (repeat-count exp) (cadr exp))
|
|
|
|
(define (repeat-body exp) (cddr exp))
|
|
|
|
|
|
|
|
(define (repeat->combination exp)
|
|
|
|
(if (= (repeat-count exp) 0)
|
|
|
|
'()
|
|
|
|
(list
|
|
|
|
(sequence->exp (repeat-body exp))
|
|
|
|
(cons 'repeat
|
|
|
|
(cons (- (repeat-count exp) 1)
|
|
|
|
(repeat-body exp))))))
|
|
|
|
|
|
|
|
(display "repeat: ")
|
|
|
|
(assert (repeat->combination '(repeat 10 (display "foo") (newline)))
|
|
|
|
'((begin (display "foo") (newline)) (repeat 9 (display "foo") (newline))))
|
|
|
|
|
|
|
|
(define (while? exp) (tagged-list exp 'while))
|
|
|
|
(define (while-predicate exp) (cadr exp))
|
|
|
|
(define (while-body exp) (cddr exp))
|
|
|
|
|
|
|
|
(define (while->combination exp)
|
|
|
|
(let ((body (while-body exp))
|
|
|
|
(predicate (while-predicate exp)))
|
|
|
|
(if (not (true? predicate))
|
|
|
|
'()
|
|
|
|
(list
|
|
|
|
(sequence->exp body)
|
|
|
|
(cons 'while
|
|
|
|
(cons predicate
|
|
|
|
body))))))
|
|
|
|
|
|
|
|
(display "while: ")
|
|
|
|
(display (while->combination '(while (lambda () #t) (display "one"))))
|
|
|
|
|
2021-01-18 14:19:32 +01:00
|
|
|
(display "\nex-4.10\n")
|
2021-01-14 13:35:46 +01:00
|
|
|
|