Recursive Procedures and Scopes

Slides:



Advertisements
Similar presentations
Cs784(Prasad)L10Rec1 Implementing Recursion. cs784(Prasad)L10Rec2 let insufficient for recursion ( (let((fact(lambda (n) (if (zero? n) 1 (* n (fact (-
Advertisements

Semantics of PLs via Interpreters: Getting Started CS784: Programming Languages Prabhaker Mateti.
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
Assignments and Procs w/Params EOPL3 Chapter 4. Expressible vs. Denotable values Expressible Values –the language can express and compute these –represented.
Control-Flow Graphs & Dataflow Analysis CS153: Compilers Greg Morrisett.
1 How to transform an analyzer into a verifier. 2 OUTLINE OF THE LECTURE a verification technique which combines abstract interpretation and Park’s fixpoint.
Recap 1.Programmer enters expression 2.ML checks if expression is “well-typed” Using a precise set of rules, ML tries to find a unique type for the expression.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Cs784(TK)1 Semantics of Procedures and Scopes. Kinds of Scope Static or Lexical scope –determined by structure of program –Scheme, C++, Java, and many.
(1) ICS 313: Programming Language Theory Chapter 10: Implementing Subprograms.
Names and Scopes CS 351. Program Binding We should be familiar with this notion. A variable is bound to a method or current block e.g in C++: namespace.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Cse321, Programming Languages and Compilers 1 6/19/2015 Lecture #18, March 14, 2007 Syntax directed translations, Meanings of programs, Rules for writing.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
SchemeCOP Introduction to Scheme. SchemeCOP Scheme Meta-language for coding interpreters –“ clean ” semantics Scheme = LISP + ALGOL –simple.
EOPL3: Section 3.3 PROC and App B: SLLGEN
Cs784(tk)1 Implementing Recursion. Recap: Goals Experimenting with PL design alternatives Scoping, parameter passing, arrays,... Runnable prototype of.
Cs7100(Prasad)L8Proc1 Procedures. cs7100(Prasad)L8Proc2 Primitive procedures  etc User-defined procedures –Naming a sequence of operations.
3.5 Procedures Recall procedures (functions) in Scheme: (let ((f (lambda(y z) (+ y (- z 5))) (f 2 28)) We would like something similar in our toy language:
1 Scope Scope describes the region where an identifier is known, and semantic rules for this.
Plt /17/ Environment-Passing Interpreters Programming Language Essentials 2nd edition Chapter 3.8 Parameter-Passing Variations.
Implementing Subprograms What actions must take place when subprograms are called and when they terminate? –calling a subprogram has several associated.
Comp 311 Principles of Programming Languages Lecture 4 The Scope of Variables Corky Cartwright September 3, 2008.
CSE 130 : Spring 2011 Programming Languages Ranjit Jhala UC San Diego Lecture 5: Functions and Closures.
CS314 – Section 5 Recitation 9
Operational Semantics of Scheme
Abstract Syntax cs7100 (Prasad) L7AST.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2017.
6.001 SICP Compilation Context: special purpose vs. universal machines
The interpreter.
Implementing Subprograms
Introduction to Scheme
Interpreters Study Semantics of Programming Languages through interpreters (Executable Specifications) cs7100(Prasad) L8Interp.
Principles of programming languages 4: Parameter passing, Scope rules
Subprograms The basic abstraction mechanism.
Corky Cartwright January 18, 2017
Implementing Recursion
Env. Model Implementation
SSA in Scheme Static single assignment (SSA) :
Original material by Eric Grimson
5.4.1: Implementation Method Invocation
Semantics of PLs via Interpreters: Getting Started
CSE 3302 Programming Languages
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2018.
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
The Metacircular Evaluator
Abstract Syntax Prabhaker Mateti 1.
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Zach Tatlock Winter 2018.
Procedures App B: SLLGEN 1.
3.7 Variable Assignment Recall instance variables in Python:
3.4 Local Binding Recall Scheme's let: > (let ((x 5)‏ (y 6))
The Metacircular Evaluator (Continued)
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2016.
Streams, Delayed Evaluation and a Normal Order Interpreter
Abstract Syntax cs7100 (Prasad) L7AST.
UNIT V Run Time Environments.
3.6 Interpreter: Recursion
6.001 SICP Variations on a Scheme
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Autumn 2017.
Assignments cs7100(Prasad) L13Assg.
6.001 SICP Interpretation Parts of an interpreter
Assignments and Procs w/Params
CSE 341 Lecture 11 b closures; scoping rules
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Spring 2019.
Presentation transcript:

Recursive Procedures and Scopes EOPL3 Sections 3.4 - 3.7 1

The LETREC Language All of PROC, plus … Concrete: AST: Expression in Expression AST: proc-body letrec-body) CS7100(pm) 2 2

value of a letrec expression bound-var proc-body letrec-body) ρ) = (value-of letrec-body bound-var proc-body ρ)) CS7100(pm) 3 3

(extend-env-rec pnm bvar pbdy ρ) Let ρ1 == (extend-env-rec proc-name bound-var proc-body ρ) (procedure bound-var proc-body ρ1)) (apply-env ρ1 var) = (apply-env ρ var) CS7100(pm) 4 4

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?))) CS7100(pm) 5 5

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)))))) CS7100(pm) 6 6

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 …” . CS7100(pm) 7 7

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)))) CS7100(pm) 8 8

