;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname M) (read-case-sensitive #t) (teachpacks ((lib "world.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "world.ss" "teachpack" "htdp"))))) ; ; ::= ( + ) ; | ( * ) ; | ; | ; | ifZero( , , ) ; ; Examples of *strings* which are valid programs. ; x ; 3 ; ( 1 + 2 ) ; ( 4 * ( 1 + 2 ) ) ; ( x + ( 2 * y ) ) ; ifZero(3,4,5) ; ( 3 + ifZero(x, (2*y), 17) ) ; ifZero( ifZero(x,y,0), ifZero((3*z),y,y), 17 ) ; ;; Here are examples of *internal representation* of the programs: ;; ;; x => 'x ;; 3 => 3 ;; (1+2) => (make-sum 1 2) ;; (4 * (1 + 2)) => (make-prod 4 (make-sum 1 2)) ;; We can actually formalize this notion, ;; rather than use the fuzzy "=>" notation: ;; parsing is a function that takes in a string, and returns the internal ;; representation. ;; (check-expect (parse "x") 'x) (check-expect (parse "3") 3) (check-expect (parse "(1+2)") (make-sum 1 2)) (check-expect (parse "(4 * (1 + 2))") (make-prod 4 (make-sum 1 2) )) (check-expect (parse "( x + ( 2 * y ))") (make-sum 'x (make-prod 2 'y))) (check-expect (parse "ifZero(3,4,5)") (make-ifZero 3 4 5)) (check-expect (parse "( 3 + ifZero(x, (2*y), 17) )") (make-sum 3 (make-ifZero 'x (make-prod 2 'y) 17))) ;; We'll define 'parse' later; right now just stub it out ;; so that check-expect works. (Even though we won't pass the test cases.) (define parse identity) ;; make-sum : AExpr, AExpr -> sum ;; (make-sum [AExpr] [AExpr]) (define-struct sum (left right)) (define-struct prod (left right)) (define-struct ifZero (test then else)) ;; Examples of *my* data (the internal representation: 'x 3 (make-sum 1 2) (make-prod 4 (make-sum 1 2) ) (make-sum 'x (make-prod 2 'y)) (make-ifZero 3 4 5) (make-sum 3 (make-ifZero 'x (make-prod 2 'y) 17)) (check-expect (evalM 3) 3) (check-expect (evalM (make-sum 1 2)) 3) (check-expect (evalM (make-sum (make-prod (make-sum 3 4) (make-sum 5 6)) 17)) 94) ; (evalM 'x) should blow up at run-time, "unbound variable" ;; evalM : AExpr -> num (define (evalM an-aexpr) (cond [(number? an-aexpr) an-aexpr] [(symbol? an-aexpr) (error 'evalM (format "Unbound variable: ~a" an-aexpr))] [(sum? an-aexpr) (+ (evalM (sum-left an-aexpr)) (evalM (sum-right an-aexpr)))] [(prod? an-aexpr) (* (evalM (prod-left an-aexpr)) (evalM (prod-right an-aexpr)))] [(ifZero? an-aexpr) (if (= 0 (evalM (ifZero-test an-aexpr))) (evalM (ifZero-then an-aexpr)) (evalM (ifZero-else an-aexpr)))] )) ;; m-to-string : AExpr -> string (define (m-to-string an-aexpr) (cond [(number? an-aexpr) (number->string an-aexpr)] [(symbol? an-aexpr) (symbol->string an-aexpr)] [(sum? an-aexpr) (string-append "(" (m-to-string (sum-left an-aexpr)) " + " (m-to-string (sum-right an-aexpr)) ")")] [(prod? an-aexpr) (string-append "(" (m-to-string (prod-left an-aexpr)) " * " (m-to-string (prod-right an-aexpr)) ")")] [(ifZero? an-aexpr) (string-append "ifZero(" (m-to-string (ifZero-test an-aexpr)) ", " (m-to-string (ifZero-then an-aexpr)) ", " (m-to-string (ifZero-else an-aexpr)) ")")] )) ;; ::= set <-- in ;; "set x <-- 7 in (x+3)" ;; "set x <-- set y <-- 17 in (y*3) in (x + y)"