6 001 SICP Variations on a Scheme Scheme

  • Slides: 26
Download presentation
6. 001 SICP Variations on a Scheme • Scheme Evaluator – A Grand Tour

6. 001 SICP Variations on a Scheme • Scheme Evaluator – A Grand Tour • Techniques for language design: • Interpretation: eval/apply • Semantics vs. syntax • Syntactic transformations • Beyond Scheme – designing language variants • Lexical scoping vs. Dynamic scoping 1

Building up a language. . . 1. 3. 4. 5. eval/apply core 2. syntax

Building up a language. . . 1. 3. 4. 5. eval/apply core 2. syntax procedures environment manipulation primitives and initial env. read-eval-print loop 2

The Core Evaluator 1. Eval exp & env eval/apply core proc & args Apply

The Core Evaluator 1. Eval exp & env eval/apply core proc & args Apply • Core evaluator • eval: dispatch on expression type • apply: eval args then apply operator 3

Basic Semantics: m-eval & m-apply • primitive expressions – self-evaluating, quoted • variables and

Basic Semantics: m-eval & m-apply • primitive expressions – self-evaluating, quoted • variables and the environment – variable definition, lookup, and assignment • conditionals – if, cond • procedure application • sequences – begin 4

Side comment – procedure body • The procedure body is a sequence of one

Side comment – procedure body • The procedure body is a sequence of one or more expressions: (define (foo x) (do-something (+ x 1)) (* x 5)) • In m-apply, we eval-sequence the procedure body. 5

2. Syntactic Abstraction • Semantics • What the language means • Model of computation

2. Syntactic Abstraction • Semantics • What the language means • Model of computation syntax procedures • Syntax • Particulars of writing expressions • E. g. how to signal different expressions • Separation of syntax and semantics: allows one to easily alter syntax eval/apply syntax procedures 6