Scoping and Binding references declarations lexical scoping rules (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 rules CS7100(pm) 9 9

Kinds of Scope Static or Lexical scope Dynamic scope Global 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 CS7100(pm) 10 10

Scoping : Free (non-local) Variables proc main() int x := 5; proc q() { x := x + 1;} proc r() {int x := 0; q();} {r(); print(x); } Static scoping x -> x output: 6 Dynamic scoping output: 5 CS7100(pm) 11 11

Static Scoping x -> x 30 Dynamic Scoping x -> x 23 x -> x let x = 15 in let f = proc () x in ( let x = 8 in (f) ) + (f) Static Scoping x -> x 30 Dynamic Scoping x -> x 23 x -> x CS7100(pm) 12 12

Fig 3.13 Contour diagram CS7100(pm) 13 13

Figure 3.14 Contour diagram CS7100(pm) 14 14

Binding Rules A variable declared by a proc is bound when the procedure is applied. = (value-of body (extend-env var val ρ)) A let-variable is bound by the value of its right-hand side. = (value-of body (extend-env var val ρ)) A variable declared by a letrec is bound using its right-hand side as well. bound-var proc-body ρ)) CS7100(pm) 15 15

lexical depth # of contours crossed zero-based indexing (lambda (x) ( (lambda (a) (x a)) x)) (nameless-lambda ( (#1 #0)) #0)) CS7100(pm) 16 16

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. CS7100(pm) 17 17

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)))))) CS7100(pm) 18 18

Fg 3.16 lexical-address translator (define translation-of (lambda (exp senv) (diff-exp (exp1 exp2) (diff-exp (translation-of exp1 senv) (translation-of exp2 senv))) … altogether 8 cases … (else (report-invalid-source-expression exp)) ))) Senv = Listof(Sym) Lexaddr = N CS7100(pm) 19 19

translation-of zero?-exp (zero?-exp (exp1) (zero?-exp (translation-of exp1 senv))) CS7100(pm) 20 20

translation-of if-exp (if-exp (exp1 exp2 exp3) (if-exp (translation-of exp1 senv) (translation-of exp2 senv) (translation-of exp3 senv))) CS7100(pm) 21 21

translation-of var-exp (var-exp (var) (nameless-var-exp (apply-senv senv var))) CS7100(pm) 22 22

translation-of let-exp (let-exp (var exp1 body) (nameless-let-exp (translation-of exp1 senv) (translation-of body (extend-senv var senv)))) CS7100(pm) 23 23

translation-of proc-exp (proc-exp (var body) (nameless-proc-exp (translation-of body (extend-senv var senv)))) CS7100(pm) 24 24

translation-of call-exp (call-exp (rator rand) (call-exp (translation-of rator senv) (translation-of rand senv))) CS7100(pm) 25 25

Our top-level procedure (define run (lambda (string) (value-of-program (translation-of-program (scan&parse string))))) CS7100(pm) 26 26

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 = (value-of body (extend-env var val ρ)) page 79 = (value-of body (extend-nameless-env val ρ)) page 98 CS7100(pm) 27 27

procedure datatype (define-datatype proc proc? (procedure (body expression?) (saved-nameless-env nameless-environment?))) CS7100(pm) 28 28

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)))))) CS7100(pm) 29 29

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))))) CS7100(pm) 30 30

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))) CS7100(pm) 31 31

value-of-program (define value-of-program (lambda (pgm) (cases program pgm (a-program (exp1) (value-of exp1 (init-nameless-env)))))) CS7100(pm) 32 32

extra slide if time permits ======================================================================================================================================================================================================================================================== CS7100(pm) 33 33

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) ) )) CS7100(pm) 34 34

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)) ))) CS7100(pm) 35 35

Processing Procedure Invocations >(run "let x = 1 in let f = proc () x in (f)") 1 let f = proc (x) x in (f 2)") 2 Static scoping x = 5 in (f)") Dynamic scoping let f = proc () x x = 5 5 CS7100(pm) 36 36

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. Recursion easy to implement in dynamically scoped language: (let f = proc (x) if 0 then 0 else f(x-1) in (f 5)) More interestingly, consider a mutually recursive definition. CS7100(pm) 37 37

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 CS7100(pm) 38 38

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. CS7100(pm) 39 39

Dyn Binding Can be Difficult Exercise 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 = 3 in 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? CS7100(pm) 40 40

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 CS7100(pm) 41 41

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. CS7100(pm) 42 42