Com S 342 meeting -*- Outline -*- * Procedures (5.4) ** syntax ------------------------------------------ PROCEDURES (5.4) Concrete syntax: ::= proc ::= ( ) | ( ) ::= {,}* Examples: Abstract syntax: ------------------------------------------ ... let sum3 = proc (a, b, c) +(a, +(b, c)) in sum3(3, 4, 2) (proc (a,b,c) +(a, +(b,c)))(3, 4, 2) Q: What should be the abstract syntax? something similar to the following from the text ... (define-record proc (formals body)) ** closures ------------------------------------------ PROCEDURE SCOPING Example: let x = 5 in let addx = proc (i) +(i, x); x = 41 in addx(3) FOR YOU TO DO (IN PAIRS) 1. Which x should addx find? 2. What should be the value of a proc expression? 3. How would you complete this equation? Procedure = Primitive Procedure + 4. Make the changes needed in eval-exp and apply-proc ------------------------------------------ Q: To get lexical scoping, what do we have to do? remember the environment where the procedure was made, and use that when evaluating the body, so to run a procedure call, (1) extend the remembered environment, by binding the formals to the actuals (the result of eval-rands), (2) eval-exp the body in that env. Q: So what should be the value of a proc expression? a closure, which we'll represent as a record ;; in procedure.scm (define-record closure (formals body env)) Apply-proc can now find either a primitive procedure or a closure: Procedure = Primitive Procedure + Closure See the files procedure.scm and ch5-4-expressed-value.scm (define apply-proc ; TYPE: (-> (Procedure (list Expressed-Value)) Expressed-Value) (lambda (proc args) (variant-case proc (prim-proc (prim-op) (apply-prim-op prim-op args)) (closure (formals body env) (eval-exp body (extend-env formals (map expressed->denoted args) env))) (else (error "Invalid procedure:" proc))))) (define eval-exp ; TYPE: (-> (parsed-exp Environment) Expressed-Value) (lambda (exp env) (variant-case exp (proc (formals body) (procedure->expressed (make-closure formals body env))) (else ...)))) ** sugars ------------------------------------------ SUGARS IN THE INTERPRETER Can let be a syntactic sugar now? ;;; In file eval-form-0.scm ;; Grammar: ;;
::= (define eval-form ;; TYPE: (-> (parsed-form) ;; Expressed-Value) (lambda (form) (eval-exp init-env))) ;;; In file run.scm (define run ;; TYPE: (-> () Expressed-Value) (lambda (x) (eval-form (parse x)))) ------------------------------------------ ... yes, can leave out let, have it syntax-expanded (desugared) before interpreter runs by using let x1 = e1; ... ; xn = en in body ==> (proc(x1,...,xn) body) (e1,...,en) but at the level of abstract syntax trees, not concrete syntax ... (syntax-expand (form->exp form)) these are what are used in the interpreters now ** second-class procedures (may omit or make homework) Q: What are the defined language's expressed values currently? Expressed-Value = Number + Procedure Denoted-Value = Number + Procedure ------------------------------------------ SECOND-CLASS PROCEDURES What would we have to do to make procedures more like those in C? ------------------------------------------ in C you can have pointers to procedures and write (*f)(3) Closures can only appear at the top-level. Q: What syntax change? no need for independent procs as expressions Would need a "define" syntax to name them. Q: Could the syntax be simplified then? define proc fact(i) = Q: What about the implementation can be simplified? Q: Do we still need closures? no, only environment that will be extended is init-env, assuming we aren't going to desugar let. Q: What about C++? there still need closures, as have nesting, classes Q: What would we have to change to make them as in FORTRAN-77? Nothing but top-level procedures, so no need for closures and procedures are not part of the Expressed-Value domain Expressed-Value = number Denoted-Value = number + Procedure Q: What syntax change? application ::= ( {, }*)