Você está na página 1de 16

Func%onal

and Logic
Programming
Lecture 7 - Expression Evalua%on
Context & Environment Model
!

Yotam Harchol
Fall 2015

Todays Agenda

Expression Evalua0on
Context for Evalua0on
Environment Model
Exercise 7

Expression Evalua%on
Expression deni0on:

expr = (operator operand operand)


operator = [+ - * /]
operand = a number
!

Examples:
(+ 1 2)
(* 7 8)
3

Exercise 1.1

Write the func0on (eval1 expr)


The func0on receives an expression and evaluates its value

Expression Evalua%on
Recursive expression deni0on:

expr = (operator operand operand)


operator = [+ - * /]
operand = a number | expr
!

Examples:
(+ 1 (* 7 8))
(* (+ 1 2) (/ (+ 3 1) 2))
5

Exercise 1.2

Write the func0on (eval2 expr)


The func0on receives an expression (may be recursive) and
evaluates its value

Context for Evalua%on


Recursive expression deni0on:

expr = (operator operand operand)


operator = [+ - * /]
operand = a number | a symbol | expr
!

Examples:
(+ a (* b c))
(* (+ 1 x) (/ y z))

What are the values of these symbols?

Context

Context is a dic0onary that maps symbols to values


An expression that uses symbols should be evaluated under the
presence of a certain context, with which the values of the symbols
can be looked-up

Exercise 2.1

Dene an empty dic0onary as an empty list


Dic0onary element is a two-elements list

Example: ((a 4) (b 7) (x 2) (y 6) (z 2))


Write the func0on (dict-put key value dict)
That adds a pair of <key, value> to the dic0onary dict

The assoc func%on

Used to lookup elements in a dic0onary:

(assoc key dict)


Assuming dict is a list of pairs (can be also a list of lists), assoc
returns the rst pair (or list...) whose car is equal to key
Example:
(assoc b ((a 1) (b 2) (c 3))) will return (b 2)

10

Exercise 2.2

Write the func0on (dict-get key dict)


That returns the value associated to key in the dic0onary dict
(or not-found if there is no such key in the dic0onary)

11

Exercise 3

Write the func0on (eval3 expr dict)


The func0on receives an expression (may be recursive) and a
context, and evaluates expressions value according to given
context

12

Context
Context is the dictionary that
helps the interpreter to
translate from symbols to
values on the Eval stage
On Apply stage, a new, nested
function context is created

Global Context

+, -, /, *, quo0ent,
if, lambda,
#t, #f,

User dened
contexts

Program Context

First level dened


symbols

Inner contexts

Func0on Context

Parameter
Argument couples

Inner contexts

Inner Context

!
..

Param/Args


Inner contexts

13

Context
A new context is created when a lambda expression is
applied
The new context contains the bindings of parameters
and arguments - symbols to values
Dene adds a binding to current context
Let is lambda - so it creates a new context...

14

Environment Model

Consider the following code:


(define foo (lambda (x y) (+ x y)))
(define goo (lambda (a b) (* a (foo a b))))
(goo 1 2)

Lets see how the interpreter executes it...

15

Environment Model
(define a 3)
(define foo (lambda (x y) (+ x y a)))
(define goo (lambda (a b) (* a (foo a b))))
(goo 1 2)
System Context

+:
-:
*:
/:

primitive
primitive
primitive
primitive

proc."
proc."
proc."
proc.

User Context

a: 3"
foo: user proc."
goo: user proc.

parameters: x, y
body: (+ x y a)

parameters: a, b
body: (* a (foo a b))

(goo ...) Call Context

a: 1"
b: 2

Static Context:
Function is evaluated
in the context where
it was defined

(foo ...) Call Context

x: 1"
y: 2

So far, we always assumed that we use the static context model


16

Context - Sta%c vs. Dynamic


Sta%c context:
Func0ons body is evaluated in the context in which it
was dened:
(dene pi 3.14)
(dene (circle-area r)
(* pi r r))
!

(let ((r1 10) (r2 5) (pi 7))


(+ (circle-area r1) (circle-area r2)))
17

Context - Sta%c vs. Dynamic


Dynamic context:
Func0ons body is evaluated in the context in which it is
applied:
(dene pi 3.14)
(dene (circle-area r)
(* pi r r))
!

(let ((r1 10) (r2 5) (pi 7))


(+ (circle-area r1) (circle-area r2)))
18

Context - Sta%c vs. Dynamic


Sta%c context:
Func0ons body is evaluated in the context in
which it was dened
!

Dynamic context:
Func0ons body is evaluated in the context in
which it is applied
19

Environment Model
(define a 3)
(define foo (lambda (x y) (+ x y a)))
(define goo (lambda (a b) (* a (foo a b))))
(goo 1 2)
System Context

