1 Read-Eval-Print Loop (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-env))) (announce-output.

Slides:



Advertisements
Similar presentations
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Advertisements

Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Scheme in Scheme?!? …the metacircular evaluator….
1 The metacircular evaluator Names Extend the calculator to store intermediate results as named values (define x (+ 4 5)) store result as x (+ x.
1 Programming Languages (CS 550) Operational Semantics of Scheme using Substitution and the Lambda Calculus Jeremy R. Johnson TexPoint fonts used in EMF.
Metacircular Evaluation SICP Chapter 4 Mark Boady.
1 Programming Languages (CS 550) Lecture 7 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts used in EMF. Read.
מבוא מורחב למדעי המחשב תרגול 13 Lazy Evaluation. Lazy Evaluation Implementation Two types of values – Delayed Values – Actual Values Introduce two functions.
1 The Metacircular Evaluator Chapter 4 Section 4.1 We will not cover every little detail in the lectures, so you MUST read Section 4.1 in full.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 11. Metacircular Evaluator 4.1, pages definitions file on web 2.
(define applicative-eval (lambda (exp) (cond ((atomic? exp) (eval-atomic exp)) ((special-form? exp) (eval-special-form exp)) ((list-form? exp) (eval-list.
1 Lecture 18 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure.
6.001 SICP 1 Normal (Lazy) Order Evaluation Memoization Streams.
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 26: In Praise of Idleness.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 21. Overview 1. Dynamic Binding 2. Lazy Evaluation 3. More MC-Eval 2.
Lexical vs. Dynamic Scope …where do I point to?. Intro… Remember in Scheme whenever we call a procedure we pop a frame and point it to where the procedure.
SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Techniques for language design: Interpretation: eval/apply Semantics vs. syntax Syntactic.
SICP Infinite streams – using lazy evaluation Beyond Scheme – designing language variants: Streams – an alternative programming style!
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Scheme More MCE examples. Q1 new special form which defines global variables (static ) search the global environment – Variable exists: does nothing,
SICP Variations on a Scheme (2) Beyond Scheme – designing language variants: Lazy evaluation Complete conversion – normal order evaluator Upward.
The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using.
1 Saves repeated renaming and substitution: explicit substitution is replaced by variable bindings using new data structures (frame, environment). Can.
1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is aa good way to learn more about programming languages  Interpreters are.
1 The metacircular evaluator (Cont.) Defining new procedures (define (lambda? e) (tag-check e 'lambda)) (define (eval exp env) (cond ((number? exp)
CS220 Programming Principles 프로그래밍의 이해 2002 가을학기 Class 15: Meta-Circular Evaluator 한 태숙.
SICP Interpretation Parts of an interpreter Arithmetic calculator Names Conditionals and if Storing procedures in the environment Environment as.
SICP Explicit-control evaluator Big ideas: how to connect evaluator to machine instructions how to achieve tail recursion Obfuscation: tightly.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
The environment-based operational semantics Chapter
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 29: Typed Scheme MC Escher, Liberation.
1 Lecture 20 Lazy Evaluation Continued (4.2.1, 4.2.2) MC-eval examples from exams (Time permitting)
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
1/33 Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
1 Programming Languages (CS 550) Lecture 4 Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
1 Env. Model Implementation & Analyzer Practice Session #10 Env. Model Implementation & Analyzer Practice Session #10.
1 Lecture 19 Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
1/ SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Making the environment model concrete Defining eval defines the language –Provides.
CS 598 Scripting Languages Design and Implementation 10. Interpreters Part I: Lisp.
1 Lecture 19 Review last lecture on evaluator, Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
CS61A Lecture Colleen Lewis 1. Clicker poll Are you in a two person group for project 4? A)Yes – I have my partner B)No – I plan to work.
David Evans CS200: Computer Science University of Virginia Computer Science Lecture 27: Types of Types “It would appear.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
Evaluators for Functional Programming 1. How to describe (specify) a programming language? 1.Syntax: atoms, primitives, combination and abstraction means.
6.037 Lecture 7B Scheme Variants Normal Order Lazy Evaluation Streams Edited by Mike Phillips & Ben Vandiver Original Material by Eric Grimson & Duane.
SICP Interpretation part 2 Store operators in the environment Environment as explicit parameter Defining new procedures.
CSE 341 Lecture 21 delayed evaluation; thunks; streams slides created by Marty Stepp
(Thunking about Thunks)
Operational Semantics of Scheme
6.001 SICP Variations on a Scheme
6.001 SICP Object Oriented Programming
The interpreter.
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Env. Model Implementation
Original material by Eric Grimson
The Metacircular Evaluator
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
6.001 SICP Streams – the lazy way
The Metacircular Evaluator (Continued)
Lecture 26: The Metacircular Evaluator Eval Apply
6.001 SICP Further Variations on a Scheme
Streams, Delayed Evaluation and a Normal Order Interpreter
6.001 SICP Variations on a Scheme
6.001 SICP Interpretation Parts of an interpreter
topics interpreters meta-linguistic abstraction eval and apply
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
Lecture 25: The Metacircular Evaluator Eval Apply
Presentation transcript:

1 Read-Eval-Print Loop (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-env))) (announce-output output-prompt) (user-print output))) (driver-loop)) (define (prompt-for-input string) (newline) (newline) (display string) (newline)) (define (announce-output string) (newline) (display string) (newline)) (define (user-print object) (if (compound-procedure? object) (display (list 'compound-procedure (procedure-parameters object) (procedure-body object) ' )) (display object))) (define input-prompt ";;; M-Eval input:") (define output-prompt ";;; M-Eval value:")

2 We implemented lexical scoping Free variables in an application of procedure f get their values from the procedure where f was defined (by the appropriate lambda special form). Also called static binding (define (foo x y) (lambda (z) (+ x y z))) (define bar (foo 1 2)) (bar 3) bar : (lambda (z) (+ 1 2 z))

3 Diving in Deeper: Lexical Scope How does our evaluator achieve lexical scoping? –procedures that capture their lexical environment make-procedure : stores away the evaluation environment of lambda the "evaluation environment" is always the enclosing lexical scope why? –our semantic rules for procedure application! –"hang a new frame" –"bind parameters to actual args in new frame" –"evaluate body in this new environment"

4 Lexical Scope & Environment Diagram (define (foo x y) (lambda (z) (+ x y z))) GE p: x y body: ( (z) (+ x y z)) foo: E1 x: 1 y: 2 bar: p: z body: (+ x y z) (+ x y z) | E2 => 6 z: 3 E2 (define bar (foo 1 2)) (bar 3) Will always evaluate (+ x y z) in a new environment inside the surrounding lexical environment.

5 Alternative Model: Dynamic Scoping Dynamic scope: –Look up free variables in the caller's environment rather than the surrounding lexical environment Example: (define x 11) (define (pooh x) (bear 20)) (define bear (lambda (y) (+ x y))) (pooh 9) => 29

6 Dynamic Scope & Environment Diagram (define (pooh x) (bear 20)) GE p: x body: (bear  pooh: (+ x y) | E2 => 29 x: 9 E1 (define (bear y) (+ x y)) (pooh 9) Will evaluate (+ x y) in an environment that extends the caller's environment. bear: p: y body: (+ x y  y: 20 E2 (define x 11) x:11

7 A "Dynamic" Scheme (define (d-eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env))... ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) '*no-environment*)) ;CHANGE: no env... ((application? exp) (d-apply (d-eval (operator exp) env) (list-of-values (operands exp) env) env)) ;CHANGE: add env (else (error "Unknown expression -- M-EVAL" exp))))

8 A "Dynamic" Scheme – d-apply (define (d-apply procedure arguments calling-env) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments calling-env))) ;CHANGE: use calling env (else (error "Unknown procedure" procedure))))

