Recursive Procedures and Scopes

42
Recursive Procedures and Scopes EOPL3 Sections 3.4 - 3.7

description

Recursive Procedures and Scopes. EOPL3 Sections 3.4 - 3.7. The LETREC Language. All of PROC, plus … Concrete: Expression :: = letrec Identifier (Identifier) = Expression in Expression AST: letrec-exp (proc-name bound-var proc-body letrec-body). value of a letrec expression. - PowerPoint PPT Presentation

Transcript of Recursive Procedures and Scopes

Page 1: Recursive Procedures and Scopes

Recursive Procedures and Scopes

EOPL3 Sections 3.4 - 3.7

Page 2: Recursive Procedures and Scopes

2

The LETREC Language

• All of PROC, plus …• Concrete:

– Expression :: = letrec Identifier (Identifier) =

Expression in Expression• AST:

– letrec-exp (proc-name bound-varproc-body letrec-body)

CS784(pm)

Page 3: Recursive Procedures and Scopes

value of a letrec expression

(value-of(letrec-exp proc-name

bound-var proc-body letrec-body)ρ)

= (value-of letrec-body(extend-env-rec proc-name

bound-var proc-body ρ))

CS784(pm) 3

Page 4: Recursive Procedures and Scopes

(extend-env-rec pnm bvar pbdy ρ)

• Let ρ1 == (extend-env-rec proc-name bound-var proc-body ρ)

• (apply-env ρ1 proc-name)= (proc-val

(procedure bound-var proc-body ρ1))

• (apply-env ρ1 var) = (apply-env ρ var)

CS784(pm) 4

Page 5: Recursive Procedures and Scopes

environment datatype(define-datatype environment environment?

(empty-env)(extend-env(var identifier?)(val expval?)(env environment?))(extend-env-rec(p-name identifier?)(b-var identifier?)(body expression?)(env environment?)))

CS784(pm) 5

Page 6: Recursive Procedures and Scopes

apply-env(define apply-env (lambda (env search-var)

(cases environment env(empty-env () (report-no-binding-found search-var))(extend-env (saved-var saved-val saved-env) (if (eqv? saved-var search-var)saved-val(apply-env saved-env search-var)))(extend-env-rec (p-name b-var p-body saved-env) (if (eqv? search-var p-name)(proc-val (procedure b-var p-body env))(apply-env saved-env search-var))))))

CS784(pm) 6

Page 7: Recursive Procedures and Scopes

7

Exercise 3.35• “The representations we have seen so far are inefficient, because they

build a new closure every time the procedure is retrieved. But the closure is the same every time. We can build the closures only once, by putting the value in a vector of length 1 and building an explicit circular structure, like …”

• .

CS784(pm)

Page 8: Recursive Procedures and Scopes

Exercise 3.35: extend-env-rec

(define extend-env-rec(lambda (p-name b-var body saved-env)(let ((vec (make-vector 1)))(let ((new-env (extend-env p-name vec saved-env)))(vector-set! vec 0(proc-val (procedure b-var body new-env)))new-env))))

CS784(pm) 8

Page 9: Recursive Procedures and Scopes

Scoping and Binding

• references– (f x y)– f, x, and y

• declarations– (lambda (x) (+ x 3))– (let ((x (+ y 7))) (+ x 3))

• y, and second x are refs• first x is a declaration

• lexical scoping rulesCS784(pm) 9

Page 10: Recursive Procedures and Scopes

Kinds of Scope• Static or Lexical scope

– determined by structure of program– Scheme, C++, Java, and many compiled languages

• Dynamic scope– determined by path of execution– Lisp dialects, Perl, and many interpreted languages

• Global Scope– File scope

• Local Scope– Block

• Body of a procedure• Body of a loop

• Scope alters the meaning

CS784(pm) 10

Page 11: Recursive Procedures and Scopes

CS784(pm) 11

proc main()int x := 5; proc q() { x := x + 1;}

proc r() {int x := 0;

q(); }{ r(); print(x); }.

Scoping : Free (non-local) Variables• Static scoping x -> xoutput: 6

• Dynamic scoping

x -> xoutput: 5

Page 12: Recursive Procedures and Scopes

CS784(pm) 12

let x = 15in let f = proc () x in ( let x = 8 in (f) ) + (f)

Static Scoping x -> x 30Dynamic Scoping x -> x 23 x -> x

Page 13: Recursive Procedures and Scopes

Fig 3.13 Contour diagram

CS784(pm) 13

Page 14: Recursive Procedures and Scopes

Figure 3.14 Contour diagram

CS784(pm) 14

