;
; util.scm - miscellaneous utility procedures
; Total Procedures in Scheme, May 2006, Chris Pressey
; For license information, see the file LICENSE in this directory.
;
;
; Determine if a Scheme datum is acyclic.
;
(define acyclic?
(lambda (pair)
(acyclic-test pair '())))
(define acyclic-test
(lambda (pair acc)
(cond
((not (pair? pair))
#t)
((memq pair acc)
#f)
(else
(let ((fst (car pair))
(snd (cdr pair))
(new-acc (cons pair acc)))
(and (acyclic-test fst new-acc) (acyclic-test snd new-acc)))))))
;
; XXX explain and/or borrow eopl:error
;
(define-total error
(lambda (msg)
(display msg) (newline)
(read '())))
;
; Test case for test suite.
;
(define-syntax test
(syntax-rules ()
((test test-name expr expected)
(begin
(display "Running test: ") (display (quote test-name)) (display "... ")
(let ((result expr))
(cond
((equal? result expected)
(display "passed.") (newline))
(else
(display "FAILED!") (newline)
(display "Expected: ") (display expected) (newline)
(display "Actual: ") (display result) (newline))))))))
;
; XXX there may be a problem doing NON-TAIL (self-)recursion, check it out.
;
(define-total bindings->names
(lambda (bindings)
(if (acyclic? bindings)
(cond
((null? bindings)
'())
(else
(let* ((binding (car bindings))
(rest (cdr bindings))
(name (car binding)))
(cons name (bindings->names rest))))))))
(define-total bindings->values
(lambda (bindings)
(if (acyclic? bindings)
(cond
((null? bindings)
'())
(else
(let* ((binding (car bindings))
(rest (cdr bindings))
(value (cadr binding)))
(cons value (bindings->values rest))))))))
(define-total is-lambda?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'lambda (car expr-rep)))))
(define-total is-let?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'let (car expr-rep)))))
(define-total is-let*?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'let* (car expr-rep)))))
(define-total is-if?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'if (car expr-rep)))))
(define-total is-cond?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'cond (car expr-rep)))))
(define-total is-begin?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'begin (car expr-rep)))))
(define-total is-call?
(lambda (expr-rep)
(and
(pair? expr-rep)
(not (eq? (car expr-rep) 'quote))))) ;... and all others
(define-total is-identifier?
(lambda (expr-rep)
(symbol? expr-rep)))
(define-total is-quote?
(lambda (expr-rep)
(and
(pair? expr-rep)
(eq? 'quote (car expr-rep)))))