+:
-:
*:
/:

primitive
primitive
primitive
primitive

proc."
proc."
proc."
proc.

User Context

a: 3"
foo: user proc."
goo: user proc.

parameters: x, y
body: (+ x y a)

parameters: a, b
body: (* a (foo a b))

(goo ...) Call Context

a: 1"
b: 2

Static Context:
Dynamic
Context:
Functionisisevaluated
evaluated
Function
in
in the
thecontext
contextwhere
where

it itwas
defined
is applied

(foo ...) Call Context

x: 1"
y: 2

Dr. Racket interpreter uses static context model


20

Context - Sta%c vs. Dynamic


(dene r 0.04)
(dene (capitalize amount years)
(* amount (expt (+ 1 r) years)))
!

Using dynamic
context - what are
the values of the
symbols in blue?

(let ((r 0.05)


(years 10))
(capitalize 100000 years))
!

And now when


executing this call?

(capitalize 100000 10)


21

Lambda Expression
We said that calling to (lambda (...) (...)) returns a black
box which is an internal representa2on of a func2on
!

Whats in this black box?


List of parameters
Body
Reference to a context (which context?)
22

Evalua%ng Lambda Expression


We now dene an expression as follows:

expr = symbol | number | list


list = (func) | (func expr) | (func expr expr) | (func expr expr expr) | ...
func = + | - | * | / | lambda-expr
lambda-expr = (lambda params body)
params = a list of symbols
body = expr
Examples:
7
(+ 1 2)
((lambda (x y z) (+ x y z)) 7 8 9)
23

Evalua%ng Lambda Expression


When an expression begins with a lambda expression
(such as (lambda (x y z) (+ x y z))), evaluator should:
1. Evaluate the arguments
2. Apply the func0on:
2.1. Bind parameters to evaluated arguments and
add the new bindings to the context (crea0ng a new
context)
2.2. Evaluate the body of the lambda expression in
the new context
24

Exercise 4

Write the func0on (eval4 expr ctx)


The func0on receives an expression (as dened in the two
previous slides) and a context, and evaluates expressions value
according to given context ctx

* For now, assume func0ons can only get a xed number of arguments
** Note that the current expression deni0on does not allow passing func0ons as arguments

25

Ques%on

What is the context model of the eval4 func0on?


(i.e. sta0c context / dynamic context?)

26

Evalua%ng Lambda Expression


We now dene an expression as follows:

expr = symbol | number | list | func


list = (func) | (func expr) | (func expr expr) | (func expr expr expr) | ...
func = symbol-primi%ve | symbol-lambda | lambda-expr
symbol-primi%ve = a symbol that represents a primi%ve func%on
symbol-lambda = a symbol that represents a lambda expression in context
lambda-expr = (lambda params body)
params = a list of symbols
body = expr

27

Evalua%ng Lambda Expression


Main dierence from before:
In the eval4 version, a lambda expression was
immediately invoked aper deni0on
Now, a func0on can be passed as a parameter and
therefore get stored in the context (upon binding).
Then, it can be invoked later on some arguments
Why does it maqer?
What is the context model now?
What should we store in context as the func4on?
28

Evalua%ng Lambda Expression

Example code:
((lambda (foo)
((lambda (pi)
(foo 5))
10))
(lambda (r) (* pi r r)))

(let ((foo (lambda (r) (* pi r r))))


(let ((pi 10))
(foo 5)))

What is the result of evalua0on of this code?

29

Exercise 5

Write the func0on (eval5 expr ctx)


The func0on receives an expression (as dened in the three
previous slides) and a context, and evaluates expressions value
according to given context ctx

* For now, assume func0ons can only get a xed number of arguments
** Note that the current expression deni0on does allow passing func0ons as arguments

30

Evalua%ng Macro
Lets dene now an expression as follows:

expr = symbol | number | lst


lst = (func [expr, [expr, [...]]]) (means any number of expressions, 0)
lst = (macro-deni0on [expr, [expr, [...]]])
func = + | - | * | / | list | quote (for simplicity, only allowing these func2ons in this example)
macro-deni0on = (macro params body)
params = a list of symbols
body = expr
Examples:
7
(+ 1 2)
((macro (x y z) (list + x y z)) 7 8 (+ a b))
31

Evalua%ng Macro
When an expression begins with a macro expression
(such as (macro (x y z) (list + x y z))), evaluator should:
1. Evaluate the arguments
2. Apply the macro:
2.1. Bind parameters to evaluated arguments and add the
new bindings to the context (crea0ng a new context)
2.2. Evaluate the body of the macro expression in the new
context
Returned value is an expression (created by the macro)!
3. Evaluate the returned expression in the context of run0me
32

