Procedures EOPL3: Section 3.3 PROC and App B: SLLGEN The PROC language • Expression ::= proc (Identifier) Expression – AST: proc-exp (var body) • Expression ::= (Expression Expression) – AST: call-exp (rator rand) • PROC includes all of LET language • Anonymous procedure • One parameter always CS784(pm) 2 Semantics of Procedures • (This slide is for procedures in general.) • Procedure Definition – Store formal parameters and body • Procedure Invocation – Evaluate body in an environment that binds formals to actual argument values • Interpretation of free-variables: Two methods – Use env at proc definition (lexical/static scoping) – Use env at proc call (dynamic scoping) CS784(pm) 3 Scoping and Binding • references – (f x y) – f, x, and y • declarations – (lambda (x) (+ x 3)) – (let ((x (+ y 7))) (+ x 3)) • y, and second/right x are refs • first/left x is a declaration • lexical scoping rules CS784(pm) 4 Kinds of Scope • Static or Lexical scope – determined by structure of program – Scheme, C++, Java, and many compiled languages • Dynamic scope – determined by path of execution – Lisp dialects, Perl, and many interpreted languages • Global Scope – File scope • Local Scope – Block • Body of a procedure • Body of a loop • Scope alters the meaning CS784(pm) 5 Example-1 of PROC • • • • • • • let f = proc (x) --(x,11) in (f (f 77)) Defines an anonymous procedure with one formal parameter named x. Body of the procedure: --(x,11) Binds the name f to this procedure. Invokes f with actual argument 77. Invokes f again with the result of above. (will use two -- just for visibility) CS784(pm) 6 Example-2 of PROC • (proc (f) (f (f 77)) proc (x) --(x,11)) • This example is derived from the production – Expression ::= (Expression Expression) – so is (f (f 77)) – so is (f 77) • proc (f) (f (f 77)) is the rator. – It defines an anonymous procedure with one formal parameter named f. • proc (x) --(x,11)) is the rand. – It also defines an anonymous procedure with one formal parameter named x. CS784(pm) 7 Example-3 of PROC • let x = 200 in let f = proc (z) --(z, x) in let x = 100 in let g = proc (z) --(z, x) in --((f 1), (g 1)) CS784(pm) • Illustrates scope issues • x and z appear four times each. • Lexical scoping – In --((f 1), (g 1)), the bodies of f and g must be evaluated in the env they were defined. – In f, x is bound to 200 – In g, x is bound to 100 8 Example Programs of PROC • Example-1 and -2 produce same result, but different mechanisms. • Previous two slides gave semantics informally – Watch out: a very seductive approach – Next few slides: interpreter based CS784(pm) 9 Example Calc w/ Spec 1 CS784(pm) 10 Example Calc w/ Spec 2 CS784(pm) 11 Example Calc w/ Spec 3 CS784(pm) 12 Example Calc w/ Spec 4 CS784(pm) 13 Recall value-of • value-of is an operator with two operands – an AST – an environment – (value-of ast env) • PROC = LET + two more productions • Bring in all value-of specs from LET • Additions are shown on next few slides … CS784(pm) 14 additional value-of specs • (value-of (proc-exp var body) ρ) = (proc-val (procedure var body ρ)) • (value-of (call-exp rator rand) ρ) = (let ( (proc (expval->proc (value-of rator ρ))) (arg (value-of rand ρ))) (apply-procedure proc arg)) • To be defined: proc-val, apply-procedure CS784(pm) 15 Spec of apply-procedure • (apply-procedure (procedure var body ρ) val) = (value-of body [var=val]ρ ) • apply-procedure takes two arguments: – an AST of a procedure definition – an argument for the parameter of the procedure – yields an expressed value CS784(pm) 16 Impl of apply-procedure (define proc? (lambda (pc) (procedure? pc))) • procedure? provided from r5rs • Names being bound: (define procedure (lambda (var body env) (lambda (val) (value-of body (extend-env var val env))))) • • • • (define apply-procedure (lambda (pc val) (pc val))) CS784(pm) – proc? – procedure – apply-procedure env is an environment ASTs: body, pc, val, var Use of procedure? is too liberal. procedure is not self-contained; takes three arguments: – param name var – body AST – environment 17 Alternate impl called Closures (define-datatype proc proc? (procedure (var identifier?) (body expression?) (saved-env environment?))) • • Defining a new data type called “proc” Has only one variant – • procedure That has three parts – var • (define apply-procedure (lambda (pc val) (cases proc pc (procedure (var body saved-env) (value-of body (extend-env var val saved-env)))))) CS784(pm) – body • – an expression saved-env • • • which must be an id an environment apply-procedure takes pc and val. “cases proc pc” – – pc is expected to be of type proc code for each variant of proc • only one variant “procedure” here 18 the data type expval is now … (define-datatype expval expval? (num-val (num number?)) (bool-val (bool boolean?)) (proc-val (proc proc?))) CS784(pm) 19 value-of: two new clauses (proc-exp (var body) (proc-val (procedure var body env))) (call-exp (rator rand) (let ( (proc (expval->proc (value-of rator env))) (arg (value-of rand env))) (apply-procedure proc arg))) CS784(pm) 20 Curried procedures • In PROC, procedures with multiple arguments can be had as in: – let f = proc (x) proc (y) ... in ((f 3) 4) – proc (x) … yields a procedure • Named after Haskell Brooks Curry (1900 – 1982), a combinatory logician. CS784(pm) 21 chapter3/proc-lang/ • Two subdirectories – chapter3/proc-lang/proc-rep: procedural implementation – chapter3/proc-lang/ds-rep: data type based (i.e., closure) • Both directories have the following files – – – – – – – data-structures.scm drscheme-init.scm environments.scm interp.scm lang.scm tests.scm top.scm CS784(pm) 22 EOPL3 Appendix B SLLGEN (define scanner-spec-1 ...) (define grammar-1 ...) (sllgen:make-define-datatypes scanner-spec-1 grammar-1) (define list-the-datatypes (lambda () (sllgen:list-define-datatypes scanner-spec-1 grammar-1))) (define just-scan (sllgen:make-string-scanner scanner-spec-1 grammar-1)) (define scan&parse (sllgen:make-string-parser scanner-spec-1 grammar-1)) (define read-eval-print (sllgen:make-rep-loop "--> " value-of--program (sllgen:make-stream-parser scanner-spec-1 grammar-1))) CS784(pm) • sllgen:make-definedatatypes: generates a define-datatype for each production of the grammar, for use by cases. • sllgen:make-stringscanner takes a scanner spec and a grammar and generates a scanning procedure • read-eval-print loop 23 Lexical Analysis (define the-lexical-spec '((whitespace (whitespace) skip) (comment ("%" (arbno (not #\newline))) skip) (identifier (letter (arbno (or letter digit "_" "-" "?"))) symbol) (number (digit (arbno digit)) number) (number ("-" digit (arbno digit)) number) )) CS784(pm) • the-lexical-spec • from chapter3/ proc-lang/*/lang.scm • scanners are specified by reg exp – next slide • All our languages use this lexical analysis. 24 SLLGEN Scanner Spec Scanner-spec ::= ({Regexp-and-action}∗) Regexp-and-action ::= (Name ({Regexp}∗) Action) Name ::= Symbol Regexp ::= String | letter | digit| whitespace|any ::= (not Character) | (or {Regexp}∗) ::= (arbno Regexp) | (concat {Regexp}∗) Action ::= skip | symbol | number | string CS784(pm) • A scanner specification in SLLGEN is a list that satisfies the grammar at left 25 The SLLGEN Parsing System (define the-grammar '((program (expression) a-program) (expression (number) const-exp) (expression ("-" "(" expression "," expression ")") diff-exp) (expression ("zero?" "(" expression ")") zero?-exp) (expression ("if" expression "then" expression "else" expression) if-exp) (expression (identifier) var-exp) (expression ("let" identifier "=" expression "in" expression) let-exp) • the-grammar of PROC • from chapter3/ proc-lang/*/lang.scm • Double-quoted items are terminals/tokens. (expression ("proc" "(" identifier ")" expression) proc-exp) (expression ("(" expression expression ")") call-exp) )) CS784(pm) 26 Specifying Grammars Grammar ::= ({Production}∗) Production ::= (Lhs ({Ritem}∗) Prod-name) Lhs ::= Symbol Ritem ::= Symbol | String ::= (arbno {Ritem}∗) ::= (separated-list {Ritem}∗ String) Prod-name ::= Symbol CS784(pm) • A grammar in SLLGEN is a list described by the grammar at left 27 HW2 Problem (define closure (lambda (ids body env) (let ((freevars (set-diff (free-vars body) ids))) (let ((saved-env (extend-env freevars (map (lambda (v) (apply-env env v)) freevars) (empty-env)))) (lambda (args) (eval-expression body (extend-env ids args saved-env))))))) CS784(pm) • • • • http://www.cs.wright.edu/~pmateti/Course s/784/Top/784-HW2.html In our data-structure representation of procedures, we have kept the entire environment in the closure. But of course all we need are the bindings for the free variables. Modify the representation of procedures to retain only the free variables. flat closure rep shown left – • • • consists of exactly one rib of free variables and their values. free-vars: ykwim ;-) set-diff: difference of two sets map provided from r5rs 28