1 saves repeated renaming and substitution: explicit substitution is replaced by variable bindings...
Post on 24-Dec-2015
219 Views
Preview:
TRANSCRIPT
1
• Saves repeated renaming and substitution: explicit substitution is replaced by variable
bindings using new data structures (frame, environment).
• Can be utilized to gain further improvements that cannot be achieved using the
substitution model (The analyzer/compiler)
Env. model evaluator: Motivation
Env. model evaluator: Structure and implementation
Data Structures:
• New data structures: frame, environment
• Additional procedures are added to handle the new ADTs
• A closure keeps the Env in which it was created.
• Renaming and substitution are no longer needed!
ASPASP
Derived expressions
Derived expressions
TestTest
Data structuresData structures
UtilsA racket lib
UtilsA racket lib
• Proc / Primitive-Proc.• Global Environment.
• Op. semantics(evaluation rules)• Special forms
• ADT per expressions• An abstraction barrier• Used by all evaluators
<Scheme-expression>
ParserParser
<AST>
substitutionsubstitution
valuesvalues
CoreCore
Env. model evaluator: Structure and implementation
ASPASP
Derived expressions
Derived expressions
TestTest
Data structuresData structures
UtilsA racket lib
UtilsA racket lib
• Proc / Primitive-Proc.• Global Environment.
• Op. semantics(evaluation rules)• Special forms
• ADT per expressions• An abstraction barrier• Used by all evaluators
<Scheme-expression>
ParserParser
<AST>
substitutionsubstitution
valuesvalues
CoreCore
Core:• Procedure application (apply procedure) and evaluation of
expressions are done with respect to a certain environment.
Tests:
• Updated accordingly.
4
Env. model evaluator: Structure and implementation
Box, unbox:
• The global environment may change (E.g., by definitions).
• Values that may change should be boxed (similar to pointers).
#<primitive:+>+Binding: implemented as a Pair
• A correspondence between a variable and its value.
‘((x foo) (4 <procedure (x) x>))
• A substitution from variables to values. Each variable is bound to a single value.
Frame: Implemented as a substitution
5
Environment: Implemented as a list of boxed frames
• A finite sequence of frames in which the last frames is the-global-environment.
Env. model evaluator: Structure and implementation
…
…
E1
box-pointer diagram:
frame
t-g-e
‘((foo …) ( ))
‘((+ - …) (prim+ prim- …))
box box
proc params body
frame
E2
E3
6
Env. model evaluator: Evaluation examples
(define env-eval (lambda (exp env) (cond ((atomic? exp) (eval-atomic exp env)) ((special-form? exp) (eval-special-form exp env)) ((application? exp) (apply-procedure (env-eval (operator exp) env) (list-of-values (operands exp) env))) (else (error 'eval "unknown expression type: ~s" exp)))))
Reminder: env-eval (interpreter-core.rkt)
7
Env. model evaluator: Evaluation examples
1. Evaluating a definition expression:
(define eval-special-form (lambda (exp env) (cond ... ((definition? exp) (if (not (eq? env t-g-e)) (error 'eval "non global definition: ~s" exp) (eval-definition exp))) ...)))
(define eval-definition (lambda (exp) (add-binding! (make-binding (definition-variable exp)
(env-eval (definition-value exp) t-g-e))) 'ok))
(define env-eval (lambda (exp env) (cond ((atomic? exp) (eval-atomic exp env)) ((special-form? exp) (eval-special-form exp env)) ...)))
> (env-eval (derive '(define f (lambda (x) (lambda (y) (+ x y))))) t-g-e)
8
Env. model evaluator: Evaluation examples
(define eval-special-form (lambda (exp env) (cond ... ((lambda? exp) (eval-lambda exp env)) ...)))
> (env-eval (derive '(define f (lambda (x) (lambda (y) (+ x y))))) t-g-e)
(define eval-lambda (lambda (exp env) (make-procedure (lambda-parameters exp) (lambda-body exp) env)))
(define make-procedure (lambda (parameters body env) (attach-tag (list parameters body env) 'procedure)))
(make-procedure '(x) '(lambda (y) (+ x y)) t-g-e)
P: xB: (lambda (y) (+ x y))
t-g-e
1. Evaluating a definition expression:
Textual annotation:<procedure (x) (lambda (y) (+ x y))>@t-g-e
9
Env. model evaluator: Evaluation examples
> (env-eval (derive '(define f (lambda (x) (lambda (y) (+ x y))))) t-g-e)
(add-binding! (make-binding ‘f <procedure (x) (lambda (y) (+ x y))>@t-g-e))
1. Evaluating a definition expression:
(define eval-special-form (lambda (exp env) (cond ... ((definition? exp) (if (not (eq? env t-g-e)) (error 'eval "non global definition: ~s" exp) (eval-definition exp))) ...)))
(define env-eval (lambda (exp env) (cond ((atomic? exp) (eval-atomic exp env)) ((special-form? exp) (eval-special-form exp env)) ...)))
(define eval-definition (lambda (exp) (add-binding! (make-binding (definition-variable exp)
(env-eval (definition-value exp) t-g-e))) 'ok)) Done!
10
Env. model evaluator: Evaluation examples
2. Evaluating a user procedure:
(define env-eval (lambda (exp env) (cond ((atomic? exp) (eval-atomic exp env)) ((special-form? exp) (eval-special-form exp env)) ...)))
> (derive-eval 'f)
(define eval-atomic (lambda (exp env) (if (or (number? exp) (boolean? exp) (null? exp)) exp (lookup-variable-value exp env))))
> <procedure (x) (lambda (y) (+ x y))>@t-g-e
x: 1
GE
11
Env. model evaluator: Evaluation examples
3. Evaluating an application of a user procedure:
> (derive-eval '(define g (f 1)) )
(apply-procedure <procedure (x) (lambda (y) (+ x y))>@t-g-e (1))
Create a new frame where x maps to 1(make-frame ‘(x) ‘(1))
Extend the environment(extend-env new-frame t-g-e)
Evaluate the body(eval-sequence body new-env)
12
• Can be regarded as a nested let expression.
• Similar to let, but each defined variable can be used in subsequent definitions.
> (let ((a 1) (c (* a 2))) (+ a c))
> (define a 10)
Env. model evaluator: Supporting let*
Reminder: What is a let* expression?
Example:
> (let* ((a 1) (c (* a 2))) (+ a c))
> (let ((a 1)) (let ((c (* a 2))) (+ a c)))
> ((λ (a) ((λ (c) (+ a c)) (* a 2)) 1)
> 3
= =
> 21
13
An expression (let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm),
with respect to environment E0, is defined as follows:
E1 E0 * make-frame [(v1),(env-eval e1 E0)]E2 E1 * make-frame [(v2),(env-eval e2 E1)]...En En-1* make-frame [(vn),(env-eval en En-1)]
(env-eval b1 En) ... (env-eval bm-1 En)
Return (env-eval bm En)
Q: How would the evaluation rule for let look like?
A: e1…en will be evaluated with respect to E0. A new frame mapping (v1…vn) to (e1…en)
will extend E0, creating a new environment, E1.
Evaluation rule for a let* expression:
Env. model evaluator: Supporting let*
14
Env. model evaluator: Supporting let* - as a derived expression
1. Add the required ADT procedures to the ASP
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
ASPASP
Derived expressions
Derived expressions
CoreCoreData structures
Data structures
(define let*? (lambda (exp) (tagged-by? exp 'let*)))
(define let*-initial-values (lambda (exp) (map cadr (let*-bindings exp))))
(define let*-bindings (lambda (exp) (car (get-content exp))))(define let*-body (lambda (exp) (cdr (get-content exp))))(define let*-variables (lambda (exp) (map car (let*-bindings exp))))
(define make-let* (lambda (bindings body) (attach-tag (cons bindings body) 'let*)))(define (let*-first-variable exp) (caar (let*-bindings exp)))
(define (let*-first-initial-value exp) (cadar (let*-bindings exp)))
(define (make-let*-bindings vars vals) (map list vars vals))
15
Env. model evaluator: Supporting let* - as a derived expression
2. Modify the procedure derived?(define (derived? exp) (or (cond? exp) (function-definition? exp) (let? exp) (let*? exp)))
(define (shallow-derive exp) (cond ((cond? exp) (cond->if exp)) ... ((let*? exp) (let*->nested-let exp)) (else (error "Unhandled " exp))))
3. Modify the procedure shallow-derive
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
ASPASP
Derived expressions
Derived expressions
CoreCoreData structures
Data structures
16
Env. model evaluator: Supporting let* - as a derived expression
Q: The result is a let exp. Shouldn’t it be further derived?
A: Nah, derive recursively calls itself until the result exp does not change.
Q: What about the let* expression created by make-let*?
A: Nope. derive is recursively called for all sub expressions.
Q: When the if-condition does not hold, we wrap the body parameter in a list. Why?
A: Since the body of a let expression may consist of several expressions.
4. Add a translation procedure let*->nested-let (define (let*->nested-let exp) (let ((bindings (let*-bindings exp)) (body (let*-body exp))) (if (null? bindings) (make-lambda '() body) (if (null? (cdr bindings)) (make-let bindings body) ;dit (make-let ;dif (make-let*-bindings (list (let*-first-variable exp)) (list (let*-first-initial-value exp))) (list (make-let* (cdr bindings) body)) )))))(let*->nested-let
(derive
17
Env. model evaluator: Supporting let* - as a special form
1. Add the required ADT procedures to the ASP
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
ASPASP
Derived expressions
Derived expressions
CoreCoreData structures
Data structures
DONE
18
(define (special-form? exp) (or (quoted? exp) (lambda? exp) (definition? exp) (if? exp) (begin? exp) (let*? exp)))
(define (eval-special-form exp env) (cond ((quoted? exp) (text-of-quotation exp)) ((lambda? exp) (eval-lambda exp env)) … ((let*? exp) (eval-let* exp env))))
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
ASPASP
Derived expressions
Derived expressions
CoreCoreData structures
Data structures
Env. model evaluator: Supporting let* - as a special form
2. Modify the procedure special-form?
3. Modify eval-special-form
19
(define (eval-let* exp env) (let ((vars (let*-variables exp)) (vals (let*-initial-values exp)) (body (let*-body exp))) (letrec ((helper
(lambda (vars-lst vals-lst env) (if (null? vars-lst) (eval-sequence body env) (helper (cdr vars-lst) (cdr vals-lst) (extend-env
(make-frame (list (car vars-lst)) (list (env-eval (car vals-lst) env)))
env)))))) (helper vars vals env))))
Env. model evaluator: Supporting let* - as a special form
4. Add the procedure eval-let*, direct approach:
• Extend the environment with a new frame per variable.
• When no variables remain, evaluate the body.
20
(define (eval-let* exp env) (let ((body (let*-body exp))) (if (null? (let*-bindings exp)) (eval-sequence body env) (let ((first-var (let*-first-variable exp)) (first-val (let*-first-initial-value exp)) (rest-bindings (let*-rest-bindings exp))) (eval-let* (make-let* rest-bindings body) (extend-env (make-frame (list first-var) (list (env-eval first-val env))) env) )))))
Env. model evaluator: Supporting let* - as a special form
4. Add the procedure eval-let*, code generation approach:
21
Env. model Compiler: Motivation
(define length (lambda (lst) (if (null? lst) 0 (* 1 (length (cdr lst))))))
Special form?
What is ? *
What’s fact?
Each time fact is called, the interpreter:
• Uses the ASP to identify the body as an if exp,
• Extracts the required components for evaluation,
• Looks-up variables, etc.
To avoid repeated analysis, the compiler:
• Analyzes a given expression in static (compilation) time.
• Returns a procedure that awaits an environment argument.
• Once applied, it evaluates the analyzed expression with respect to the given environment.
• No further Analysis is performed!
22
• Using the compiler, we distinguish analysis from evaluation.
• The compiler returns a procedure ready for execution.
• Given an env, the procedure will compute the analyzed code with respect to that env.
• No analysis is performed during computation.
(define env-eval (lambda (exp env) <body>))
(define analyze (lambda (exp) (lambda (env) <analyzed -body>)))
Env. model Compiler: Introduction
env-eval:
[Exp*Env->Scheme-
Type]
compiler:
[Exp->[Env->Scheme-
Type]
Interpreter vs Compiler:
(define (analyze exp) (cond ((atomic? exp) (analyze-atomic exp)) ((special-form? exp) (analyze-special-form exp)) ((application? exp) (analyze-application exp)) (else
(error "Unknown expression type -- EVAL“ exp))))
Env. model Compiler: Comparing with env-eval
The analyze procedure:
Handling an if expression:(define eval-if (lambda (exp env) (if (true? (env-eval (if-predicate exp) env)) (env-eval (if-consequent exp) env) (env-eval (if-alternative exp) env))))
(define analyze-if (lambda (exp) (let ((pred (analyze (if-predicate exp))) (consequent (analyze (if-consequent exp))) (alternative (analyze (if-alternative exp)))) (lambda (env) (if (true? (pred env)) (consequent env) (alternative env))))))
Evaluator
Analyzer
24
(define (analyze-special-form exp) (cond ((quoted? exp) (analyze-quoted exp)) ((lambda? exp) (analyze-lambda exp)) … ((let*? exp) (analyze-let* exp))))
As a derived expression? Already done in the ASP!
1. Add the required ADT procedures to the ASP
2. identify a let* expression as a special form
3. Modify the procedure analyze-special-form:
Env. model Compiler: Supporting let*
As a special form?
25
Env. model Compiler: Supporting let*
(define (analyze-let* exp) (let ((vars (let*-variables exp)) (vals (map analyze (let*-initial-values exp))) (body (analyze-sequence (let*-body exp)))) (letrec ((fold (lambda (vars-lst vals-lst env) (if (null? vars-lst) (body env) (fold (cdr vars-lst) (cdr vals-lst) (extend-env (make-frame (list (car vars-lst)) (list ((car vals-lst) env))) env)))))) (lambda (env) (fold vars vals env)))))
4. Add the procedure analyze-let*:
“Translate” eval-let*, to an analyzer procedure: • Curry the env parameter. • Inductively analyze all sub expressions.
top related