123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- ;;; Copyright (C) 2020 Wolfgang Corcoran-Mathe
- ;;;
- ;;; Permission is hereby granted, free of charge, to any person obtaining a
- ;;; copy of this software and associated documentation files (the
- ;;; "Software"), to deal in the Software without restriction, including
- ;;; without limitation the rights to use, copy, modify, merge, publish,
- ;;; distribute, sublicense, and/or sell copies of the Software, and to
- ;;; permit persons to whom the Software is furnished to do so, subject to
- ;;; the following conditions:
- ;;;
- ;;; The above copyright notice and this permission notice shall be included
- ;;; in all copies or substantial portions of the Software.
- ;;;
- ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- ;;; OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- ;;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- ;;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- ;;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- ;;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ;;;
- ;;;; Utility
- (define-syntax assert
- (syntax-rules ()
- ((assert expr)
- (unless expr
- (error "assertion failed" 'expr)))
- ((assert expr msg)
- (unless expr
- (error msg 'expr)))))
- (define (exact-natural? obj)
- (and (exact-integer? obj) (not (negative? obj))))
- (define (bitvector-subset? vec1 vec2)
- (let loop ((i (- (bitvector-length vec1) 1)))
- (cond ((< i 0) #t)
- ((and (bitvector-ref/bool vec1 i)
- (zero? (bitvector-ref/int vec2 i)))
- #f)
- (else (loop (- i 1))))))
- ;;;; Types
- (define-record-type <enum-type>
- (make-raw-enum-type enum-vector name-table comparator)
- enum-type?
- (enum-vector enum-type-enum-vector set-enum-type-enum-vector!)
- (name-table enum-type-name-table set-enum-type-name-table!)
- (comparator enum-type-comparator set-enum-type-comparator!))
- (define-record-type <enum>
- (make-enum type name ordinal value)
- enum?
- (type enum-type)
- (name enum-name)
- (ordinal enum-ordinal)
- (value enum-value))
- (define (make-enum-type names+vals)
- (assert (or (pair? names+vals) (null? names+vals))
- "argument must be a proper list")
- (let* ((type (make-raw-enum-type #f #f #f))
- (enums (generate-enums type names+vals)))
- (set-enum-type-enum-vector! type (list->vector enums))
- (set-enum-type-name-table! type (make-name-table enums))
- (set-enum-type-comparator! type (make-enum-comparator type))
- type))
- (define (generate-enums type names+vals)
- (map (lambda (elt ord)
- (cond ((and (pair? elt) (= 2 (length elt)) (symbol? (car elt)))
- (make-enum type (car elt) ord (cadr elt)))
- ((symbol? elt) (make-enum type elt ord ord))
- (else (error "make-enum-type: invalid argument" elt))))
- names+vals
- (iota (length names+vals))))
- (define symbol-comparator
- (make-comparator symbol?
- eqv?
- (lambda (sym1 sym2)
- (string<? (symbol->string sym1)
- (symbol->string sym2)))
- symbol-hash))
- (define (make-name-table enums)
- (hash-table-unfold null?
- (lambda (enums)
- (values (enum-name (car enums)) (car enums)))
- cdr
- enums
- symbol-comparator))
- (define (%enum-type=? etype1 etype2)
- (eqv? etype1 etype2))
- (define (make-enum-comparator type)
- (make-comparator
- (lambda (obj)
- (and (enum? obj) (eq? (enum-type obj) type)))
- eq?
- (lambda (enum1 enum2)
- (< (enum-ordinal enum1) (enum-ordinal enum2)))
- (lambda (enum)
- (symbol-hash (enum-name enum)))))
- ;;;; Predicates
- (define (enum-type-contains? type enum)
- (assert (enum-type? type))
- (assert (enum? enum))
- ((comparator-type-test-predicate (enum-type-comparator type)) enum))
- (define (%enum-type-contains?/no-assert type enum)
- ((comparator-type-test-predicate (enum-type-comparator type)) enum))
- (define (%well-typed-enum? type obj)
- (and (enum? obj) (%enum-type-contains?/no-assert type obj)))
- (define (%compare-enums compare enums)
- (assert (and (pair? enums) (pair? (cdr enums)))
- "invalid number of arguments")
- (assert (enum? (car enums)))
- (let ((type (enum-type (car enums))))
- (assert (every (lambda (e) (%well-typed-enum? type e)) (cdr enums))
- "enums must all belong to the same type")
- (apply compare (enum-type-comparator type) enums)))
- (define (enum=? enum1 enum2 . enums)
- (assert (enum? enum1))
- (let* ((type (enum-type enum1))
- (comp (enum-type-comparator type)))
- (cond ((null? enums) ; fast path
- (assert (%well-typed-enum? type enum2)
- "enums must all belong to the same type")
- ((comparator-equality-predicate comp) enum1 enum2))
- (else ; variadic path
- (assert (every (lambda (e) (%well-typed-enum? type e)) enums)
- "enums must all belong to the same type")
- (apply =? comp enum1 enum2 enums)))))
- (define (enum<? . enums) (%compare-enums <? enums))
- (define (enum>? . enums) (%compare-enums >? enums))
- (define (enum<=? . enums) (%compare-enums <=? enums))
- (define (enum>=? . enums) (%compare-enums >=? enums))
- ;;;; Enum finders
- ;;; Core procedures
- (define (enum-name->enum type name)
- (assert (enum-type? type))
- (assert (symbol? name))
- (hash-table-ref/default (enum-type-name-table type) name #f))
- (define (enum-ordinal->enum enum-type ordinal)
- (assert (enum-type? enum-type))
- (assert (exact-natural? ordinal))
- (and (< ordinal (enum-type-size enum-type))
- (vector-ref (enum-type-enum-vector enum-type) ordinal)))
- ;; Fast version for internal use.
- (define (%enum-ordinal->enum-no-assert enum-type ordinal)
- (vector-ref (enum-type-enum-vector enum-type) ordinal))
- ;;; Derived procedures
- (define (%enum-project type finder key proc)
- (assert (enum-type? type))
- (cond ((finder type key) => proc)
- (else (error "no enum found" type key))))
- (define (enum-name->ordinal type name)
- (assert (symbol? name))
- (%enum-project type enum-name->enum name enum-ordinal))
- (define (enum-name->value type name)
- (assert (symbol? name))
- (%enum-project type enum-name->enum name enum-value))
- (define (enum-ordinal->name type ordinal)
- (assert (exact-natural? ordinal))
- (%enum-project type %enum-ordinal->enum-no-assert ordinal enum-name))
- (define (enum-ordinal->value type ordinal)
- (assert (exact-natural? ordinal))
- (%enum-project type %enum-ordinal->enum-no-assert ordinal enum-value))
- ;;;; Enum type accessors
- (define (enum-type-size type)
- (assert (enum-type? type))
- (vector-length (enum-type-enum-vector type)))
- (define (enum-min type)
- (assert (enum-type? type))
- (vector-ref (enum-type-enum-vector type) 0))
- (define (enum-max type)
- (assert (enum-type? type))
- (let ((vec (enum-type-enum-vector type)))
- (vector-ref vec (- (vector-length vec) 1))))
- (define (enum-type-enums type)
- (assert (enum-type? type))
- (vector->list (enum-type-enum-vector type)))
- (define (enum-type-names type)
- (assert (enum-type? type))
- (let ((vec (enum-type-enum-vector type)))
- (list-tabulate (vector-length vec)
- (lambda (n) (enum-name (vector-ref vec n))))))
- (define (enum-type-values type)
- (assert (enum-type? type))
- (let ((vec (enum-type-enum-vector type)))
- (list-tabulate (vector-length vec)
- (lambda (n) (enum-value (vector-ref vec n))))))
- ;;;; Enum object procedures
- (define (enum-next enum)
- (assert (enum? enum))
- (enum-ordinal->enum (enum-type enum) (+ (enum-ordinal enum) 1)))
- (define (enum-prev enum)
- (assert (enum? enum))
- (let ((ord (enum-ordinal enum)))
- (and (> ord 0)
- (enum-ordinal->enum (enum-type enum) (- ord 1)))))
- ;;;; Enum set constructors
- (define-record-type <enum-set>
- (make-enum-set type bitvector)
- enum-set?
- (type enum-set-type)
- (bitvector enum-set-bitvector set-enum-set-bitvector!))
- (define (enum-empty-set type)
- (assert (enum-type? type))
- (make-enum-set type (make-bitvector (enum-type-size type) #f)))
- (define (enum-type->enum-set type)
- (assert (enum-type? type))
- (make-enum-set type (make-bitvector (enum-type-size type) #t)))
- (define (enum-set type . enums) (list->enum-set type enums))
- (define (list->enum-set type enums)
- (assert (or (pair? enums) (null? enums))
- "argument must be a proper list")
- (let ((vec (make-bitvector (enum-type-size type) #f)))
- (for-each (lambda (e)
- (assert (%well-typed-enum? type e) "ill-typed enum")
- (bitvector-set! vec (enum-ordinal e) #t))
- enums)
- (make-enum-set type vec)))
- ;; Returns a set of enums drawn from the enum-type/-set src with
- ;; the same names as the enums of eset.
- (define (enum-set-projection src eset)
- (assert (or (enum-type? src) (enum-set? src))
- "argument must be an enum type or enum set")
- (assert (enum-set? eset))
- (let ((type (if (enum-type? src) src (enum-set-type src))))
- (list->enum-set
- type
- (enum-set-map->list
- (lambda (enum)
- (let ((name (enum-name enum)))
- (or (enum-name->enum type name)
- (error "enum name not found in type" name type))))
- eset))))
- (define (enum-set-copy eset)
- (make-enum-set (enum-set-type eset)
- (bitvector-copy (enum-set-bitvector eset))))
- ;; [Deprecated]
- (define (make-enumeration names)
- (enum-type->enum-set (make-enum-type (zip names names))))
- ;; [Deprecated]
- (define (enum-set-universe eset)
- (assert (enum-set? eset))
- (enum-type->enum-set (enum-set-type eset)))
- ;; [Deprecated] Returns a procedure which takes a list of symbols
- ;; and returns an enum set containing the corresponding enums. This
- ;; extracts the type of eset, but otherwise ignores this argument.
- (define (enum-set-constructor eset)
- (assert (enum-set? eset))
- (let ((type (enum-set-type eset)))
- (lambda (names)
- (list->enum-set type
- (map (lambda (sym)
- (or (enum-name->enum type sym)
- (error "invalid enum name" sym)))
- names)))))
- ;; [Deprecated] Returns a procedure which takes a symbol and returns
- ;; the corresponding enum ordinal or #f. This doesn't make any use
- ;; of eset, beyond pulling out its enum type.
- (define (enum-set-indexer eset)
- (assert (enum-set? eset))
- (let ((type (enum-set-type eset)))
- (lambda (name)
- (cond ((enum-name->enum type name) => enum-ordinal)
- (else #f)))))
- ;;;; Enum set predicates
- (define (enum-set-contains? eset enum)
- (assert (enum-set? eset))
- (assert (%well-typed-enum? (enum-set-type eset) enum)
- "enum types of arguments must match")
- (bitvector-ref/bool (enum-set-bitvector eset) (enum-ordinal enum)))
- ;; FIXME: Avoid double (type, then set) lookup.
- (define (enum-set-member? name eset)
- (assert (symbol? name))
- (assert (enum-set? eset))
- (bitvector-ref/bool (enum-set-bitvector eset)
- (enum-name->ordinal (enum-set-type eset) name)))
- (define (%enum-set-type=? eset1 eset2)
- (%enum-type=? (enum-set-type eset1) (enum-set-type eset2)))
- (define (enum-set-empty? eset)
- (assert (enum-set? eset))
- (zero? (bitvector-count #t (enum-set-bitvector eset))))
- (define (bit-nand a b)
- (not (and (= 1 a) (= 1 b))))
- (define (enum-set-disjoint? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (let ((vec1 (enum-set-bitvector eset1))
- (vec2 (enum-set-bitvector eset2)))
- (let ((len (bitvector-length vec1)))
- (let loop ((i 0))
- (or (= i len)
- (and (bit-nand (bitvector-ref/int vec1 i)
- (bitvector-ref/int vec2 i))
- (loop (+ i 1))))))))
- (define (enum-set=? eset1 eset2)
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (bitvector=? (enum-set-bitvector eset1) (enum-set-bitvector eset2)))
- (define (enum-set<? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (let ((vec1 (enum-set-bitvector eset1))
- (vec2 (enum-set-bitvector eset2)))
- (and (bitvector-subset? vec1 vec2)
- (not (bitvector=? vec1 vec2)))))
- (define (enum-set>? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (let ((vec1 (enum-set-bitvector eset1))
- (vec2 (enum-set-bitvector eset2)))
- (and (bitvector-subset? vec2 vec1)
- (not (bitvector=? vec1 vec2)))))
- (define (enum-set<=? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (bitvector-subset? (enum-set-bitvector eset1)
- (enum-set-bitvector eset2)))
- (define (enum-set>=? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-type=? (enum-set-type eset1) (enum-set-type eset2))
- "arguments must have the same enum type")
- (bitvector-subset? (enum-set-bitvector eset2)
- (enum-set-bitvector eset1)))
- ;; This uses lists as sets and is thus not very efficient.
- ;; An implementation with SRFI 113 or some other set library
- ;; might want to optimize this.
- (define (enum-set-subset? eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (lset<= eqv?
- (enum-set-map->list enum-name eset1)
- (enum-set-map->list enum-name eset2)))
- (define (enum-set-any? pred eset)
- (assert (procedure? pred))
- (call-with-current-continuation
- (lambda (return)
- (enum-set-fold (lambda (e _) (and (pred e) (return #t)))
- #f
- eset))))
- (define (enum-set-every? pred eset)
- (assert (procedure? pred))
- (call-with-current-continuation
- (lambda (return)
- (enum-set-fold (lambda (e _) (or (pred e) (return #f)))
- #t
- eset))))
- ;;;; Enum set mutators
- (define (enum-set-adjoin eset . enums)
- (apply enum-set-adjoin! (enum-set-copy eset) enums))
- (define enum-set-adjoin!
- (case-lambda
- ((eset enum) ; fast path
- (assert (enum-set? eset))
- (assert (%well-typed-enum? (enum-set-type eset) enum)
- "arguments must have the same enum type")
- (bitvector-set! (enum-set-bitvector eset) (enum-ordinal enum) #t)
- eset)
- ((eset . enums) ; variadic path
- (assert (enum-set? eset))
- (let ((type (enum-set-type eset))
- (vec (enum-set-bitvector eset)))
- (for-each (lambda (e)
- (assert (%well-typed-enum? type e)
- "arguments must have the same enum type")
- (bitvector-set! vec (enum-ordinal e) #t))
- enums)
- eset))))
- (define (enum-set-delete eset . enums)
- (apply enum-set-delete! (enum-set-copy eset) enums))
- (define enum-set-delete!
- (case-lambda
- ((eset enum) ; fast path
- (assert (enum-set? eset))
- (assert (%well-typed-enum? (enum-set-type eset) enum)
- "arguments must have the same enum type")
- (bitvector-set! (enum-set-bitvector eset) (enum-ordinal enum) #f)
- eset)
- ((eset . enums) ; variadic path
- (enum-set-delete-all! eset enums))))
- (define (enum-set-delete-all eset enums)
- (enum-set-delete-all! (enum-set-copy eset) enums))
- (define (enum-set-delete-all! eset enums)
- (assert (enum-set? eset))
- (assert (or (pair? enums) (null? enums))
- "argument must be a proper list")
- (unless (null? enums)
- (let ((type (enum-set-type eset))
- (vec (enum-set-bitvector eset)))
- (for-each (lambda (e)
- (assert (%well-typed-enum? type e)
- "arguments must have the same enum type")
- (bitvector-set! vec (enum-ordinal e) #f))
- enums)))
- eset)
- ;;;; Enum set operations
- (define (enum-set-size eset)
- (assert (enum-set? eset))
- (bitvector-count #t (enum-set-bitvector eset)))
- (define (enum-set->enum-list eset)
- (assert (enum-set? eset))
- (enum-set-map->list values eset))
- (define (enum-set->list eset)
- (enum-set-map->list enum-name eset))
- ;; Slightly complicated by the order in which proc is applied.
- (define (enum-set-map->list proc eset)
- (assert (procedure? proc))
- (assert (enum-set? eset))
- (let* ((vec (enum-set-bitvector eset))
- (len (bitvector-length vec))
- (type (enum-set-type eset)))
- (letrec
- ((build
- (lambda (i)
- (cond ((= i len) '())
- ((bitvector-ref/bool vec i)
- (cons (proc (%enum-ordinal->enum-no-assert type i))
- (build (+ i 1))))
- (else (build (+ i 1)))))))
- (build 0))))
- (define (enum-set-count pred eset)
- (assert (procedure? pred))
- (enum-set-fold (lambda (e n) (if (pred e) (+ n 1) n)) 0 eset))
- (define (enum-set-filter pred eset)
- (enum-set-filter! pred (enum-set-copy eset)))
- (define (enum-set-filter! pred eset)
- (assert (procedure? pred))
- (assert (enum-set? eset))
- (let* ((type (enum-set-type eset))
- (vec (enum-set-bitvector eset)))
- (let loop ((i (- (bitvector-length vec) 1)))
- (cond ((< i 0) eset)
- ((and (bitvector-ref/bool vec i)
- (not (pred (%enum-ordinal->enum-no-assert type i))))
- (bitvector-set! vec i #f)
- (loop (- i 1)))
- (else (loop (- i 1)))))))
- (define (enum-set-remove pred eset)
- (enum-set-remove! pred (enum-set-copy eset)))
- (define (enum-set-remove! pred eset)
- (assert (procedure? pred))
- (assert (enum-set? eset))
- (let* ((type (enum-set-type eset))
- (vec (enum-set-bitvector eset)))
- (let loop ((i (- (bitvector-length vec) 1)))
- (cond ((< i 0) eset)
- ((and (bitvector-ref/bool vec i)
- (pred (%enum-ordinal->enum-no-assert type i)))
- (bitvector-set! vec i #f)
- (loop (- i 1)))
- (else (loop (- i 1)))))))
- (define (enum-set-for-each proc eset)
- (assert (procedure? proc))
- (enum-set-fold (lambda (e _) (proc e)) '() eset))
- (define (enum-set-fold proc nil eset)
- (assert (procedure? proc))
- (assert (enum-set? eset))
- (let ((type (enum-set-type eset)))
- (let* ((vec (enum-set-bitvector eset))
- (len (bitvector-length vec)))
- (let loop ((i 0) (state nil))
- (cond ((= i len) state)
- ((bitvector-ref/bool vec i)
- (loop (+ i 1)
- (proc (%enum-ordinal->enum-no-assert type i) state)))
- (else (loop (+ i 1) state)))))))
- ;;;; Enum set logical operations
- (define (%enum-set-logical-op! bv-proc eset1 eset2)
- (assert (enum-set? eset1))
- (assert (enum-set? eset2))
- (assert (%enum-set-type=? eset1 eset2)
- "arguments must have the same enum type")
- (bv-proc (enum-set-bitvector eset1) (enum-set-bitvector eset2))
- eset1)
- (define (enum-set-union eset1 eset2)
- (%enum-set-logical-op! bitvector-ior! (enum-set-copy eset1) eset2))
- (define (enum-set-intersection eset1 eset2)
- (%enum-set-logical-op! bitvector-and! (enum-set-copy eset1) eset2))
- (define (enum-set-difference eset1 eset2)
- (%enum-set-logical-op! bitvector-andc2! (enum-set-copy eset1) eset2))
- (define (enum-set-xor eset1 eset2)
- (%enum-set-logical-op! bitvector-xor! (enum-set-copy eset1) eset2))
- (define (enum-set-union! eset1 eset2)
- (%enum-set-logical-op! bitvector-ior! eset1 eset2))
- (define (enum-set-intersection! eset1 eset2)
- (%enum-set-logical-op! bitvector-and! eset1 eset2))
- (define (enum-set-difference! eset1 eset2)
- (%enum-set-logical-op! bitvector-andc2! eset1 eset2))
- (define (enum-set-xor! eset1 eset2)
- (%enum-set-logical-op! bitvector-xor! eset1 eset2))
- (define (enum-set-complement eset)
- (enum-set-complement! (enum-set-copy eset)))
- (define (enum-set-complement! eset)
- (assert (enum-set? eset))
- (bitvector-not! (enum-set-bitvector eset))
- eset)
- ;;;; Syntax
- ;; Defines a new enum-type T, binds type-name to a macro which
- ;; takes a symbol to an enum in T, and binds constructor to a
- ;; macro taking symbols to an enum set of type T.
- (define-syntax define-enum
- (syntax-rules ()
- ((_ type-name (name-val ...) constructor)
- (begin
- (define etype (make-enum-type '(name-val ...)))
- (define-syntax type-name
- (syntax-rules ()
- ((_ name)
- (enum-name->enum etype 'name))))
- (define-syntax constructor
- (syntax-rules ()
- ((_ . names)
- (list->enum-set etype
- (map (lambda (s)
- (enum-name->enum etype s))
- 'names)))))))))
- ;; [Deprecated] As define-enum, except that type-name is bound to
- ;; a macro that returns its symbol argument if the corresponding
- ;; enum is in the new type.
- (define-syntax define-enumeration
- (syntax-rules ()
- ((_ type-name (name-val ...) constructor)
- (begin
- (define etype (make-enum-type '(name-val ...)))
- (define-syntax type-name
- (syntax-rules ()
- ((_ name)
- (and (enum-name->enum etype 'name) 'name))))
- (define-syntax constructor
- (syntax-rules ()
- ((_ . names)
- (list->enum-set etype
- (map (lambda (s)
- (enum-name->enum etype s))
- 'names)))))))))
|