Basic Syntax • Routines to detect expressions (define (if? exp) (tagged-list? exp 'if)) (define

Basic Syntax • Routines to detect expressions (define (if? exp) (tagged-list? exp 'if)) (define (lambda? exp) (tagged-list? exp 'lambda)) (define (application? exp) (pair? exp)) • Routines to get information out of expressions (define (operator app) (car app)) (define (operands app) (cdr app)) • Routines to manipulate expressions (define (no-operands? args) (null? args)) (define (first-operand args) (car args)) (define (rest-operands args) (cdr args)) 7

Example – Changing Syntax • Suppose you wanted a "verbose" application syntax: (CALL <proc>

Example – Changing Syntax • Suppose you wanted a "verbose" application syntax: (CALL <proc> ARGS <arg 1> <arg 2>. . . ) • Changes – only in the syntax routines! (define (application? exp) (tagged-list? 'CALL)) (define (operator app) (cadr app)) (define (operands app) (cdddr app)) 8

Implementing "Syntactic Sugar" • Idea: • Implement a simple fundamental "core" in the evaluator

Implementing "Syntactic Sugar" • Idea: • Implement a simple fundamental "core" in the evaluator • Easy way to add alternative/convenient syntax? • "let" as sugared procedure application: (let ((<name 1> <val 1>) (<name 2> <val 2>)) <body>) ((lambda (<name 1> <name 2>) <val 1> <val 2>) <body>) 9

Detect and Transform the Alternative Syntax )define (m-eval exp env( ) cond ((self-evaluating? exp)

Detect and Transform the Alternative Syntax )define (m-eval exp env( ) cond ((self-evaluating? exp) exp( )) variable? exp( ) lookup-variable-value exp env(( )) quoted? exp( ) text-of-quotation exp((. . . ((let? exp) (m-eval (let->combination exp) env)) ((application? exp) (m-apply (m-eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression" exp)))) 10

Let Syntax Transformation )define (let? exp) (tagged-list? exp 'let(( (define (let-bound-variables let-exp) (map car

Let Syntax Transformation )define (let? exp) (tagged-list? exp 'let(( (define (let-bound-variables let-exp) (map car (cadr let-exp))) (define (let-values let-exp) (map cadr (cadr let-exp))) (define (let-body let-exp) (sequence->exp (cddr let-exp))) )define (let->combination let-exp) (let ((names (let-bound-variables let-exp)) (values (let-values let-exp)) (body (let-body let-exp))) (cons (list 'lambda names body) values))) 11

Details of let syntax transformation )let ((x 23( ) y 15(( ) dosomething x

Details of let syntax transformation )let ((x 23( ) y 15(( ) dosomething x y(( let dosomething x 23 y x y 15 12

Details of let syntax transformation let dosomething 23 x x y 15 y 23

Details of let syntax transformation let dosomething 23 x x y 15 y 23 15 lambda x y dosomething x y 13

Named Procedures – Syntax vs. Semantics ) define (foo <parm>) <body>) • Semantic implementation

Named Procedures – Syntax vs. Semantics ) define (foo <parm>) <body>) • Semantic implementation – just another define: (define (eval-definition exp env) (define-variable! (definition-variable exp) (m-eval (definition-value exp) env)) • Syntactic transformation: (define (definition-value exp) (if (symbol? (cadr exp)) (caddr exp) (make-lambda (cdadr exp) (cddr exp)))) ; formal params ; body 14

3. How the Environment Works • Abstractly – in our environment diagrams: E 2

3. How the Environment Works • Abstractly – in our environment diagrams: E 2 • Concretely – our implementation (as E 2 in SICP) list of variables x plus E 1 environment manipulation x: 10 plus: (procedure. . . ) frame enclosingenvironment list of values 10 procedure 15

Extending the Environment • )extend-environment '(x y) (list 4 5) E 2) Abstractly Concretely

Extending the Environment • )extend-environment '(x y) (list 4 5) E 2) Abstractly Concretely E 2 E 3 E 1 E 2 x: 10 plus: (procedure. . . ) E 3 x: y: 4 5 E 1 frame list of variables x y list of values 4 5 16

"Scanning" the environment • Look for a variable in the environment. . . •

"Scanning" the environment • Look for a variable in the environment. . . • Look for a variable in a frame. . . – loop through the list of vars and list of vals in parallel – detect if the variable is found in the frame • If not found in frame (out of variables in the frame), look in enclosing environment 17

The Initial (Global) Environment • setup-environment 4. primitives and initial env. (define (setup-environment) (let

The Initial (Global) Environment • setup-environment 4. primitives and initial env. (define (setup-environment) (let ((initial-env (extend-environment (primitive-procedure-names) (primitive-procedure-objects) the-empty-environment))) (define-variable! 'true #T initial-env) (define-variable! 'false #F initial-env)) • define initial variables we always want • bind explicit set of "primitive procedures" • here: use underlying scheme • in other interpreters: assembly code, hardware, . . 18

Read-Eval-Print Loop 5. read-eval-print loop )define (driver-loop( ) prompt-for-input-prompt( ) let ((input (read))) (let

Read-Eval-Print Loop 5. read-eval-print loop )define (driver-loop( ) prompt-for-input-prompt( ) let ((input (read))) (let ((output (m-eval input the-global-env))) (announce-output-prompt) (user-print output))) (driver-loop)) 19

Diving in Deeper: Lexical Scope • How does our evaluator achieve lexical scoping? –

Diving in Deeper: Lexical Scope • How does our evaluator achieve lexical scoping? – environment chaining – 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" 20

Lexical Scope & Environment Diagram )define (foo x y) (lambda (z) (+ x y

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

Alternative Model: Dynamic Scoping • Dynamic scope: – Look up free variables in the

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

Dynamic Scope & Environment Diagram )define (pooh x) (bear 20(( Will evaluate (+ x

Dynamic Scope & Environment Diagram )define (pooh x) (bear 20(( Will evaluate (+ x y) in an environment that extends the caller's environment. )define (bear y) (+ x y)) )pooh 9( GE pooh: bear: E 1 p: x body: (bear 20) E 2 x: 9 y: 20 +)x y) | E 2 => 29 p: y body: (+ x y) 23

A "Dynamic" Scheme )define (m-eval exp env( ) cond )) self-evaluating? exp) exp( ))

A "Dynamic" Scheme )define (m-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 (m-eval (operator exp) env) (list-of-values (operands exp) env)) ; CHANGE: add env (else (error "Unknown expression -- M-EVAL" exp)))) 24

A "Dynamic" Scheme – d-apply )define (d-apply procedure arguments calling-env) (cond ((primitive-procedure? procedure) (apply-primitive-procedure

A "Dynamic" Scheme – d-apply )define (d-apply procedure arguments calling-env) (cond ((primitive-procedure? procedure) (apply-primitive-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)))) 25

Summary • Scheme Evaluator – Know it Inside & Out • Techniques for language

Summary • Scheme Evaluator – Know it Inside & Out • Techniques for language design: • Interpretation: eval/apply • Semantics vs. syntax • Syntactic transformations • Able to design new language variants! • Lexical scoping vs. Dynamic scoping 26