For these problems and for future reference,letrec-expandprim-appvariants ofexpressionhave been added, and aprimitivedata type has been defined.Here are
define-datatypedefinitions forexpressionandprimitiveand a definition ofparsefor converting Scheme syntax into abstract syntax.Changes and additions are highlighted. Note, for example, that (plus x y) and (+ x y) have different abstract syntax.
(define-datatype expression expression? (var-exp (id symbol?)) (lit-exp (datum number?)) (primapp-exp (prim primitive?) (rands (list-of expression?))) (if-exp (test-exp expression?) (true-exp expression?) (false-exp expression?)) (proc-exp (ids (list-of symbol?)) (body expression?)) (let-exp (ids (list-of symbol?)) (exps (list-of expression?)) (body expression?)) (letrec-exp (ids (list-of symbol?)) (exps (list-of expression?)) (body expression?)) (app-exp (rator expression?) (rands (list-of expression?)))) (define-datatype primitive primitive? (add-prim) (subtract-prim) (mult-prim) (incr-prim) (decr-prim)) (define parse (lambda (datum) (cond ((symbol? datum) (var-exp datum)) ((number? datum) (lit-exp datum)) ((pair? datum) (cond ((eqv? (car datum) 'if) (if-exp (parse (cadr datum)) (parse (caddr datum)) (parse (cadddr datum)))) ((memv (car datum) '(+ - * add1 sub1)) (primapp-exp (case (car datum) ((+) (add-prim)) ((-) (subtract-prim)) ((*) (mult-prim)) ((add1) (incr-prim)) ((sub1) (decr-prim))) (map parse (cdr datum)))) ((eqv? (car datum) 'lambda) (proc-exp (cadr datum) (parse (caddr datum)))) ((eqv? (car datum) 'let) (let ((ids (map car (cadr datum))) (datums (map cadr (cadr datum)))) (let-exp ids (map parse datums) (parse (caddr datum))))) ((eqv? (car datum) 'letrec) (let ((ids (map car (cadr datum))) (datums (map cadr (cadr datum)))) (letrec-exp ids (map parse datums) (parse (caddr datum))))) (else (app-exp (parse (car datum)) (map parse (cdr datum)))))) (else (error 'parse "bad syntax ~s" datum)))))
- In Assignment 2, you extended
lex-add-parsedfrom cs17d5.scm sowhere(lexical-address datum) => lexical address of datumis correct for Scheme expressions with(define lexical-address (lambda (datum) (lex-add-parsed (parse datum) '())))iforlet.Extend it further so it works for Scheme expressions with
- a primitive procedure
+, -, *, add1, decr1, orletrecFor your convenience, here is a solution to the Assignment 2 problem.
(define index-of (lambda (x lst) (if (null? lst) #f (if (eqv? x (car lst)) 0 (let ((v (index-of x (cdr lst)))) (if v (+ v 1) v)))))) ;; (depth-pos v vlsts d0) -- returns depth and position, (: d p), ;; of a variable within a list of lists, vlsts, relative to d0, ;; else (: free). (define depth-pos (lambda (v vlsts d) (if (null? vlsts) (list ': 'free) (let ((p (index-of v (car vlsts)))) (if p (list ': d p) (depth-pos v (cdr vlsts) (+ d 1))))))) ;; (lex-add-parsed exp vlsts) ;; => lexical address of abstract syntax exp relative to vlsts. (define lex-add-parsed (lambda (exp vlsts) (cases expression exp (lit-exp (datum) datum) (var-exp (id) (cons id (depth-pos id vlsts 0))) (if-exp (test-exp true-exp false-exp) (list 'if (lex-add-parsed test-exp vlsts) (lex-add-parsed true-exp vlsts) (lex-add-parsed false-exp vlsts))) (primapp-exp (prim rands) ADD CODE HEE) (proc-exp (ids body) (list 'lambda ids (lex-add-parsed body (cons ids vlsts)))) (let-exp (ids exps body) (list 'let (map (lambda (id exp) (list id (lex-add-parsed exp vlsts))) ids exps) (lex-add-parsed body (cons ids vlsts)))) (letrec-exp (ids exps body) ADD CODE HERE) (app-exp (rator rands) (cons (lex-add-parsed rator vlsts) (map (lambda (rand) (lex-add-parsed rand vlsts)) rands))) (else (error 'lex-add-parsed "not done ~s" exp)))))- Define a
do-testsexpression which testslexical-addresson examples of your invention. RecallHere is a start. Replace x, y and z by interesting cases and insert the correct answers so your tests pass all OK. You need to implement both primapp-exp and letrec-exp for the last to work.(define writeln (lambda args (for-each display args) (newline))) (define do-tests (lambda (proc-name proc tests results) (writeln "Testing " proc-name) (for-each (lambda (test result) (let ((val (apply proc test))) (pretty-print `(,proc-name ,@test)) (writeln " => ") (pretty-print val) (if (equal? val result) (writeln "OK") (writeln "Not OK. Should be " result)) (newline))) tests results) (writeln "Done " proc-name) (newline)))(do-tests 'lexical-address lexical-address (map list '( x y z (let ((x a) (y b) (f (lambda (x) (plus x y)))) (f y)) (letrec ((x a) (y b) (f (lambda (x) (+ x y)))) (f y)) )) '( #f #f #f (let ((x (a : free)) (y (b : free)) (f (lambda (x) ((plus : free) (x : 0 0) (y : free))))) ((f : 0 2) (y : 0 1))) (letrec ((x (a : free)) (y (b : free)) (f (lambda (x) (+ (x : 0 0) (y : 1 1))))) ((f : 0 2) (y : 0 1))) ))- Optional -- Implement the unfinished procedures for
pefrom Day 8.assgn3.scm must be loadable into Scheme and procedures must pass tests of correctness.