programming abstractions
play

Programming Abstractions Week 7-2: MiniScheme A and B Stephen - PowerPoint PPT Presentation

Programming Abstractions Week 7-2: MiniScheme A and B Stephen Checkoway Structure of MiniScheme Environment env.rkt Contains the environment data type (env list-of-symbols list-of-values previous-env) Contains other procedures to


  1. Programming Abstractions Week 7-2: MiniScheme A and B Stephen Checkoway

  2. Structure of MiniScheme Environment env.rkt ‣ Contains the environment data type 
 (env list-of-symbols list-of-values previous-env) ‣ Contains other procedures to recognize and access the symbols, values, and previous environment ‣ Your task is to implement (env-lookup environment symbol)

  3. Structure of MiniScheme Parser parse.rkt ‣ Contains data types for let expressions, lambda expressions, if-then-else expressions, procedure-application expressions and so on ‣ Builds a parse tree out of these data types from an expression 
 > (parse '(let ([f (lambda (x) (+ x 1))]) (f 5))) 
 '(let-exp (f) ((lam-exp (x) ...)) (app-exp ...)) ‣ You get to implement all of this, bit by bit

  4. Structure of MiniScheme Interpreter interp.rkt ‣ Contains data types for closures and primitive procedures (i.e., built-in procedures) ‣ Takes an expression tree and an environment and returns a value 
 > (eval-exp exp-tree environment) ‣ You get to implement all of this, bit by bit, at the same time you're implementing the parser

  5. A full grammar for Minischeme EXP → number | symbol | ( if EXP EXP EXP ) | ( let ( LET-BINDINGS ) EXP ) | ( letrec ( LET-BINDINGS ) EXP ) | ( lambda ( PARAMS ) EXP ) | ( set! symbol EXP ) | ( begin EXP * ) | ( EXP + ) LET-BINDINGS → LET-BINDING * LET-BINDING → [ symbol EXP ] PARAMS → symbol *

  6. Programs are just structured lists Parsing Consider the program 
 (let ([x 10] 
 [y 20]) 
 (+ x y)) This is just a structured list containing the symbols let , f , x , y , and + and the numbers 10 and 20 Your first task is going to be to build some new data types to represent programs by parsing these structured lists

  7. Start simple: only numbers EXP → number parse into lit-exp We're going to need a data type to represent literal expression (and the only type of literals we have are numbers) We're going to want something like 
 (lit-exp num) ; constructor 
 (lit-exp? exp) ; recognizer 
 (lit-exp-num exp) ; accessor

  8. Parsing numbers Our first parser: MiniScheme A (define (parse input) 
 (cond [(number? input) (lit-exp input)] 
 [else (error 'parse "Invalid syntax ~s" input)])) This and the definition of the lit-exp data type belong in parse.rkt You don't need to implement it exactly the way I do That said, when I run (parse 52) , I get 
 '(lit-exp 52)

  9. What, exactly, is the input to parse? Scheme (and thus Racket) has a procedure (read) that reads input and returns a structured list or an atom The interpreter project flow 1. read returns a structured list which is passed to parse as the input parameter 2. parse produces a parse tree containing nodes like lit-exp , let-exp , and app-exp which is passed, along with init-env to eval-exp 3. eval-exp takes a parse tree and an environment and evaluates the expression, returning the result Do a demo with (let ([x 100] [z 25]) (+ (- x y) z))

  10. Provide the definitions (provide proc1 proc2 data1 data2 ...) We want parse.rkt to be just one module in our program so make sure to provide the procedures ‣ (provide parse) ‣ Also the procedures for creating and manipulating the lit-exp

  11. Evaluating literals Our first interpreter: MiniScheme A We'll need to require env.rkt and parse.rkt to get access to those modules' procedures The main procedure in interp.rkt is eval-exp Extracts the number from the lit-exp (define (eval-exp tree e) 
 (cond [(lit-exp? tree) (lit-exp-num tree)] 
 [else (error 'eval-exp "Invalid tree: ~s" tree)]))

  12. Putting them together > (parse 107) 
 '(lit-exp 107) > (lit-exp 107) 
 '(lit-exp 107) > (eval-exp (lit-exp 107) empty-env) 
 107 > (eval-exp (parse 107) empty-env) 
 107

  13. What does (parse 15) return (assuming the implementation we've discussed so far)? A. 15 B. the result of (number 15) C. the result of (lit-exp 15) D. the result of (lit-exp "15") E. It's an error of some sort 13

  14. What does (eval-exp 15 empty-env) return (assuming the implementation we've discussed so far)? A. 15 B. the result of (value 15) C. the result of (lit-exp 15) D. It's an error of some sort 14

  15. What does (eval-exp (lit-exp 15) empty-env) return (assuming the implementation we've discussed so far)? A. 15 B. the result of (value 15) C. the result of (lit-exp 15) D. It's an error of some sort 15

  16. Read-eval-print loop Having to call parse and then eval-exp over and over is a hassle It'd be better if we could run a read-eval-print loop that would read in an expression from the user, parse it, and evaluate it in an environment minischeme.rkt will do this for you but it needs several things ( provide ) ‣ parse.rkt - A (parse input) procedure ‣ interp.rkt - An (eval-exp tree environment) procedure - An initial environment init-env 
 Something like 
 (define init-env (env '(x y) '(23 42) empty-env))

  17. Running the read-eval-print loop Open minischeme.rkt in DrRacket, click Run Enter expressions in the box (only numbers are supported right now) Enter exit to exit MiniScheme

  18. Let's add some variables! MiniScheme B Grammar 
 EXP → number parse into lit-exp 
 | symbol parse into var-exp Data type for a variable reference expression ‣ (var-exp symbol) ‣ (var-exp? exp) ‣ (var-exp-symbol exp)

  19. Parsing symbols MiniScheme B (define (parse input) 
 (cond [(number? input) (lit-exp input)] 
 [(symbol? input) (var-exp input)] 
 [else (error 'parse "Invalid syntax ~s" input)])) When I run (parse 'foo) , I get 
 '(var-exp foo)

  20. Interpreting symbols MiniScheme B (define (eval-exp tree e) 
 (cond [(lit-exp? tree) (lit-exp-num tree)] 
 [(var-exp? tree) 
 (env-lookup e (var-exp-symbol tree))] 
 [else (error 'eval-exp "Invalid tree: ~s" tree)])) You'll need a working env-lookup > (env-lookup init-env 'x) 
 23 
 > (eval-exp '(var-exp x) init-env) 
 23

  21. What can MiniScheme do at this point? MiniScheme B has constant numbers MiniScheme B has pre-bound symbols that are in the init-env

  22. Homeworks 6 and 7 Multiple steps, each adding parts to the EXP → number | symbol MiniScheme interpreter | ( if EXP EXP EXP ) | ( let ( LET-BINDINGS ) EXP ) For each new type of expression | ( letrec ( LET-BINDINGS ) EXP ) ‣ Add a new data type | ( lambda ( PARAMS ) EXP ) - ift-exp | ( set! symbol EXP ) - let-exp | ( begin EXP * ) - etc. | ( EXP EXP * ) ‣ Add constructors, recognizers and LET-BINDINGS → LET-BINDING * LET-BINDING → [ symbol EXP ] accessors PARAMS → symbol * ‣ Modify parse to produce those ‣ Modify eval-exp to interpret them

  23. Let's add arithmetic and some list procedures MiniScheme C Let's add + , - , * , / , car , cdr , cons , etc. Students find this to be the hardest part of the project ‣ It's the first complex part ‣ It contains some things that make more sense later, once we add lambda expressions

  24. Many ways to call procedures (+ 2 3) ((lambda (x y) (+ x y) 2 3) (let ([f +]) (f 2 3) The parser can't identify primitive procedures like + because symbols like f may be bound to primitive procedures ‣ It can't tell because the parser does not have access to the environment All that the parser can do is recognize a procedure application and parse ‣ the procedure; and ‣ the arguments

Recommend


More recommend