9 Implement lazy evaluation Beyond Scheme – designing language variants: Lazy evaluation Complete conversion – normal order evaluator Upward compatible extension – lazy, lazy-memo

10 Normal Order (Lazy) Evaluation Alternative models for computation: Applicative Order: evaluate all arguments, then apply operator Normal Order: go ahead and apply operator with unevaluated argument subexpressions evaluate a subexpression only when value is needed to print by primitive procedure (that is, primitive procedures are "strict" in their arguments)

11 Applicative Order Example (define (foo x) (write-line "inside foo") (+ x x)) (foo (begin (write-line "eval arg") 222)) We first evaluated argument, then substituted value into the body of the procedure eval arg => (begin (write-line "inside foo") ( )) => 222 => (begin (write-line “eval arg”) 222) => 444 inside foo

12 Normal Order Example (define (foo x) (write-line "inside foo") (+ x x)) (foo (begin (write-line "eval arg") 222)) As if we substituted the unevaluated expression in the body of the procedure => (begin (write-line "inside foo") (+ (begin (w-l "eval arg") 222) (begin (w-l "eval arg") 222))) inside foo eval arg => 444

13 How can we implement lazy evaluation? (define (l-apply procedure arguments env) ; changed (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure (list-of-arg-values arguments env))) ((compound-procedure? procedure) (l-eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) (list-of-delayed-args arguments env) (procedure-environment procedure)))) (else (error "Unknown proc" procedure))))

