6.001 SICP Variations on a Scheme Scheme Evaluator A Grand Tour Techniques for language design: Interpretation: eval/appl Semantics vs. snta Sntactic transformations Building up a language... 3. 1. eval/appl core environment manipulation 4. primitives and initial env. 2. snta procedures Beond Scheme designing language variants Leical scoping vs. Dnamic scoping 5. read-eval-print loop 1 2 The Core Evaluator ep & env Eval Appl proc & args Core evaluator eval: dispatch on epression tpe appl: eval args then appl operator 1. eval/appl core Meval (define (meval ep env) (cond ((self-evaluating? ep) ep) ((variable? ep) (lookup-variable-value ep ((quoted? ep) (tet-of-quotation ep)) ((assignment? ep) (eval-assignment ep ((definition? ep) (eval-definition ep ((if? ep) (eval-if ep ((lambda? ep) (make-procedure (lambda-parameters ep) (lambda-bod ep) ((begin? ep) (eval-sequence (begin-actions ep) ((cond? ep) (eval (cond->if ep) (mappl (meval (operator ep) env) (list-of-values (operands ep) ) (else (error "Unknown epression tpe -- EVAL" ep)))) 3 4 Basic Semantics: m -eval & m-appl Side comment procedure bod primitive epressions The procedure bod is a sequence of one or more self -evaluating, quoted epressions: variables and the environment (define (foo ) variable definition, lookup, and assignment (do-something (+ 1)) (* 5)) conditionals if, cond In m-appl, we eval-sequence the procedure bod. procedure application sequences begin 5 6 1
Mappl (define (mappl procedure arguments) (cond ((primitive-procedure? procedure) (appl-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-bod procedure) (etend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure tpe -- APPLY" procedure)))) Pieces of Eval&Appl (define (meval ep env) (cond ((self-evaluating? ep) ep) ((variable? ep) (lookup-variable-value ep ((quoted? ep) (tet-of-quotation ep)) ((assignment? ep) (eval-assignment ep ((definition? ep) (eval-definition ep ((if? ep) (eval-if ep ((lambda? ep) (make-procedure (lambda-parameters ep) (lambda-bod ep) ((begin? ep) (eval-sequence (begin-actions ep) ((cond? ep) (eval (cond->if ep) (mappl (meval (operator ep) env) (list-of-values (operands ep) ) (else (error "Unknown epression tpe -- EVAL" ep)))) 7 8 Pieces of Eval&Appl (define (eval-sequence eps env) (cond ((last-ep? eps) (meval (first-ep eps) (else (meval (first-ep eps) env) (eval-sequence (rest-eps eps) )) (define (eval-assignment ep env) (set-variable-value! (assignment-variable ep) (meval (assignment-value ep) ep) (define (eval-definition ep env) (define-variable! (definition-variable ep) (meval (definition-value ep) env) Sntactic Abstraction Semantics What the language means Model of computation Snta Particulars of writing epressions E.g. how to signal different epressions Separation of snta and semantics: allows one to easil alter snta eval/appl snta procedures 2. snta procedures 9 10 Basic Snta Routines to detect epressions (define (if? ep) (tagged-list? ep 'if)) (define (lambda? ep) (tagged-list? ep 'lambda)) (define (application? ep) (pair? ep)) Routines to get information out of epressions (define (operator app) (car app)) (define (operands app) (cdr app)) Routines to manipulate epressions (define (no-operands? args) (null? args)) (define (first-operand args) (car args)) (define (rest-operands args) (cdr args)) Eample Changing Snta Suppose ou wanted a "verbose" application snta: (CALL <proc> ARGS <arg1> <arg2>...) Changes onl in the snta routines! (define (application? ep) (tagged-list? 'CALL)) (define (operator app) (cadr app)) (define (operands app) (cdddr app)) 11 12 2
Implementing "Sntactic Sugar" Idea: Implement a simple fundamental "core" in the evaluator Eas wa to add alternative/convenient snta? "let" as sugared procedure application: (let ((<name1> <val1>) (<name2> <val2>)) <bod>) ((lambda (<name1> <name2>) <bod>) <val1> <val2>) Detect and Transform the Alternative Snta (define (m-eval ep env) (cond ((self-evaluating? ep) ep) ((variable? ep) (lookup-variable-value ep ((quoted? ep) (tet-of-quotation ep))... ((let? ep) (m-eval (let->combination ep) (m-appl (m-eval (operator ep) env) (list-of-values (operands ep) ) (else (error "Unknown epression" ep)))) 13 14 Let Snta Transformation Details of let snta transformation (define (let? ep) (tagged-list? ep 'let)) (let (( 23) (define (let-bound-variables let-ep) (map car (cadr let-ep))) ( 15)) (dosomething )) (define (let-values let-ep) (map cadr (cadr let-ep))) (define (let-bod let-ep) (sequence->ep (cddr let-ep))) let (define (let->combination let-ep) (let ((names (let-bound-variables let-ep)) (values (let-values let-ep)) (bod (let-bod let-ep))) (cons (list 'lambda names bod) values))) 23 15 dosomething 15 16 Details of let snta transformation Named Procedures Snta vs. Semantics (define (foo <parm>) <bod>) let dosomething Semantic implementation just another define: (define (eval-definition ep env) (define-variable! (definition-variable ep) (m-eval (definition-value ep) env) 23 15 lambda 23 15 Sntactic transformation: (define (definition-value ep) (if (smbol? (cadr ep)) (caddr ep) (make-lambda (cdadr ep) ;formal params (cddr ep)))) ;bod dosomething 17 18 3
19 How the Environment Works Abstractl in our environment diagrams: : Concretel our implementation (as in SICP) variables 10 plus: (procedure...) frame enclosingenvironment values 3. environment manipulation Etending the Environment (etend-environment '( ) (list 4 5) ) Concretel E3 variables frame values E3 Abstractl : 10 plus: (procedure...) : 4 : 5 plus 10 procedure 4 5 20 "Scanning" the environment Scanning the environment (details) Look for a variable in the environment... Look for a variable in a frame... loop through the vars and 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 (define (lookup-variable-value var env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment ) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empt-environment) (error "Unbound variable -- LOOKUP" var) (let ((frame (first-frame ) (scan (frame-variables frame) (frame-values frame))))) (env-loop 21 22 The Initial (Global) Environment setup-environment (define (setup-environment) (let ((initial-env 4. primitives and initial env. (etend-environment (primitive-procedure-names) (primitive-procedure-objects) the-empt-environment))) (define-variable! 'true #T initial-env) (define-variable! 'false #F initial-env) initial- define initial variables we alwas want bind eplicit set of "primitive procedures" here: use underling scheme in other interpreters: assembl code, hardware,... Read-Eval-Print Loop 5. read-eval-print loop (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (m-eval input the-global-) (announce-output output-prompt) (user-print output))) (driver-loop)) 23 24 4
Diving in Deeper: Leical Scope How does our evaluator achieve leical scoping? environment chaining procedures that capture their leical environment make-procedure: stores awa the evaluation environment of lambda the "evaluation environment" is alwas the enclosing leical scope wh? our semantic rules for procedure application! "hang a new frame" "bind parameters to actual args in new frame" "evaluate bod in this new environment" 25 Leical Scope & Environment Diagram (define (foo ) (lambda (z) (+ z))) (define bar (foo 1 2)) (bar 3) GE foo: p: bod: (l (z) (+ z)) bar: : 1 : 2 Will alwas evaluate (+ z) in a new environment inside the surrounding leical environment. p: z z: 3 bod: (+ z) (+ z) => 6 26 Alternative Model: Dnamic Scoping Dnamic scope: Look up free variables in the caller's environment rather than the surrounding leical environment Eample: Dnamic Scope & Environment Diagram (define (pooh ) (bear 20)) (define (bear ) (+ )) (pooh 9) Will evaluate (+ ) in an environment that etends the caller's environment. (define (pooh ) (bear 20)) GE pooh: bear: (define (bear ) (+ )) (pooh 9) => 29 27 p: bod: (bear 20) : 9 : 20 (+ ) => 29 p: bod: (+ ) 28 A "Dnamic" Scheme (define (m-eval ep env) (cond ((self-evaluating? ep) ep) ((variable? ep) (lookup-variable-value ep... ((lambda? ep) (make-procedure (lambda-parameters ep) (lambda-bod ep) '*no-environment*)) ;CHANGE: no env... (d-appl (m-eval (operator ep) env) (list-of-values (operands ep) env) ;CHANGE: add env (else (error "Unknown epression -- M-EVAL" ep)))) A "Dnamic" Scheme d-appl (define (d-appl procedure arguments calling-env) (cond ((primitive-procedure? procedure) (appl-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-bod procedure) (etend-environment (procedure-parameters procedure) arguments calling-) ;CHANGE: use calling env (else (error "Unknown procedure" procedure)))) 29 30 5
Summar Scheme Evaluator Know it Inside & Out Techniques for language design: Interpretation: eval/appl Semantics vs. snta Sntactic transformations Able to design new language variants! Leical scoping vs. Dnamic scoping 31 6