From: Chris Hanson Date: Wed, 7 Feb 1990 23:25:58 +0000 (+0000) Subject: Implement new record proposal. X-Git-Tag: 20090517-FFI~11543 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=05cb1dca7d44a3f91f755833c9764f6af297f997;p=mit-scheme.git Implement new record proposal. --- diff --git a/v7/src/runtime/record.scm b/v7/src/runtime/record.scm index 572ff3f2a..6ac6ba550 100644 --- a/v7/src/runtime/record.scm +++ b/v7/src/runtime/record.scm @@ -1,8 +1,8 @@ #| -*-Scheme-*- -$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/record.scm,v 1.2 1989/02/28 18:36:10 cph Rel $ +$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/record.scm,v 1.3 1990/02/07 23:25:58 cph Exp $ -Copyright (c) 1989 Massachusetts Institute of Technology +Copyright (c) 1989, 1990 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and @@ -33,80 +33,144 @@ promotional, or sales literature without prior written consent from MIT in each case. |# ;;;; Records -;;; written by Jonathan Rees +;;; adapted from JAR's implementation +;;; conforms to R4RS proposal (declare (usual-integrations)) -(define (make-record-type type-id field-names) - (let ((size (+ (length field-names) 1))) - - (define (constructor names) - (let ((number-of-inits (length names)) - (indexes (map field-index names))) - (lambda field-values - (if (not (= (length field-values) number-of-inits)) - (error "wrong number of arguments to record constructor" - field-values type-id names)) - (let ((record (make-vector size))) - (vector-set! record 0 the-descriptor) - (for-each (lambda (index value) (vector-set! record index value)) - indexes - field-values) - record)))) - - (define (predicate obj) - (and (vector? obj) - (= (vector-length obj) size) - (eq? (vector-ref obj 0) the-descriptor))) +(define (make-record-type type-name field-names) + (let ((size (+ (length field-names) 1)) + (the-descriptor (make-vector 7))) + + (define (predicate object) + (and (vector? object) + (= (vector-length object) size) + (eq? (vector-ref object 0) the-descriptor))) (define (guarantee record) (if (not (predicate record)) - (error "invalid argument to record accessor" record type-id))) - - (define (accessor name) - (let ((index (field-index name))) - (lambda (record) - (guarantee record) - (vector-ref record index)))) - - (define (updater name) - (let ((index (field-index name))) - (lambda (record new-value) - (guarantee record) - (vector-set! record index new-value)))) - - (define (describe record) - (guarantee record) - (map (lambda (name) (list name (vector-ref record (field-index name)))) - field-names)) + (error "invalid argument to record accessor" record type-name))) (define (field-index name) (let loop ((names field-names) (index 1)) - (cond ((null? names) (error "bad field name" name)) - ((eq? name (car names)) index) - (else (loop (cdr names) (+ index 1)))))) - - (define (the-descriptor request) - (case request - ((CONSTRUCTOR) constructor) - ((PREDICATE) predicate) - ((ACCESSOR) accessor) - ((UPDATER) updater) - (else (error "invalid request to record type" type-id request)))) - + (if (null? names) + (error "bad field name" name)) + (if (eq? name (car names)) + index + (loop (cdr names) (+ index 1))))) + + (vector-set! the-descriptor 0 "record-type-descriptor") + (vector-set! the-descriptor 1 predicate) + (vector-set! the-descriptor 2 + (lambda (names) + (let ((number-of-inits (length names)) + (indexes (map field-index names))) + (lambda field-values + (if (not (= (length field-values) number-of-inits)) + (error "wrong number of arguments to record constructor" + field-values type-name names)) + (let ((record (make-vector size))) + (vector-set! record 0 the-descriptor) + (for-each (lambda (index value) + (vector-set! record index value)) + indexes + field-values) + record))))) + (vector-set! the-descriptor 3 + (lambda (name) + (let ((index (field-index name))) + (lambda (record) + (guarantee record) + (vector-ref record index))))) + (vector-set! the-descriptor 4 + (lambda (name) + (let ((index (field-index name))) + (lambda (record new-value) + (guarantee record) + (vector-set! record index new-value))))) + (vector-set! the-descriptor 5 type-name) + (vector-set! the-descriptor 6 (list-copy field-names)) (unparser/set-tagged-vector-method! the-descriptor - (unparser/standard-method type-id)) - (named-structure/set-tag-description! the-descriptor describe) + (unparser/standard-method type-name)) + (named-structure/set-tag-description! the-descriptor + (lambda (record) + (guarantee record) + (map (lambda (name) + (list name (vector-ref record (field-index name)))) + field-names))) the-descriptor)) - -(define (record-constructor record-type names) - ((record-type 'CONSTRUCTOR) names)) + +(define (record-constructor record-type #!optional field-names) + (guarantee-record-type record-type) + ((vector-ref record-type 2) + (if (default-object? field-names) + (record-type-field-names record-type) + field-names))) (define (record-predicate record-type) - (record-type 'PREDICATE)) + (guarantee-record-type record-type) + (vector-ref record-type 1)) (define (record-accessor record-type field-name) - ((record-type 'ACCESSOR) field-name)) + (guarantee-record-type record-type) + ((vector-ref record-type 3) field-name)) (define (record-updater record-type field-name) - ((record-type 'UPDATER) field-name)) \ No newline at end of file + (guarantee-record-type record-type) + ((vector-ref record-type 4) field-name)) + +(define (set-record-type-unparser-method! record-type method) + (guarantee-record-type record-type) + (unparser/set-tagged-vector-method! record-type method)) + +;;; Abstraction-Breaking Operations + +(define record-type? + (let ((record-type (make-record-type "foo" '()))) + (let ((size (vector-length record-type)) + (tag (vector-ref record-type 0))) + (unparser/set-tagged-vector-method! + tag + (unparser/standard-method 'RECORD-TYPE-DESCRIPTOR + (lambda (state record-type) + (unparse-object state (vector-ref record-type 5))))) + (named-structure/set-tag-description! tag + (lambda (record-type) + (guarantee-record-type record-type) + `((PREDICATE ,(vector-ref record-type 1)) + (CONSTRUCTOR-CONSTRUCTOR ,(vector-ref record-type 2)) + (ACCESSOR-CONSTRUCTOR ,(vector-ref record-type 3)) + (UPDATER-CONSTRUCTOR ,(vector-ref record-type 4)) + (TYPE-NAME ,(vector-ref record-type 5)) + (FIELD-NAMES ,(vector-ref record-type 6))))) + (lambda (object) + (and (vector? object) + (= (vector-length object) size) + (eq? (vector-ref object 0) tag)))))) + +(define (guarantee-record-type object) + (if (not (record-type? object)) + (error "not a record type descriptor" object)) + object) + +(define (record-type-name record-type) + (guarantee-record-type record-type) + (vector-ref record-type 5)) + +(define (record-type-field-names record-type) + (guarantee-record-type record-type) + (list-copy (vector-ref record-type 6))) + +(define (record? object) + (and (vector? object) + (not (zero? (vector-length object))) + (record-type? (vector-ref object 0)))) + +(define (guarantee-record object) + (if (not (record? object)) + (error "not a record" object)) + object) + +(define (record-type-descriptor record) + (guarantee-record record) + (vector-ref record 0)) \ No newline at end of file