Subt model interpreter Introduction Components of the interpreter
Subt. model interpreter: Introduction Components of the interpreter: • Closure • Global Env. Data Structures • Op. semantics • Special forms Core Abstract Syntax Parser Derived Expressions Utils (a racket lib) 1 Test • ADT per expressions • An abstraction barrier • Used by all evaluators
Subt. model interpreter: Tests package: Should be run with every modification! The procedure test: • Receives a single expression, e, and an expected value, v. • Returns #t if and only if e evaluates to v. (test (derive-eval ‘(* 3 4)) => ‘(value 12)) The procedure run-tests: • Runs multiple number test expressions (run-tests (test (derive-eval ‘(+ 3 4)) => ‘(value 7)) (test (derive-eval ‘(- 3 4)) => ‘(value -1)) (test (derive-eval ‘(/ 4 2)) => ‘(value 2))) 2
Subt. model interpreter: Core main-loop: (define applicative-eval (lambda (exp) (cond ((atomic? exp) (eval-atomic exp)) ((special-form? exp) (eval-special-form exp)) ((evaluator-value? exp) ((application? exp) (let ((renamed-exp (rename exp))) (apply-procedure (applicative-eval (operator renamed-exp)) (list-of-values (operands renamed-exp))))) (else (error 'eval "unknown expression type: ~s" exp))))) applicative -eval (define apply-procedure (lambda (procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure arguments)) ((compound-procedure? procedure) (let ((parameters (procedure-parameters procedure)) (body (rename (procedure-body procedure)))) (eval-sequence (substitute body parameters arguments)))) (else (error 'apply "Unknown procedure type: ~s" procedure))))) applyprocedure 3 substitute rename
Subt. model interpreter: Core A reminder: Why do we need renaming? The problem: 1. ( (lambda(x) 2. (lambda(y) (y x))) 3. • • (lambda(y) (y (lambda(x) (+ x y)))) (lambda(x) (+ x y)) ) y in line 2 is bound. y in line 3 is free. • The free occurrence of y is now bound by the formal parameter. The solution: consistently rename bound occurrences and their binding instances: 1. ( (lambda(x) 2. (lambda(y 1) (y 1 x))) 3. 4 (lambda(x) (+ x y)) ) (lambda(y 1) (y 1 (lambda(x) (+ x y))))
Subt. model interpreter: Supporting case expressions Example of using a case expression: (define fib (lambda (n) control (case n (0 0) clauses (1 1) last clause (else (+ (fib (- n 1)) (fib (- n 2))))))) ASP Derived expressions Core What are the components of a case expressions? What are the components of a case-clause? Data structures 5
Subt. model interpreter: Core - Special Forms Supporting case as a special form Step 1: call the appropriate special evaluation procedure (define eval-special-form (lambda (exp) (cond ((quoted? exp) (make-symbol exp)) ((lambda? exp) (eval-lambda exp)) ((definition? exp) (eval-definition exp)) ((if? exp) (eval-if exp)) ((begin? exp) (eval-begin exp)) ((case? exp) (eval-case exp))))) ASP Derived expressions Core Step 2: Identify the expression as a special form (define special-form? (lambda (exp) (or (quoted? exp) (lambda? exp) (definition? exp) (if? exp) (begin? exp) (case? exp)))) 6 Data structures
Subt. model interpreter: Core - Special Forms Supporting case as a special form Step 3: Write the relevant special evaluation procedure Determining the evaluation rule for a case expression: 1. Evaluate the control. 2. Compare its value to each of the compared components by order (assume numerical values). 3. Evaluate the actions of the first clause in which the compared value equals the control value. 4. If no such clause exists, evaluate the actions of the else-clause by order. 7 (define fib (lambda (n) (case n (0 0) (1 1) (else (+ (fib (- n 1)) (fib (- n 2)…)
Subt. model interpreter: Core - Special Forms Supporting case as a special form Step 3: Write the relevant special evaluation procedure (define (eval-case exp) (letrec ((eval-clauses (lambda (control clauses) (cond ((null? clauses) 'unspecified) ((or (case-last-clause? clauses) (= (applicative-eval (case-compared ( case-first-clauses))) control)) (eval-sequence (case-actions (case-first-clauses)))) (else (eval-clauses control (case-rest-clauses)))))) ) (eval-clauses (applicative-eval (case-control exp)) (case-clauses exp)))) 8 (define fib (lambda (n) (case n (0 0) (1 1) (else (+ (fib (- n 1)) (fib (- n 2)…)
Subt. model interpreter: ASP - Handling lambda expressions ADT and implementation : ; Signature: make-lambda(parameters, body) ; Type: [LIST(Symbol)*LIST -> LIST] (define make-lambda (parameters body) (attach-tag (cons parameters body) 'lambda))) ; Signature: lambda-parameters(exp) ; Type: [LIST -> LIST(Symbol)] (define lambda-parameters (lambda (exp) (car (get-content exp)))) ; Signature: lambda-body(exp) ; Type: [LIST -> LIST] (define lambda-body (lambda (exp) (cdr (get-content exp)))) ; Signature: lambda? (exp) ; Type: [T -> Boolean] (define lambda? (lambda (exp) (tagged-by? exp 'lambda))) 9 ASP Derived expressions Core Data structures
Subt. model interpreter: Supporting case expressions ADT for case expressions (including ADT for case-clause): Constructor for case-clause make-case(control case-clauses) Type: [Symbol*LIST -> Case-expression] make-case-clause(compared actions) Type: [T*LIST -> LIST] Selectors Predicate case-compared case? (exp) Type: [T -> Boolean] case-actions Selectors case-first-clause case-control(case-exp) Type: [LIST -> Symbol] case-clauses(case-exp) Type: [LIST -> LIST] case-rest-clauses Predicate case-last-clause? Example of use (client side): (make-case 'n (list (make-case-clause '0 '(0)) (make-case-clause '1 '(1)) (make-case-clause 'else '(+ (fib (- n 1)) (fib (– n 2)))))) 10
Subt. model interpreter: Supporting case expressions Adding the implementation in the ASP: Co (define make-case nst ruc tor (lambda (control case-clauses) (attach-tag (cons control case-clauses) 'case))) (define case-control (lambda (case-exp) (car (get-content case-exp)))) Se lec tor s (define case-clauses (lambda (case-exp) (cdr (get-content case-exp)))) (define case? (lambda (exp) (tagged-by? exp 'case))) 11 Pre dic a (define make-case-clause (lambda (compared actions) (cons compared actions))) Co nst ruc (define case-compared car) (define case-actions cdr) (define case-first-clause (lambda (clauses) (car clauses))) Sel ect o rs (define case-rest-clauses (lambda (clauses) (cdr clauses))) Pr te tor ed (define case-last-clause? ica te (lambda (clauses) (and (null? (cdr clauses)) (eq? (case-compared (case-first-clauses)) 'else))))
Subt. model interpreter: Derived expressions Why? Smaller, simpler core! (let ((x 1)) x) ((lambda(x) x) 1) How? ASP derived? shallowderive Identifies the derived expression, calls the appropriate shallow translation procedure: derive Derived expressions Recursively applies shallow-derive Core ((cond? exp) (cond->if exp)) ⁞ ((let? exp) (let->combination exp)) 1. 2. 3. 12 Edit derive? to consider the new exp as derived. Edit shallow-derive to call the relevant translation procedure. Add a shallow translation procedure. Data structures
Subt. model interpreter: Derived expressions ASP Derived expressions Core 1. 2. 3. 14 Edit derive? to consider the new exp as derived. Edit shallow-derive to call the relevant translation procedure. Add a shallow translation procedure. Data structures
Subt. model interpreter: Data Structures The Global Environment: (define make-the-global-environment (lambda () (let* ((primitive-procedures (list 'car car) (list 'cdr cdr) (list 'cons) (list 'null? ) (list '+ +) (list '* *) (list '/ /) (list '> >) (list '< <) (list '- -) (list '= =) (list 'list) (list 'append) )) (prim-variables (map car primitive-procedures)) (prim-values (map (lambda (x) (make-primitive-procedure (cadr x))) primitive-procedures)) ) (make-sub prim-variables prim-values)))) 15 ASP Derived expressions Core Data structures
Subt. model interpreter: Data Structures The Global Environment: (define get-value-of-variable (lambda (sub var) (letrec ((lookup (lambda (vars vals) (cond ((or (empty-sub? sub) (not (member vars))) (error 'get-value-of-variable)) ((eq? var (car vars)) (car vals)) (else (lookup (cdr vars) (cdr vals))))))) (lookup (get-variables sub) (get-values sub))))) ASP Derived expressions Core Data structures 16
- Slides: 15