;;; File: ;;; semantics.scm ;;; Author: ;;; Samuel A. Rebelsky ;;; Your Name Here ;;; Version: ;;; 0.1 of March 2005 ;;; Summary: ;;; A naive implementation of Scheme using the formal semantics ;;; of Scheme, intended primarily as an illustration of the ;;; semantics. ;;; Contents: ;;; Utility Functions ;;; (reduced? val) - Determine if val is in final form ;;; (reduce exp) - Do *one* step of reduction of exp ;;; (apply-lambda lambda-exp (exp0 ... expn)) ;;; (substitute replacement sym exp) - Substitute replacement ;;; for all unbound versions of sym in exp. ;;; Valid Scheme Expressions: ;;; Atomic symbol ;;; Number ;;; (lambda (symbols) exp0 ... expn) -- Function ;;; (pair exp exp) -- Pair for building lists ;;; (exp0 exp1 ... expn) -- Application ; +--------------------+---------------------------------------------- ; | Utility Procedures | ; +--------------------+ ;;; Procedure: ;;; reduced? ;;; Parameters: ;;; exp, a representation of a Scheme expression ;;; Purpose: ;;; Determine if exp is in "final form" (cannot be further reduced). ;;; Produces: ;;; is-reduced, a Boolean value ;;; Preconditions: ;;; exp is a valid Scheme expression. ;;; Postconditions: ;;; is-reduced is true (#t) if exp is a symbol, number, lambda expression, ;;; or pair of reduced values. ;;; is-reduced is false (#f) otherwise (define reduced? (lambda (exp) (or (symbol? exp) (number? exp) (and (list? exp) (or (eq? (car exp) 'lambda) (and (eq? (car exp) 'pair) (reduced? (cadr pair)) (reduced? (caddr pair)))))))) ;;; Procedure: ;;; reduce ;;; Parameters: ;;; exp, a representation of a Scheme expression ;;; Purpose: ;;; Does *one* step of reducing the given expression. ;;; Produces: ;;; partially-reduced, a representation of a Scheme expression ;;; Preconditions: ;;; exp is a valid Scheme expression ;;; exp is not reduced ;;; Postconditions: ;;; partially-reduced is logically equivalent to exp ;;; Only one "component" of partially-reduced is not equal to the ;;; corresponding component of exp. ;;; Process: ;;; Note that it is much easier to implement a complete reduction: ;;; If the thing is a list, completely reduce all elements, apply ;;; the function, and then completely reduce again. ;;; We need to scan through non-lists, checking each value in ;;; turn and stopping when we hit the first non-reduced value. ;;; We'll use an accumulator to gather the reduced values in ;;; reverse order. (define reduce (letrec ((reduce-helper (lambda (to-check checked) (cond ; If there's nothing left to check, we can apply ; the function that should be in the first position. ((null? to-check) (apply-lambda (reverse checked))) ; If the first thing is reduced, continue on the rest. ((reduced? (car to-check)) (reduce-helper (cdr to-check) (cons (car to-check) checked))) ; Otherwise, the first thing must be reduced. (else (append (reverse checked) (reduce (car to-check)) (cdr to-check))))))))) (lambda (exp) (reduce-helper exp)) ;;; Procedure: ;;; apply-lambda