Evalua%ng Macro
Example:
Context is: ((a 7) (b 8) (c 9))
Expression: ((macro (x y z) (list + x y z)) a b c)
!

Bind parameters to arguments: ((x a) (y b) (z c))


Append bindings to context* to create the new context:
((x a) (y b) (z c) (a 7) (b 8) (c 9))
!

Evaluate macros body: (list + x y z) under the new context:


Result: (+ a b c)
!

Evaluate result expression in run0me (original) context:


Result: 24
* Depends on context model. Example uses dynamic context.
33

Important Note

Note that our evaluator handles macros slightly dierent


than the way Dr. Racket does it

34

Exercise 6

Write the func0on (eval6 expr ctx)


The func0on receives an expression (as dened in the few
previous slides) and a context, and evaluates expressions value
according to given context ctx

* For now, assume func0ons can only get a xed number of arguments

35

nLambda
In our interpreter we invent a new type of func0on
deni0on: nLambda expressions
nLambda is just like a lambda, except for the fact that its
arguments are not evaluated before the func0on is
called
nLambda is a useful tool for crea0ng special forms
!

Example:
(nlambda (x) x) - what does it do?
36

Preface for Exercise 7


In exercise 7 you will build your own Scheme interpreter
It will read some expression from user, evaluate it and
print the result of evalua0on to screen
The exercise is very modular - each part is graded
separately (this will make your life easier)
The exercise is long to read, much shorter to code
If anything is unclear - ask! (in the forum)
37

Exercise 7 - Mission
Func0ons of exercise 7:
< 15 lines
< 15 lines

Already
wriqen
< 20
short lines

2 lines
2 lines

3 lines
Already
wriqen
1 line

2 lines

* In gray - no need to implement, will be given


38

Exercise 7 - Mission
8 pages of instruc0ons and guidelines
Hard part - read and understand
Easy part - write the code
Some ini0al code is supplied - do not change it!
Addi0onal test code (framework + sample tests) is
supplied - use it to test your code
(you may add more tests, as only few are supplied)
39

Exercise 7 - Contexts
Our interpreter has three dierent context levels:
System context
Contains constant system deni0ons, such as system func0ons and constant
values
User context
Contains constant user deni0ons (similarly to system context, but as a
second level context below it)
Run0me context
Ini0ally this context is empty (when evalua0on begins). It gets lled as
func0ons are being called
Symbol lookup in context:
1. Look in current run0me context
2. Look in user context
3. Look in system context
40

Exercise 7 - Flags

The interpreter has the following four ags:

(define CONTEXT_TYPE 'static)

(define BONUS_ENABLED #f)

Denes the context model of the interpreter. Your code must support both static
and dynamic modes.
Bonus: implement an extended version of the switch macro inside the interpreter.
You must set the BONUS_ENABLED to #t if and only if you want this bonus to be
graded.

41

Exercise 7 - Limits
Our interpreter will use the following func0ons as
primi0ves from Dr. Racket:
+ - * / < > <= >= <> = eq? equal? null? pair? cons
car cdr

It will also treat the following values as special keywords:


() #t #f lambda nlambda macro if eval
Any other func0on/macro should be implemented as
non-primi0ve
Some non-primi0ve implementa0ons are provided
for free:
list quote caar cadr cadar cond map append let ...
42

Usage of the eval func%on

As the exercise is in fact wri0ng our own implementa0on


for the eval func0on of Racket, you are NOT ALLOWED
to use it anywhere in the exercise
Except for one specic point, which we will cover soon

43

Exercise 7 - Steps
1. eval-args: a func0on that evaluates a list of arguments
2. bind: binds parameters to arguments
Should also support func0ons with variable number of arguments
3. eval-symbol: evaluates the value of a single symbol:
If the symbol is a special keyword, return it.
If the symbol represents some primi0ve value, return the primi0ve*.
Otherwise, perform lookups in contexts, as explained before.
4. eval-if: evaluates an if expression
* This is the only place in the exercise where you are allowed to use the Racket eval func0on
44

Exercise 7 - Steps
5. Evaluate func0on call:
Evaluate an expression which involves a func0on (lambda / macro /
nlambda / primi0ve func0on) call.
Some parts of this sec0on are similar to the examples we did in class.
You may use them, but not as is, as the code in the exercise should be
dierent (does not do exactly the same).
6. evaluate: main evalua0on func0on
7. Bonus: Add the class macro to your user context

45

Example Run

46

Tes%ng Framework
The assert macro (supplied with the exercise) can be used to run
a func0on and compare its return value to some expected return
value
If return value is as expected, nothing happens
Otherwise, an error is raised
You can put as many assert calls as you wish at the end of your
code, to automa0cally test it
However, do NOT leave such test code in your submiqed le!
47

Você também pode gostar