Page 15: Recursive Procedures and Scopes

Binding Rules1. A variable declared by a proc is bound when the procedure is

applied. – (apply-procedure (procedure var body ρ) val)

= (value-of body (extend-env var val ρ))2. A let-variable is bound by the value of its right-hand side.

– (value-of (let-exp var val body) ρ)= (value-of body (extend-env var val ρ))

3. A variable declared by a letrec is bound using its right-hand side as well.

– (value-of (letrec-exp proc-namebound-var proc-body letrec-body) ρ)

= (value-of letrec-body (extend-env-rec proc-namebound-var proc-body ρ))

CS784(pm) 15

Page 16: Recursive Procedures and Scopes

lexical depth# of contours crossed

(lambda (x)(

(lambda (a)(x a))

x))

zero-based indexing

(nameless-lambda(

(nameless-lambda(#1 #0))

#0))

CS784(pm) 16

Page 17: Recursive Procedures and Scopes

The Translator

• Source: var-exp, let-exp, …• Target: nameless-var-exp, nameless-let-exp• translation-of: handles expressions• translation-of-program: handles programs.• translation-of-program runs translation-of

in a suitable initial static environment.

CS784(pm) 17

Page 18: Recursive Procedures and Scopes

translation-of-program

(define translation-of-program(lambda (pgm)(cases program pgm(a-program (exp1)(a-program (translation-of exp1 (init-senv)))))))

(define init-senv (lambda ()(extend-senv ’i(extend-senv ’v(extend-senv ’x(empty-senv))))))

CS784(pm) 18

Page 19: Recursive Procedures and Scopes

Fg 3.16 lexical-address translator(define translation-of

(lambda (exp senv) (cases expression exp(const-exp (num) (const-exp num))(diff-exp (exp1 exp2)(diff-exp(translation-of exp1 senv)(translation-of exp2 senv)))… altogether 8 cases …(else(report-invalid-source-expression exp)) )))

CS784(pm) 19

Page 20: Recursive Procedures and Scopes

20

translation-of zero?-exp

(zero?-exp (exp1)(zero?-exp

(translation-of exp1 senv)))

CS784(pm)

Page 21: Recursive Procedures and Scopes

translation-of if-exp

(if-exp (exp1 exp2 exp3)(if-exp

(translation-of exp1 senv)(translation-of exp2 senv)(translation-of exp3 senv)))

CS784(pm) 21

Page 22: Recursive Procedures and Scopes

translation-of var-exp

(var-exp (var)(nameless-var-exp(apply-senv senv var)))

CS784(pm) 22

Page 23: Recursive Procedures and Scopes

translation-of let-exp

(let-exp (var exp1 body)(nameless-let-exp

(translation-of exp1 senv)(translation-of body

(extend-senv var senv))))

CS784(pm) 23

Page 24: Recursive Procedures and Scopes

translation-of proc-exp

(proc-exp (var body)(nameless-proc-exp

(translation-of body(extend-senv var

senv))))

CS784(pm) 24

Page 25: Recursive Procedures and Scopes

translation-of call-exp

(call-exp (rator rand)(call-exp

(translation-of rator senv)(translation-of rand senv)))

CS784(pm) 25

Page 26: Recursive Procedures and Scopes

Our top-level procedure

(define run(lambda (string)

(value-of-program(translation-of-program

(scan&parse string)))))

CS784(pm) 26

Page 27: Recursive Procedures and Scopes

nameless environments• nameless-environment? : SchemeVal → Bool• empty-nameless-env : () → Nameless-env• extend-nameless-env : Expval × Nameless-env → Nameless-env• apply-nameless-env : Nameless-env × Lexaddr → DenVal

• (apply-procedure (procedure var body ρ) val)= (value-of body (extend-env var val ρ)) page 79

• (apply-procedure (procedure body ρ) val)= (value-of body (extend-nameless-env val ρ)) page 98

CS784(pm) 27

Page 28: Recursive Procedures and Scopes

procedure datatype

(define-datatype proc proc?(procedure

(body expression?)(saved-nameless-env

nameless-environment?)))

CS784(pm) 28

Page 29: Recursive Procedures and Scopes

apply-procedure

(define apply-procedure(lambda (pc val)

(cases proc pc (procedure (body saved-nameless-

env)(value-of body

(extend-nameless-env val saved-nameless-

env))))))CS784(pm) 29

Page 30: Recursive Procedures and Scopes

redefine value-of(define value-of

(lambda (exp nameless-env)(cases expression exp(const-exp (num) ...as before...)(diff-exp (exp1 exp2) ...as before...)(zero?-exp (exp1) ...as before...)(if-exp (exp1 exp2 exp3) ...as before...)(call-exp (rator rand) ...as before...)… next slide …(else (report-invalid-translated-expression exp)))))

CS784(pm) 30

Page 31: Recursive Procedures and Scopes

redefine value-of

(nameless-var-exp (n)(apply-nameless-env nameless-env n))

(nameless-let-exp (exp1 body)(let ((val (value-of exp1 nameless-env)))

(value-of body(extend-nameless-env val nameless-env))))

(nameless-proc-exp (body)(proc-val

(procedure body nameless-env)))

CS784(pm) 31

Page 32: Recursive Procedures and Scopes

value-of-program

(define value-of-program(lambda (pgm)

(cases program pgm(a-program (exp1)

(value-of exp1(init-nameless-

env))))))

CS784(pm) 32

Page 33: Recursive Procedures and Scopes

extra slide if time permits

• ========================================================================================================================================================================================================================================================

CS784(pm) 33

Page 34: Recursive Procedures and Scopes

34

Procedure Invocations• Dynamic scoping(define (eval-expression exp env) (cases expression exp (app-exp (rator rands) . . . (let ((proc (eval-expression rator env)) (args (eval-rands rands env))) (if (procval? proc) (apply-procval proc args env) (eopl:error 'eval-expression "Applying non-procedure ~s" proc) )))

CS784(pm)

Page 35: Recursive Procedures and Scopes

35

Processing Procedure Invocations

• Dynamic scoping• (define (apply-procval proc args c-env)

(cases procval proc (procv (ids body) (eval-expression body (extend-env ids args c-env)) )))

CS784(pm)

Page 36: Recursive Procedures and Scopes

36

Processing Procedure Invocations

>(run "let x = 1 inlet f = proc () x in(f)")

1>(run "let x = 1 in

let f = proc (x) x in (f 2)")2Static scoping>(run "let x = 1 in

let f = proc () xx = 5in (f)")

1Dynamic scoping>(run "let x = 1 in

let f = proc () x x = 5in (f)")

5

CS784(pm)

Page 37: Recursive Procedures and Scopes

37

Implementing Dynamic Scoping

• The value of variable x is the last value bound to x. => stack discipline– Deep binding

• Use a global stack for all variables– Shallow binding

• Use a separate stack for each variable• Implementing recursion is trivial.• Meaning of a call depends on the context.CS784(pm)

Page 38: Recursive Procedures and Scopes

Lexical Scope Pros and Cons

• Scope of names is known to the compiler.• Permits type checking by compiler• Easily check for uninitialized variables• Easier to analyze program correctness• Recursion is harder to implement

CS784(pm) 38

Page 39: Recursive Procedures and Scopes

Dynamic Scope Pros and Cons• Meaning of variables known only at run-time.

– Cannot perform type checking before execution– Programs are flexible, but harder to understand

• Easy to implement recursion• Renaming in the caller can effect the semantics of a program

– Locality of formals destroyed.– if renamed parameter now captures a free variable in the called

function. – Recall the interpretation of a free variable in a function body can

change based on the context (environment) of a call.

CS784(pm) 39

Page 40: Recursive Procedures and Scopes

Dyn Binding Can be DifficultExercise 3.29: … dynamic binding may be exceptionally difficult to understand.

For example, under lexical binding, consistently renaming the bound variables of a procedure can never change the behavior of a program: we can even remove all variables and replace them by their lexical addresses, as in section 3.6. But under dynamic binding, this transformation is unsafe.

For example, under dynamic binding, the procedure proc (z) a returns the value of the variable a in its caller’s environment. Thus, the program

let a = 3in let p = proc (z) a

in let f = proc (x) (p 0) in let a = 5 in (f 2)

returns 5, since a’s value at the call site is 5. What if f’s formal parameter were a?

CS784(pm) 40

Page 41: Recursive Procedures and Scopes

41

Application of Dynamic Scoping

• Exception Handling– provide a separate construct in statically scoped

language• Setting Local Formatting Parameters• Input-Output Redirection

– avoids passing parameters explicitly through “intermediate” procedures

CS784(pm)

Page 42: Recursive Procedures and Scopes

Dyn Binding Can be Powerful

• Exercise 3.37 With dynamic binding, recursive procedures may be bound by let; no special mechanism is necessary for recursion. Test the following

let fact = proc (n) add1(n)in let fact = proc (n) if zero?(n) then 1 else *(n,(fact -

(n,1)))in (fact 5)

using both lexical and dynamic binding.CS784(pm) 42