• No results found

Review TINY interpreter ev ev takes as input an AST of an expression e and an environment env, and returns an AST of a value.

N/A
N/A
Protected

Academic year: 2021

Share "Review TINY interpreter ev ev takes as input an AST of an expression e and an environment env, and returns an AST of a value."

Copied!
24
0
0

Loading.... (view fulltext now)

Full text

(1)

Review – TINY interpreter ev

ev takes as input an AST of an expression e and an environment env, and returns an AST of a value.

(define ev

(lambda (e env) (cond

((eq? (car e) ’&const) ;; e=(&const c) e)

((eq? (car e) ’&var) ;; e=(&var v) (lookup env (cadr e)))

((eq? (car e) ’&lambda) ;; e=(&lambda parms body) (mk-closure env e))

((eq? (car e) ’&if)

(let ((a (cadr e)) ;; e=(&if a b c) (b (caddr e))

(c (cadddr e)))

(ev (if (equal? (ev a env) ’(&const false)) c b) env)))

((eq? (car e) ‘&apply) ;; e=(&apply f args) (let*((f (cadr e))

(args (caddr e)) (fv (ev f env))

(av (map (lambda (a) (ev a env)) args))) (if (and (pair? fv) (eq? (car fv) ’&const))

(delta fv av)

(2)

TINY interpreter ev — basic structure Note:

Just by looking at the function ev we do not know how environments or closures are implemented. ev is said to be representation independent.

(3)

TINY interpreter ev — environments

procedural (functional) representation

(define extend

(lambda (env x v) (lambda (y)

(if (eq? x y) v

(lookup env y))))) (define lookup

(lambda (env y) (env y))) (define extend*

(lambda (env xs vs) (if (null? xs)

env

(extend* (extend env (car xs) (car vs)) (cdr xs)

(4)

TINY interpreter ev — closures list (data) representation

(define mk-closure ;; returns (&closure env parm-list body) (lambda (env v)

(cond

((eq? (car v) ’&lambda)

‘(&closure ,env ,(cadr v) ,(caddr v)))))) (define apply-cl

(lambda (vf va) (cond

((eq? (car vf) ’&closure)

(let ((env (cadr vf)) ;; environment

(p (caddr vf)) ;; parameter list

(b (cadddr vf))) ;; body

(if (= (length p) (length va)) (ev b (extend* env p va))

(5)

TINY interpreter ev — delta

delta is needed to apply a functional constant (our +, −,∗, / operations) to a value. ev uses the

corresponding Scheme operations. If a function symbol such as “+” is encountered, it is looked up in the

environment and the list ‘(&const hf unction+i) is returned. Note that an application of such a function requires all arguments to be constants, i.e., of the form ‘(&const . . .).

(define delta (lambda (f a)

(let ((R (lambda (s) ‘(&const ,s))) (R-1 (lambda (cl)

(cond

((eq? (car cl) ‘&const) (cadr cl))

(else

(error ’delta "non-const args")))))) (R (apply (R-1 f) (map R-1 a))))))

(define interpret-free-var (lambda (x)

‘(&const ,(eval x))))

(6)

Call-by-value closure interpreter evaluate

That’s it! We are now ready to put everything together.

(define evaluate (lambda (m)

(unparse (ev (parse m) empty-env))))

Questions

• What parameter passing style does our interpreter use?

• What is the order of evaluation of the actual parameters for a function application?

(7)

Call-by-name closure interpreter

How do we have to modify our interpreter to implement call–by–name instead of call–by–value?

Key idea:

If the argument of an application is not a value, we can postpone its evaluation by wrapping it into a closure that treats the argument expression as a lambda

abstraction without parameters. Such a “special”

closure is called a thunk. If we need the “real” value of an argument expression, we just evaluate the thunk in its environment.

Note that now our environment can contain three types of values, namely constants, closures, and thunks.

(8)

Dynamically-scoped interpreter

How do we have to modify our interpreter to implement call-by-value and dynamic scoping?

Key idea:

The difference between static and dynamic scoping in TINY is with respect to the rules how closures are applied.

• static ⇒ use environment within the closure

• dynamic ⇒ ignore environment within the closure and use current environment at the application (remember capturing!).

ev[ ((lambda (x) ((lambda (z)

((lambda(x) (z x)) 3))

(lambda (y) (+ x y)) )) 1)]

ev[ ((lambda (x)

((lambda(x) ((lambda (y) (+ x y)) x)) 3))

(9)

Closure interpreters

• Interpreters are important tools to understand and specify the semantics of programming languages. • Closures are an important concept for any language

with functions as first order objects and static

scoping. It gives us an idea what “price” we have to pay if we want first–order functions or a particular parameter passing style.

• So far, we only talked about “pure” functional

languages without a store and assignment (no side effects). How to extend our interpreters to deal with a store?

– Introduce a store as a function from addresses to values: store = Memory Locations → V alues

– Modify environments to map names to memory locations: ρ ∈ Env = V ariables → Memory Locations

– Modify ev to take one more argument: (define ev (lambda (e env store) . . .)). In addition, ev will return a value and a store. – Of course, there is a lot more work to be done

(10)

Part IV: Procedural Language Issues Procedures: A Control Abstraction

• A block of code that can be called (imperative)

• A lambda expression (functional)

• A clause (logic programming)

(11)

Components of a Procedure

1. Name

2. Formal parameters, optionally with types • parameter (formal parameter)

Local variable whose value is received from caller • argument (actual parameter)

The info passed from caller to callee

3. Body, which is a syntactic construct in the language: • Block, i.e., declarations and statements

(imperative)

• Expression (functional)

• Conjunction of terms (logic programming)

(12)

Procedure Implementation Issues

The general notion of a procedure leaves a number of points unspecified:

• How to pass parameters when the procedure is called • How to maintain local state and control information • How to access non-local names within a procedure

(13)

Parameter Passing

Matching arguments with parameters: 1. Positional association:

• Arguments are associated with parameters left to right

2. Keyword association:

• Arguments are given tags, e.g.,

procedure plot (x,y: in real; penup: in boolean)

...

plot(0.0, 0.0, penup=>true)

plot(penup=>true, x=>0.0, y=>0.0)

3. Optional arguments or different number of arguments:

• E.g., C printf(. . . )

• Extra arguments are packaged into some structure

(14)

Passing Modes

How to treat arguments (pass-by-x/call-by-x): 1. Pass by value

(C, C++, Pascal, Ada, Scheme, Algol68) 2. Pass by value-result

(Ada)

3. Pass by reference

(C++ with &, Fortran77/90, Pascal with var, COBOL)

4. Pass by name (Algol 60)

(15)

Example for Passing Modes

{ c : array[1..10] of integer; m,n integer;

procedure r (i , j : integer ) begin i := i + 1; j := j + 2 end r; ... m := 2; n := 3; r(m,n); // call 1 write m , n ; // print 1 m := 2; c[1] := 1; c[2] := 4; c[3] := 8; r(m,c[m]); // call 2 write m , c[m]; // print 2 }

(16)

Pass by Value

• Initial values of parameters copied from current values of arguments

• Final values of parameters are “thrown away” • Example: call 1: i = 2 j = 3 print 1: call 2: i = 2 j = 4 print 2: Discussion:

+ Arguments protected from changes in procedure – Requires copying of values: costs time and space,

(17)

Pass by Value-Result (Copy-In / Copy-Out) • Initial values of parameters copied from current

values of arguments

• Final values of parameters copied back to arguments • call 1:

– initial: i = 2 j = 3 – final: i = 3 j = 5

– return: m and n set to 3 and 5 • print 1:

• call 2:

– initial: i = 2 j = 4 – final: i = 3 j = 6

– return: which element of c is modified, c[2] or

c[3]? • print 2:

– if c[2] is modified: – if c[3] is modified:

(18)

Problem with Pass by Value-Result Calls Order of assignments and address computations is important.

Options:

1. Perform return address computations at call time: On return from call 2:

m set to 3; c[2] set to 6 print 2:

2. Perform return address computations at return time: On return from call 2:

m set to 3; c[3] set to 6 print 2:

(19)

Pass by Reference

• Parameters are pointers to the “arguments”.

• Address computations are performed at procedure call.

• Changes to the parameters inside procedure body are thus changes to the “arguments”

Example: • call 1:

– initial: i = 2 j = 3 – final: i = 3 j = 5 – return: m set to 3, n set to 5 • print 1:

• call 2:

– initial: i = 2 j = 4 – final: i = 3 j = 6

– return: m set to 3, c[2] set to 6 • print 2:

(20)

Pass by Reference

• Benefit: No copying for variables

• Problem: allow redefinition of expressions and constants?

• Problem: Leads to aliasing

– two or more visible names for same location – can cause to side effects not visible from code

itself

Question: What if actual parameter is an expression such as 2+3?

(21)

Aliasing

{ y : integer ;

procedure p ( x : integer ) begin x := x + 1; x := x + y end p; ... y := 2; p(y); write y } Pass by Reference:

• The identifiers x and y refer to the same location in call of p

• Result of “write y”? Pass by Value-Result:

• The identifiers x and y refer to different locations in call of p

(22)

More Aliasing

{ i, j, k : integer ;

procedure q ( a, b : integer ) begin a := i * b; b := i * b; end q; ... i := 2; j := 3; k := 4; q(i,j); q(k,k); }

• First call has global-formal aliases: – a and i

– b and j

• Second call has formal-formal alias: – a and b

(23)

Pass by Name

• A “name” for the argument expression is passed into procedure. Note: the expression is not evaluated. • Like textual substitution of argument in procedure • Thus expression evaluations are done whenever

parameter is used

• Example:

– call 1: m set to 3, n set to 5 – print 1:

– call 2: m set to 3, but then c[3] set to 10 – print 2:

Discussion

• Benefits: same as pass by reference • Problems: Inefficient, requires a thunk:

– essentially a little program that represents argument is passed

(24)

Things to do

• Read Sethi Chs. 5.3 – 5.7

References

Related documents

between CFSR and simulated seasonal temperature using WRFfor 1997 and 1998. The 8-station mean values in winter and summer are plotted as dashed red lines in Fig. Note that Fig. The

The YOGAKSHENA i.e. Risk and Safety has been the oldest term of insurance used in the Rigveda for insurance. The claim settlement ratio indicates the number of

 When a flower is cut, it no longer has its roots, but the stem of the flower still "drinks" up the water and provides it to the leaves and flowers.  Coloring the

The diagram below shows the data flow between the Windows Services running On-Prem and the Windows Azure Components of PI Cloud Connect leveraging the Azure Service Bus Relay.

position, temporarily place the wired remote on the upper transport handle, then position the HFL directly behind the fallen person, with the mounting ramp seat as close to

The committee read, noted, considered public comment, edited, and approved the recommendations and information as submitted by the working group. A discussion occurred regarding

Contract Security Classification Specification required by DoD 5220.22-4, Industrial Security Regulation and the National Industrial Security Program Operating Manual (NISPOM) is

For more detailed information on the process, and what it may or may not do for you, refer to the resource guide titled Expunging Criminal Records: Step by Step that is provided by