14 Lazy Evaluation – l-eval Most of the work is in l-apply ; need to call it with: actual value for the operator just expressions for the operands the environment... (define (l-eval exp env) (cond ((self-evaluating? exp) exp)... ((application? exp (l-apply (actual-value (operator exp) env) (operands exp) env)) (else (error "Unknown expression" exp))))

15 Actual vs. Delayed Values (define (actual-value exp env) (force-it (l-eval exp env))) (define (list-of-delayed-args exps env) (if (no-operands? exps) '() (cons (delay-it (first-operand exps) env) (list-of-delayed-args (rest-operands exps) env)))) (define (list-of-arg-values exps env) (if (no-operands? exps) '() (cons (actual-value (first-operand exps) env) (list-of-arg-values (rest-operands exps) env))))

16 Representing Thunks Abstractly – a thunk is a "promise" to return a value when later needed ("forced") Concretely – our representation: thunk envexp

17 Thunks – delay-it and force-it (define (delay-it exp env) (list 'thunk exp env)) (define (thunk? obj) (tagged-list? obj 'thunk)) (define (thunk-exp thunk) (cadr thunk)) (define (thunk-env thunk) (caddr thunk)) (define (force-it obj) (cond ((thunk? obj) (actual-value (thunk-exp obj) (thunk-env obj))) (else obj))) (define (actual-value exp env) (force-it (l-eval exp env)))

18 Lazy Evaluation – other changes needed Example – need actual predicate value in conditional if... (define (l-eval-if exp env) (if (true? (actual-value (if-predicate exp) env)) (l-eval (if-consequent exp) env) (l-eval (if-alternative exp) env))) Example – don't need actual value in assignment... (define (l-eval-assignment exp env) (set-variable-value! (assignment-variable exp) (l-eval (assignment-value exp) env) env) 'ok)

