#lang scheme/base
(require (for-syntax scheme/base))
(provide (all-defined-out))
(define empty-bit-field 0)
(define empty-bit-field? zero?)
(define (bit-field . flags)
(if (null? flags) 0 (apply bitwise-ior flags)))
(define (make-bit-field . pairs)
(apply bit-field (map (lambda (pair)
(if (cdr pair) (car pair) 0))
pairs)))
(define-syntax (define-bit-flags stx)
(syntax-case stx ()
[(_ (x1 x2 ...))
(with-syntax ([(i1 i2 ...) (for/list ([i (in-range (length (syntax->list #'(x1 x2 ...))))])
(expt 2 i))])
#'(begin (define x1 i1)
(define x2 i2)
...))]))
(define (bit-flag-set? bf flag)
(not (zero? (bitwise-and bf flag))))
(define-struct attributed ([value #:mutable] attributes) #:transparent)
(define-syntax (object-table stx)
(syntax-case stx ()
[(_ [key . value-info] ...)
(with-syntax ([(name ...)
(map (lambda (stx)
(let ([x (syntax->datum stx)])
(if (string? x) x (symbol->string x))))
(syntax->list #'(key ...)))]
[(value ...)
(map (lambda (stx)
(syntax-case stx ()
[(value) #'value]
[(value (attributes ...))
#'(make-attributed value (bit-field attributes ...))]
[(getter setter (attributes ...))
#'(make-attributed (make-ref getter setter (lambda () 'false))
(bit-field DONT-DELETE? attributes ...))]))
(syntax->list #'(value-info ...)))])
#'(let ([table (make-hash)])
(for ([n (list name ...)]
[v (list value ...)])
(hash-set! table n v))
table))]))
(define-struct object ([call #:mutable] [construct #:mutable] proto class [properties #:mutable]) #:transparent)
(define-struct (array object) (vector) #:transparent)
(define-struct ref (get set! delete!))
(define (function? x)
(and (object? x)
(object-call x)
#t))
(define-bit-flags (READ-ONLY? DONT-ENUM? DONT-DELETE?))