; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*- ; Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees. See file COPYING. ; Macros for defining data types. ; An ugly and unsafe macro for defining VM data structures. ; ; (DEFINE-PRIMITIVE-DATA-TYPE ; *) ; ::= () | ( ) ; ; (define-primitive-data-type pair N #f cons (car set-car!) (cdr)) ; => ; (begin ; (define (cons a b) (d-vector N ...)) ; (define pair? (stob-predicate ...)) ; (define pair-size 3) ; (define (car x) (d-vector-ref x 0)) ; (define (set-car! x val) (d-vector-set! x 0 val)) ; (define (cdr x) (d-vector-ref x 1)) (define-syntax define-primitive-data-type (lambda (exp rename compare) (destructure (((d-p-d-t name type immutable? make . body) exp)) (define (concatenate-symbol . syms) (string->symbol (apply string-append (map symbol->string syms)))) (let* ((pred (concatenate-symbol name '?)) (size (concatenate-symbol name '- 'size)) (shorten (lambda (l1 l2) (map (lambda (x1 x2) x2 x1) l1 l2))) (vars (shorten `(a b c d e f g h i j) body))) `(begin ,@(if make `((define ,make (let ((type (enum stob ,type))) (lambda (,@vars key) ,(if immutable? `(immutable-d-vector type key ,@vars) `(d-vector type key ,@vars)))))) '()) (define ,pred (stob-predicate (enum stob ,type))) (define ,size (+ ,(length body) stob-overhead)) ,@(do ((s body (cdr s)) (i 0 (+ i 1)) (d '() (let* ((slot (car s)) (d (cons `(define (,(car slot) x) (d-vector-ref x ,i)) d))) (if (null? (cdr slot)) d (cons `(define (,(cadr slot) x val) (d-vector-set! x ,i val)) d))))) ((null? s) (reverse d)))))))) ; This is a front for DEFINE-PRIMITIVE-DATA-TYPE that gets the names from ; STOB-DATA (which is defined in arch.scm). This ensures that the run-time ; code, the VM, and the linker agree on what these structures look like. ; ; SCHEME? is #T if the data structure is a Scheme structure, in which case ; the names defined by the form all have VM- prepended. (define-syntax define-shared-primitive-data-type (lambda (exp rename compare) (let* ((name (cadr exp)) (scheme? (if (null? (cddr exp)) #f (car (cddr exp)))) (immutable? (if (or (null? (cddr exp)) (null? (cdddr exp))) #f (cadr (cddr exp)))) (rest (if (or (null? (cddr exp)) (null? (cdddr exp))) '() (cddddr exp))) (extra-maker (if (null? rest) #f (car rest))) (extra-setters (if (or (null? rest) (null? (cdr rest))) '() (cadr rest))) (extra-fields (if (or (null? rest) (null? (cdr rest))) '() (cddr rest)))) (define (concatenate-symbol . syms) (string->symbol (apply string-append (map symbol->string syms)))) (let ((data (cddr (assq name stob-data))) (fixup (lambda (n) (if scheme? (concatenate-symbol 'vm- n) n)))) `(define-primitive-data-type ,(fixup name) ,name ,immutable? ,(fixup (if (car data) (car data) extra-maker)) . ,(map (lambda (p) (cons (fixup (car p)) (cond ((and (not (null? (cdr p))) (cadr p)) (list (fixup (cadr p)))) ((assq (car p) extra-setters) => cdr) (else '())))) (append (cdr data) extra-fields))))))) ; A d-vector macro version of the VECTOR procedure. ; This is only used in the expansion of DEFINE-PRIMITIVE-DATA-TYPE. (define-syntax d-vector (lambda (exp rename compare) (destructure (((d-v type key . args) exp)) `(let ((v (make-d-vector ,type ,(length args) key))) ,@(do ((a args (cdr a)) (i 0 (+ i 1)) (z '() (cons `(d-vector-init! v ,i ,(car a)) z))) ((null? a) (reverse z))) v)))) (define-syntax immutable-d-vector (syntax-rules () ((immutable-d-vector stuff ...) (let ((vec (d-vector stuff ...))) (make-immutable! vec) vec)))) ; A simpler macro for defining types of vectors. Again SCHEME? being #T ; causes VM- to be prepended to the defined names. (define-syntax define-vector-data-type (lambda (exp rename compare) (let ((name (cadr exp)) (scheme? (cddr exp))) (define (concatenate-symbol . syms) (string->symbol (apply string-append (map symbol->string syms)))) (let* ((type `(enum stob ,name)) (fix (if (not (null? scheme?)) 'vm- (string->symbol ""))) (pred (concatenate-symbol fix name '?)) (make (concatenate-symbol fix 'make- name)) (size (concatenate-symbol fix name '- 'size)) (length (concatenate-symbol fix name '- 'length)) (ref (concatenate-symbol fix name '- 'ref)) (set (concatenate-symbol fix name '- 'set!))) `(begin (define ,make (stob-maker ,type make-d-vector)) (define ,pred (stob-predicate ,type)) (define (,size len) (+ len stob-overhead)) (define ,length d-vector-length) (define ,ref d-vector-ref) (define ,set d-vector-set!))))))