19 (l-eval ‘((lambda (x) (+ x x) ) (+ 1 1)) GE) (l-apply (actual-value ‘(lambda (x) (+ x x)) GE) ‘((+1 1 )) GE) (force-it (l-eval ‘(lambda (x) (+ x x)) GE)) ‘(procedure ‘(x) ‘((+ x x)) GE) (l-apply ‘(procedure ‘(x) ‘(+ x x) GE) ‘((+1 1 )) GE) (l-eval ‘(+ x x) E1) x : (‘thunk ‘(+1 1) GE) GE E1 (l-apply (actual-value ‘+ E1) ‘(x x) E1) (l-apply ‘(primitive #[add]) ‘(x x) E1) (apply-primitive-procedure ‘(primitive #[add]) (actual-value x E1)(actual-value x E1) ) (force-it (l-eval x E1)) (force-it (‘thunk ‘(+ 1 1) GE)) (actual-value ‘(+ 1 1) GE) (force-it (l-eval ‘(+ 1 1) GE)) ==> 2

20 Memo-izing Thunks Idea: once thunk exp has been evaluated, remember it If value is needed again, just return it rather than recompute thunk envexp Concretely – mutate a thunk into an evaluated-thunk evaluated- thunk result

21 Thunks – Memoizing Implementation (define (evaluated-thunk? obj) (tagged-list? obj 'evaluated-thunk)) (define (thunk-value evaluated-thunk) (cadr evaluated-thunk)) (define (force-it obj) (cond ((thunk? obj) (let ((result (actual-value (thunk-exp obj) (thunk-env obj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdr obj) result) (set-cdr! (cdr obj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

22 Laziness and Language Design We have a dilemma with lazy evaluation Advantage: only do work when value actually needed Disadvantages –not sure when expression will be evaluated; can be very big issue in a language with side effects –may evaluate same expression more than once Alternative approach: give programmer control! Memoization doesn't fully resolve our dilemma Advantage: Evaluate expression at most once Disadvantage: What if we want evaluation on each use?

23 Variable Declarations: lazy and lazy-memo Handle lazy and lazy-memo extensions in an upward- compatible fashion.; (lambda (a (b lazy) c (d lazy-memo))...) "a", "c" are normal variables (evaluated before procedure application "b" is lazy; it gets (re)-evaluated each time its value is actually needed "d" is lazy-memo; it gets evaluated the first time its value is needed, and then that value is returned again any other time it is needed again.

24 Syntax Extensions – Parameter Declarations (define (first-variable var-decls) (car var-decls)) (define (rest-variables var-decls) (cdr var-decls)) (define declaration? pair?) (define (parameter-name var-decl) (if (pair? var-decl) (car var-decl) var-decl)) (define (lazy? var-decl) (and (pair? var-decl) (eq? 'lazy (cadr var-decl)))) (define (memo? var-decl) (and (pair? var-decl) (eq? 'lazy-memo (cadr var-decl))))

25 Controllably Memo-izing Thunks thunk – never gets memoized thunk-memo – first eval is remembered evaluated-thunk – memoized-thunk that has already been evaluated thunk- memo envexp evaluated- thunk result when forced

26 A new version of delay-it Look at the variable declaration to do the right thing... (define (delay-it decl exp env) (cond ((not (declaration? decl)) (l-eval exp env)) ((lazy? decl) (list 'thunk exp env)) ((memo? decl) (list 'thunk-memo exp env)) (else (error "unknown declaration:" decl))))

27 Change to force-it (define (force-it obj) (cond ((thunk? obj) ;eval, but don't remember it (actual-value (thunk-exp obj) (thunk-env obj))) ((memoized-thunk? obj) ;eval and remember (let ((result (actual-value (thunk-exp obj) (thunk-env obj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdr obj) result) (set-cdr! (cdr obj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

28 Changes to l-apply Key: in l-apply, only delay "lazy" or "lazy-memo" params make thunks for "lazy" parameters make memoized-thunks for "lazy-memo" parameters (define (l-apply procedure arguments env) (cond ((primitive-procedure? procedure)...) ; as before; apply on list-of-arg-values ((compound-procedure? procedure) (l-eval-sequence (procedure-body procedure) (let ((params (procedure-parameters procedure))) (extend-environment (map parameter-name params) (list-of-delayed-args params arguments env) (procedure-environment procedure))))) (else (error "Unknown proc" procedure))))

29 Deciding when to evaluate an argument... Process each variable declaration together with application subexpressions – delay as necessary: (define (list-of-delayed-args var-decls exps env) (if (no-operands? exps) '() (cons (delay-it (first-variable var-decls) (first-operand exps) env) (list-of-delayed-args (rest-variables var-decls) (rest-operands exps) env))))

30 Summary Lazy evaluation – control over evaluation models Convert entire language to normal order Upward compatible extension –lazy & lazy-memo parameter declarations

31 How do we use this new lazy evaluation? Our users could implement a stream abstraction: (define (cons-stream x (y lazy-memo)) (lambda (msg) (cond ((eq? msg 'stream-car) x) ((eq? msg 'stream-cdr) y) (else (error "unknown stream msg" msg))))) (define (stream-car s) (s 'stream-car)) (define (stream-cdr s) (s 'stream-cdr)) OR (define (cons-stream x (y lazy-memo)) (cons x y)) (define stream-car car) (define stream-cdr cdr)

32 Stream Object a thunk-memo a value stream-car cons-stream stream-cdr