home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p2 / Thomas / record.scm < prev    next >
Encoding:
Text File  |  1994-07-26  |  6.3 KB  |  169 lines  |  [TEXT/gamI]

  1. ; -*-Scheme-*-
  2. ; $Id: record.scm,v 1.3 1992/09/23 15:30:30 birkholz Exp $
  3. ; $MIT-Header: /scheme/users/cph/src/runtime/RCS/record.scm,v 1.12 1991/11/26 06:50:09 cph Exp $
  4. ; Copyright (c) 1989-91 Massachusetts Institute of Technology
  5. ; This material was developed by the Scheme project at the Massachusetts
  6. ; Institute of Technology, Department of Electrical Engineering and
  7. ; Computer Science.  Permission to copy this software, to redistribute
  8. ; it, and to use it for any purpose is granted, subject to the following
  9. ; restrictions and understandings.
  10. ; 1. Any copy made of this software must include this copyright notice
  11. ; in full.
  12. ; 2. Users of this software agree to make their best efforts (a) to
  13. ; return to the MIT Scheme project any improvements or extensions that
  14. ; they make, so that these may be included in future releases; and (b)
  15. ; to inform MIT of noteworthy uses of this software.
  16. ; 3. All materials developed as a consequence of the use of this
  17. ; software shall duly acknowledge such use, in accordance with the usual
  18. ; standards of acknowledging credit in academic research.
  19. ; 4. MIT has made no warrantee or representation that the operation of
  20. ; this software will be error-free, and MIT is under no obligation to
  21. ; provide any services, by way of maintenance, update, or otherwise.
  22. ; 5. In conjunction with products arising from the use of this material,
  23. ; there shall be no use of the name of the Massachusetts Institute of
  24. ; Technology nor of any adaptation thereof in any advertising,
  25. ; promotional, or sales literature without prior written consent from
  26. ; MIT in each case.
  27.  
  28. ; This file requires the following non-IEEE primitives:
  29.  
  30. ; error:wrong-type-argument and error:bad-range-argument each signal Scheme
  31. ; conditions indicating an argument of the wrong type or invalid value
  32. ; (respectively).
  33.  
  34. ;;;; Records
  35.  
  36. ;;; adapted from JAR's implementation
  37. ;;; conforms to R4RS proposal
  38.  
  39. (define record-type-marker
  40.   (string->symbol "#[(runtime record)record-type-marker]"))
  41.  
  42. (define (make-record-type type-name field-names)
  43.   (vector record-type-marker type-name (map (lambda (x) x) field-names)))
  44.  
  45. (define (record-type? object)
  46.   (and (vector? object)
  47.        (= (vector-length object) 3)
  48.        (eq? (vector-ref object 0) record-type-marker)))
  49.  
  50. (define (record-type-name record-type)
  51.   (if (not (record-type? record-type))
  52.       (error:wrong-type-argument record-type "record type" 'RECORD-TYPE-NAME))
  53.   (vector-ref record-type 1))
  54.  
  55. (define (record-type-field-names record-type)
  56.   (if (not (record-type? record-type))
  57.       (error:wrong-type-argument record-type "record type"
  58.                  'RECORD-TYPE-FIELD-NAMES))
  59.   (map (lambda (x) x) (vector-ref record-type 2)))
  60.  
  61. (define (record-type-record-length record-type)
  62.   (+ (length (vector-ref record-type 2)) 1))
  63.  
  64. (define (record-type-field-index record-type field-name procedure-name)
  65.   (let loop ((field-names (vector-ref record-type 2)) (index 1))
  66.     (if (null? field-names)
  67.     (error:bad-range-argument field-name procedure-name))
  68.     (if (eq? field-name (car field-names))
  69.     index
  70.     (loop (cdr field-names) (+ index 1)))))
  71.  
  72. (define (record-type-error record record-type procedure)
  73.   (error:wrong-type-argument
  74.    record
  75.    (string-append "record of type "
  76.           (let ((type-name (vector-ref record-type 1)))
  77.             (cond ((string? type-name) type-name)
  78.               ((symbol? type-name) type-name)
  79.               (else "<<unknown data type for name>>"))))
  80.    procedure))
  81.  
  82. (define (record-constructor record-type . field-names)
  83.   (if (not (record-type? record-type))
  84.       (error:wrong-type-argument record-type "record type"
  85.                  'RECORD-CONSTRUCTOR))
  86.   (let ((field-names
  87.      (if (null? field-names)
  88.          (vector-ref record-type 2)
  89.          (car field-names))))
  90.     (let ((record-length (record-type-record-length record-type))
  91.       (number-of-inits (length field-names))
  92.       (indexes
  93.        (map (lambda (field-name)
  94.           (record-type-field-index record-type
  95.                        field-name
  96.                        'RECORD-CONSTRUCTOR))
  97.         field-names)))
  98.       (lambda field-values
  99.     (if (not (= (length field-values) number-of-inits))
  100.         (error "wrong number of arguments to record constructor"
  101.            field-values record-type field-names))
  102.     (let ((record (make-vector record-length)))
  103.       (vector-set! record 0 record-type)
  104.       (for-each (lambda (index value) (vector-set! record index value))
  105.             indexes
  106.             field-values)
  107.       record)))))
  108.  
  109. (define (record? object)
  110.   (and (vector? object)
  111.        (> (vector-length object) 0)
  112.        (record-type? (vector-ref object 0))))
  113.  
  114. (define (record-type-descriptor record)
  115.   (if (not (record? record))
  116.       (error:wrong-type-argument record "record" 'RECORD-TYPE-DESCRIPTOR))
  117.   (vector-ref record 0))
  118.  
  119. (define (record-copy record)
  120.     (list->vector (vector->list record)))
  121.  
  122. (define (record-predicate record-type)
  123.   (if (not (record-type? record-type))
  124.       (error:wrong-type-argument record-type "record type" 'RECORD-PREDICATE))
  125.   (let ((record-length (record-type-record-length record-type)))
  126.     (lambda (object)
  127.       (and (vector? object)
  128.        (= (vector-length object) record-length)
  129.        (eq? (vector-ref object 0) record-type)))))
  130.  
  131. (define (record-accessor record-type field-name)
  132.   (if (not (record-type? record-type))
  133.       (error:wrong-type-argument record-type "record type" 'RECORD-ACCESSOR))
  134.   (let ((record-length (record-type-record-length record-type))
  135.     (procedure-name `(RECORD-ACCESSOR ,record-type ',field-name))
  136.     (index
  137.      (record-type-field-index record-type field-name 'RECORD-ACCESSOR)))
  138.     (lambda (record)
  139.       (if (not (and (vector? record)
  140.             (= (vector-length record) record-length)
  141.             (eq? (vector-ref record 0) record-type)))
  142.       (record-type-error record record-type procedure-name))
  143.       (vector-ref record index))))
  144.  
  145. (define (record-modifier record-type field-name)
  146.   (if (not (record-type? record-type))
  147.       (error:wrong-type-argument record-type "record type" 'RECORD-UPDATER))
  148.   (let ((record-length (record-type-record-length record-type))
  149.     (procedure-name `(RECORD-UPDATER ,record-type ',field-name))
  150.     (index
  151.      (record-type-field-index record-type field-name 'RECORD-UPDATER)))
  152.     (lambda (record field-value)
  153.       (if (not (and (vector? record)
  154.             (= (vector-length record) record-length)
  155.             (eq? (vector-ref record 0) record-type)))
  156.       (record-type-error record record-type procedure-name))
  157.       (vector-set! record index field-value))))
  158.  
  159. (define record-updater
  160.   record-modifier)
  161.