#!r6rs
;; Copyright (c) 2009 Derick Eddington.  All rights reserved.
;; Licensed under an MIT-style license.  My license is in the file
;; named LICENSE from the original collection this file is distributed
;; with.  If this file is redistributed with some other collection, my
;; license must also be included.

(library (srfi private feature-cond)
  (export
    feature-cond)
  (import
    (rnrs)
    (srfi private registry))

  (define-syntax feature-cond
    (lambda (stx)
      (define (identifier?/name=? x n)
        (and (identifier? x)
             (symbol=? n (syntax->datum x))))
      (define (make-test t)
        (define (invalid-test)
          (syntax-violation #F "invalid test syntax" stx t))
        (syntax-case t ()
          ((c x ...)
           (identifier?/name=? (syntax c) (quote and))
           (cons (syntax and) (map make-test (syntax (x ...)))))
          ((c x ...)
           (identifier?/name=? (syntax c) (quote or))
           (cons (syntax or) (map make-test (syntax (x ...)))))
          ((c x ...)
           (identifier?/name=? (syntax c) (quote not))
           (if (= 1 (length (syntax (x ...))))
             (list (syntax not) (make-test (car (syntax (x ...)))))
             (invalid-test)))
          (datum
           (not (and (identifier? (syntax datum))
                     (memq (syntax->datum (syntax datum))
                           (quote (and or not else)))))
           (syntax (and (member (quote datum) available-features) #T)))
          (_ (invalid-test))))
      (syntax-case stx ()
        ((_ (test . exprs) ... (e . eexprs))
         (identifier?/name=? (syntax e) (quote else))
         (with-syntax (((clause ...)
                        (map cons (map make-test (syntax (test ...)))
                                  (syntax (exprs ...)))))
           (syntax (cond clause ... (else . eexprs)))))
        ((kw (test . exprs) ...)
         (syntax (kw (test . exprs) ... (else (no-clause-true))))))))

  (define (no-clause-true)
    (assertion-violation (quote feature-cond) "no clause true"))
)
