Environment-Passing Interpreters
Post on 15-Jan-2016
38 Views
Preview:
DESCRIPTION
Transcript
plt-2002-2 04/21/23 4.8-1
Environment-Passing Interpreters
Programming Language Essentials
2nd edition
Chapter 3.8 Parameter-Passing Variations
plt-2002-2 04/21/23 4.8-2
Extended Languageprogram: exprexpr: number | id | primitive '(' expr *',' ')' | 'if' expr 'then' expr 'else' expr | 'let' (id '=' expr)* 'in' expr | 'proc' '(' id *',' ')' expr | '(' expr expr* ')' | 'letrec' ( id '(' id *',' ')' '=' expr )* 'in' expr | 'set' id '=' expr | 'begin' expr ( ';' expr )* 'end' begin-exp (exp exps)primitive: '+' | '-' | '*' | 'add1' | 'sub1'
plt-2002-2 04/21/23 4.8-3
Usage (1)let a = 3
p = proc (x) set x = 4
in begin (p a); a end
call-by-value: parameter bound to new location with operand value; a remains 3.
call-by-reference: if operand is variable reference, parameter is bound to location with reference to variable’s location; a becomes 4.
plt-2002-2 04/21/23 4.8-4
Usage (2)let a = 3 b = 4 swap = proc (x, y) let temp = x in begin set x = y; set y = temp endin begin (swap a b); -(a, b) end
plt-2002-2 04/21/23 4.8-5
Changes
scanner: remains unchanged.
parser: new rule for expression. This is just for convenience.
interpreter: new case for begin-exp,
reference now to direct and indirect targets,
environment now with targets.
Denoted Value = reference(Expressed Value)
Expressed Value = number + procval
plt-2002-2 04/21/23 4.8-6
target(define-datatype target target?
(direct-target
(expval expval?))
(indirect-target
(ref ref-to-direct-target?))
)
(define expval?
(lambda (x)
(or (number? x) (procval? x))
) )
plt-2002-2 04/21/23 4.8-7
ref-to-direct-target?
(define ref-to-direct-target? (lambda (x) (and (reference? x) (cases reference x (a-ref (pos vec) (cases target (vector-ref vec pos) (direct-target (v) #t) (indirect-target (v) #f)) ) ) ) )
plt-2002-2 04/21/23 4.8-8
deref(define deref (lambda (ref) (cases target (primitive-deref ref) (direct-target (expval) expval) (indirect-target (ref1) (cases target (primitive-deref ref1) (direct-target (expval) expval) (indirect-target (p) (error 'deref "Illegal reference" ref1)) ) ) ) ) )(define primitive-deref ; get value out of vector (lambda (ref) (cases reference ref (a-ref (pos vec) (vector-ref vec pos))) )
plt-2002-2 04/21/23 4.8-9
setref!(define setref! (lambda (ref expval) (let ((ref (cases target (primitive-deref ref) (direct-target (expval1) ref) (indirect-target (ref1) ref1) )) ) (primitive-setref! ref (direct-target expval))) ) )(define primitive-setref! ; set value in vector
(lambda (ref val) (cases reference ref (a-ref (pos vec) (vector-set! vec pos val))) ) )
plt-2002-2 04/21/23 4.8-10
Initial environment(define init-env
(lambda ()
(extend-env
'(i v x)
(map direct-target '(1 5 10))
(empty-env)
) ) )
every value in the environment has to be coded as target.
plt-2002-2 04/21/23 4.8-11
environment changes(define extend-env
(lambda (syms vals env)
(if ((list-of target?) vals)
(extended-env-record syms
(list->vector vals) env)
(error 'extend-env)
) ) )
(define extend-env-recursively
(lambda (names idss bodies old-env)
..
(vector-set! vec pos
(direct-target (closure ids body env))
) ..
) )
plt-2002-2 04/21/23 4.8-12
Parser(define the-grammar
'((program (expression) a-program)
..
(expression ("begin" expression
(arbno ";" expression) "end")
begin-exp) ..
) )
plt-2002-2 04/21/23 4.8-13
Interpreter (1)(define eval-expression
(lambda (exp env)
(cases expression exp
(begin-exp (exp1 exps)
(let loop
((acc (eval-expression exp1 env))
(exps exps)
)
(if (null? exps)
acc
(loop
(eval-expression (car exps) env)
(cdr exps)
) ) ) ) ..
plt-2002-2 04/21/23 4.8-14
Interpreter (2)
Modify all (sub)expression evaluations:
.. (primapp-exp (prim rands)
(let ((args (eval-primapp-exp-rands rands env)))
(apply-primitive prim args)
) ) ..
(define eval-primapp-exp-rands
(lambda (rands env)
(map (lambda (x) (eval-expression x env)) rands)) )
plt-2002-2 04/21/23 4.8-15
Interpreter (3).. (let-exp (ids rands body) (let ((args (eval-let-exp-rands rands env))) (eval-expression body(extend-env ids args env)) ) ) ..
(define eval-let-exp-rands (lambda (rands env) (map (lambda (x) (eval-let-exp-rand x env)) rands) ) )(define eval-let-exp-rand (lambda (rand env) (direct-target (eval-expression rand env))) )
plt-2002-2 04/21/23 4.8-16
Interpreter (4).. (app-exp (rator rands) (let ((proc (eval-expression rator env)) (args (eval-rands rands env)) ..
(define eval-rand ; ensure 1-level indirect (lambda (rand env) (cases expression rand (var-exp (id) (indirect-target (let ((ref (apply-env-ref env id))) (cases target (primitive-deref ref) (direct-target (expval) ref) (indirect-target (ref1) ref1) ) ) ) ) (else (direct-target (eval-expression rand env))) ) ) )
plt-2002-2 04/21/23 4.8-17
Strategy(proc (t, u, v, w)
(proc (a, b)
(proc (x, y, z)
set y = 13 x y z
a b 6)
3 v)
5 6 7 8)
a b
t u v w
5 6 7 8
3
6
plt-2002-2 04/21/23 4.8-18
How to execute$ scheme48 -I eopl.image> ,load indir-environment.scm> ,load 3.8.scm> ,load call-by-ref.scm> ,load boilerplate.scm> (run " let a = 3 p = proc (x) set x = 4 in begin (p a); a end“)4
$ cd 3; make 3.8a
plt-2002-2 04/21/23 4.8-19
Usage (1)let y = 0 g = proc (x, y) begin set y = 2; x endin (g +(y,y) y)
call-by-name: parameter bound to thunk returning reference; result is 4.
Jensen’s device for accessing arrays in Algol.
plt-2002-2 04/21/23 4.8-20
Usage (2)let g = let count = 0
in proc ()
begin
set count = add1(count);
count
end
in (proc (x) +(x, x) (g))
call-by-need, lazy evaluation: parameter bound to thunk, replaced on first call; result is 3 by-name, 2 by-need.
plt-2002-2 04/21/23 4.8-21
Terminology
thunk: procedure without arguments encapsulating an operand.
freezing, thawing: creating the thunk, evaluating it.
memoization: the value of the thunk is cached and returned — works in the absence of side-effects.
-reduction in Lambda Calculus, copy rule: replace procedure call by procedure body; in body replace each parameter by corresponding operand.
plt-2002-2 04/21/23 4.8-22
Changes
scanner: remains unchanged.
parser: remains unchanged.
interpreter: new thunk-target, created by eval-rand, evaluated — and possibly replaced — by deref.
Denoted Value = reference(Expressed Value)
Expressed Value = number + procval
plt-2002-2 04/21/23 4.8-23
target(define-datatype target target?
(direct-target
(expval expval?))
(indirect-target
(ref ref-to-direct-target?))
(thunk-target
(exp expression?)
(env environment?))
)
plt-2002-2 04/21/23 4.8-24
ref-to-direct-target?
(define ref-to-direct-target? (lambda (x) (and (reference? x) (cases reference x (a-ref (pos vec) (cases target (vector-ref vec pos) (direct-target (v) #t) (indirect-target (v) #f) (thunk-target (exp env) #t)) ) ) ) )
plt-2002-2 04/21/23 4.8-25
deref(define deref
(lambda (ref)
(cases target (primitive-deref ref)
(direct-target (expval) expval)
(indirect-target (ref1)
(cases target (primitive-deref ref1)
(direct-target (expval) expval)
(indirect-target (p)
(error 'deref "Illegal reference" ref1))
(thunk-target (exp env) (eval-thunk ref1))
) )
(thunk-target (exp env) (eval-thunk ref))
) ) )
plt-2002-2 04/21/23 4.8-26
eval-thunk(define eval-thunk
(lambda (ref)
(cases target (primitive-deref ref)
(thunk-target (exp env)
(let ((val (eval-expression exp env)))
(primitive-setref! ref (direct-target val))
val
) )
(else (eopl:error 'eval-thunk "Impossible!"))
) ) )
call-by-name results if the thunk is not overwritten by the computed value.
plt-2002-2 04/21/23 4.8-27
setref!(define setref! (lambda (ref expval) (let ((ref (cases target (primitive-deref ref) (direct-target (expval1) ref) (indirect-target (ref1) ref1) (thunk-target (exp env) ref) )) ) (primitive-setref! ref (direct-target expval))) ) )
plt-2002-2 04/21/23 4.8-28
Interpreter — call-by-reference(define eval-rand ; ensure 1-level indirect (lambda (rand env) (cases expression rand
(var-exp (id) (indirect-target (let ((ref (apply-env-ref env id))) (cases target (primitive-deref ref) (direct-target (expval) ref) (indirect-target (ref1) ref1)))))
(else (direct-target (eval-expression rand env))) ) ) )
plt-2002-2 04/21/23 4.8-29
Interpreter — call-by-need(define eval-rand ; ensure 1-level indirect (lambda (rand env) (cases expression rand (lit-exp (datum) (direct-target datum)) ; optimize (proc-exp (ids body) (direct-target (closure ids body env))) (var-exp (id) (indirect-target (let ((ref (apply-env-ref env id))) (cases target (primitive-deref ref) (direct-target (expval) ref) (indirect-target (ref1) ref1) (thunk-target (exp env) ref))))) (else (thunk-target rand env))) ) ) )
plt-2002-2 04/21/23 4.8-30
How to execute$ scheme48 -I eopl.image> ,load need-environment.scm> ,load 3.8.scm> ,load call-by-need.scm> ,load boilerplate.scm> (run " let y = 0 g = proc (x, y) begin set y = 2; x end in (g +(y,y) y)“)4$ cd 3; make 3.8b
top related