130 likes | 246 Views
Defining New Special Forms (unless test body) (if (not test) body #f) (when (not test) body). (inc! x) (set! x (inc x)). (define unless (method ((test <boolean>) (body <object>)) (if (not test) body #f))) (define inc! (method ((x <integer>)) (set! x (inc x)))) doesn't work!.
E N D
Defining New Special Forms • (unless test body) • (if (not test) body #f) • (when (not test) body)
(inc! x) (set! x (inc x))
(define unless (method ((test <boolean>) (body <object>)) (if (not test) body #f))) (define inc! (method ((x <integer>)) (set! x (inc x)))) doesn't work!
Macros Ordinary functions 1. Evaluate the arguments 2. Apply function to (values of) the arguments 3. Return the result of step 2 Macros 1. Substitute the (unevaluated) args textually in the body 2. Evaluate the result 3. Return the result of step 2.
class <macro> special formmacro (macro (params) pre-body) 1. The pre-body is evaluated twice : once to do the textual substitution and once to compute the value. 2. The first evaluation is done in the environment of the closure, the second is done in the environment of the call.
Want (inc! z) to expand to (set! z (inc z)) (define (inc! <macro>) (macro (x) (list 'set! x (list 'inc x))))
(define (inc! <macro>) (macro (x) (list 'set! x (list 'inc x)))) pre-body
1. Evaluate the pre-body in the environment of the closure with params bound to unevaluated arguments 2. Evaluate the resulting expression in the environment of the macro call.
(define (inc! <macro>) (macro (x) (list 'set! x (list 'inc x)))) (define z 3) => 3 (inc! z) => (set! z (inc z)) => 4 z => 4
(define (unless <macro>) (macro (tst bdy) (list 'if (list 'not tst) bdy '#f))) (define x 2) => 2 (unless (= x 0) (/ 2 x)) => (if (not (= x 0)) (/ 2 x) #f) => 1
EVALUATION (define-generic-function brenda-eval ((obj <object>) (env <brenda-environment>))) (add-method brenda-eval (method ((obj <object>) (env <brenda-environment>)) obj)) (add-method brenda-eval (method ((obj <symbol>) (env <brenda-environment>)) (lookup obj env))) (add-method brenda-eval (method ((obj <pair>) (env <brenda-environment>)) (brenda-apply (brenda-eval (head obj) env) (tail obj) env)))
APPLICATION (define-generic-function brenda-apply ((obj <object>) (args <list>) (env <brenda-environment>))) (add-method brenda-apply (method ((obj <brenda-special-form>) (args <list>) (env <brenda-environment>)) ((calls obj) args env))) (add-method brenda-apply (method ((obj <brenda-user-method>) (args <list>) (e <brenda-environment>)) (bind (((evaled-args <list>) (map (method (x) (brenda-eval x e)) args))) (when (args-params-match? (params obj) evaled-args) (bind ((new-env (expand-environment (params obj) evaled-args (env obj)))) (eval-sequence (body obj) new-env))))))
MACROS (add-method brenda-apply (method ((obj <brenda-macro>) (args <list>) (e <brenda-environment>)) (when (args-params-match? (params obj) args) (bind ((new-env (expand-environment (params obj) args (env obj)))) (brenda-eval (eval-sequence (body obj) new-env) e)))))