; Code constructed in Class for Logic Expression Evaluator ; Robert Keller, 22 Sept. 2008, Lecture 6 ; The construction is similar to that of a Scheme interpreter ; Note: This version has minimal checking for user errors in the expression. ; Error checking should be added. ; An expression to be evaluated has one of these forms: ; 0 ; 1 ; V where V is any symbol, representing a variable ; (not E) where E is any valid logic expression ; (and E F) where E and F are any valid logic expressions ; (or E F) ; (implies E F) ; (let Q E) where Q is a list of equations and E is a valid logic expression ; An equation has the form ; (V E) where V is any symbol and E is an expression to be evaluated (load "tester.scm") (define (myval exp env) (cond ((isZero exp) 0) ; constant 0 ((isOne exp) 1) ; constant 1 ((isVar exp) (lookup exp env)) ; variable ((list? exp) ; some kind of function app, or let (case (first exp) ;; operator ('not (myNot ; not function (myval (second exp) env))) ; The argument must be evaluated first. ('and (myAnd ; and function (myval (second exp) env) (myval (third exp) env))) ('or (myOr ; or function (myval (second exp) env) (myval (third exp) env))) ('implies (myImplies ; implies function (myval (second exp) env) (myval (third exp) env))) ('let (myLet ; let form (second exp) ; equations (third exp) env)) ; result expression (else (error "unidentified operator " (first exp))) )) (else (error "don't know")) )) ; Discriminators of various kinds (define (isOne exp) (equal? exp 1)) (define (isZero exp) (equal? exp 0)) (define (isVar exp) (symbol? exp)) ; Define the meaning of basic functions (define (myNot x) (- 1 x)) (define (myAnd x y) (* x y)) (define (myOr x y) (myNot (myAnd (myNot x) (myNot y)))) ;; Yay, DeMorgan! (define (myImplies x y) (myOr (myNot x) y)) ; Get the value of a variable in an environment (define (lookup var env) (let ((found (assoc var env))) (if found (second found) (error "unbound variable " var)))) ; Evaluate a let form (define (myLet equations result-exp env) (let ( (vars (map first equations)) (values (map (lambda(exp) (myval (second exp) env)) equations)) ) (myval result-exp (newenv vars values env)) )) ; Add bindings to the environment ; Note: These additions are not permanent. (define (newenv vars values env) (if (null? vars) env (cons (list (first vars) (first values)) (newenv (rest vars) (rest values) env)))) ; Test cases with no variables, empty environment (test (myval '0 ()) 0) (test (myval '1 ()) 1) (test (myval '(not 0) ()) 1) (test (myval '(not 1) ()) 0) (test (myval '(not (not 0)) ()) 0) (test (myval '(and 0 0) ()) 0) (test (myval '(and 0 1) ()) 0) (test (myval '(and 1 0) ()) 0) (test (myval '(and 1 1) ()) 1) (test (myval '(or 0 0) ()) 0) (test (myval '(or 0 1) ()) 1) (test (myval '(or 1 0) ()) 1) (test (myval '(or 1 1) ()) 1) (test (myval '(implies 0 0) ()) 1) (test (myval '(implies 0 1) ()) 1) (test (myval '(implies 1 0) ()) 0) (test (myval '(implies 1 1) ()) 1) ; Test cases with x and y bound to constants in the environment (test (myval '(and x x) '((x 0) (y 1))) 0) (test (myval '(and x y) '((x 0) (y 1))) 0) (test (myval '(and y x) '((x 0) (y 1))) 0) (test (myval '(and y y) '((x 0) (y 1))) 1) (test (myval '(or x x) '((x 0) (y 1))) 0) (test (myval '(or x y) '((x 0) (y 1))) 1) (test (myval '(or 1 0) '((x 0) (y 1))) 1) (test (myval '(or y x) '((x 0) (y 1))) 1) (test (myval '(implies x x) '((x 0) (y 1))) 1) (test (myval '(implies x y) '((x 0) (y 1))) 1) (test (myval '(implies y x) '((x 0) (y 1))) 0) (test (myval '(implies y y) '((x 0) (y 1))) 1) ; Test cases where the environment is augmented with values from let (test (myval '(let ((x 0) (y 0)) (implies x y)) ()) 1) (test (myval '(let ((x 0) (y 1)) (implies x y)) ()) 1) (test (myval '(let ((x 1) (y 0)) (implies x y)) ()) 0) (test (myval '(let ((x 1) (y 1)) (implies x y)) ()) 1) ; Test cases where right-hand sides of equations are expressions (test (myval '(let ((x (or 0 0)) (y (and 0 0))) (implies x y)) ()) 1) (test (myval '(let ((x (or 0 1)) (y (and 0 1))) (implies x y)) ()) 0) (test (myval '(let ((x (or 1 0)) (y (and 1 0))) (implies x y)) ()) 0) (test (myval '(let ((x (or 1 1)) (y (and 1 1))) (implies x y)) ()) 1) (tester 'show)