[plt-scheme] Dot-notation for structure field access
jos koot
jos.koot at telefonica.net
Thu Mar 15 09:53:38 EDT 2007
Skipped content of type multipart/alternative-------------- next part --------------
#| Module dot: for dotted notation of struct-fields for both references and assignments.
By Jacob J. A. Koot with thanks to Jens Axel Søgaard.
Syntax: (define-struct-type (def name constr pred [super-type-expr]) (field ...) [inspector-expr]) --> void
Syntax: (define-struct-type def name constr pred (field ...) [inspector-expr]) --> void
def, name, constr and pred must be distinct identifiers.
The super-type-expr is evaluated and must yield #f or a struct-type-decriptor.
The inspector-expr is evaluated and must yield #f or a struct inspector.
All fields must be distinct identifiers.
The following definitions are made (at top level or as internal-defs.
def : syntax: (def var (expr ...)) --> void
var must be an identifier
The variable is defined (either at top level or as an internal-def)
such as to contain an instance of the struct-type with the values of the exprs for its fields.
The number of exprs must correspond to the number of fields.
In addition syntaxes var.field are defined such that:
varref var.field returns the current contents of the field.
(set! var.field value) stores the value in the field.
(var.field arg ...) assumes the field to contain a procedure and applies the procedure to the args.
name : struct type descriptor that can be used as a super type for other struct types.
constr : procedure (constr expr ...) --> instance of the struct type.
pred : procedure (pred object) --> #t if the object is an instance of the struct type, else #f
Syntax: (let-struct-type (binding ...) internal-def ... body-expr ...)
Where binding ::= ((def name constr pred [super-type]) (field ...) [inspector-expr]) or
( def name constr pred (field ...) [inspector-expr])
Synatx let-struct-type is related to syntax define-struct-type as let to define.
Syntax: (let-struct-var ((var def (expr ...)) ...) internal-def ... body ...) ==>
(let () (def var (expr ...)) ... internal-def ... body ...)
|#
(module dot mzscheme
(require-for-syntax (only (lib "etc.ss") build-list build-vector identity))
(require (only (lib "etc.ss") build-list build-vector identity))
(define-for-syntax (make-dotted-id stx var fld)
(datum->syntax-object stx (string->symbol (string-append (symbol->string (syntax-e var)) "." (symbol->string (syntax-e fld))))))
(define-syntax (define-struct-type stx)
(syntax-case stx ()
((define-struct-type def name constr pred (field ...) )
#'(define-struct-type (def name constr pred #f ) (field ...) #f ))
((define-struct-type def name constr pred (field ...) inspector)
#'(define-struct-type (def name constr pred #f ) (field ...) inspector))
((define-struct-type (def name constr pred ) (field ...) )
#'(define-struct-type (def name constr pred #f ) (field ...) #f ))
((define-struct-type (def name constr pred super) (field ...) )
#'(define-struct-type (def name constr pred super) (field ...) #f ))
((define-struct-type (def name constr pred ) (field ...) inspector)
#'(define-struct-type (def name constr pred #f ) (field ...) inspector))
((define-struct-type (def name constr pred super) (field ...) inspector)
(let ((nr-of-fields (length (syntax->list #'(field ...)))))
#`(begin
(define-values (name constr pred accessor mutator accessors mutators)
(let-values
(((name constr pred accessor mutator)
(make-struct-type 'name super #,nr-of-fields 0 #f () inspector #f () #f)))
(define accessors (build-vector #,nr-of-fields (lambda (i) (make-struct-field-accessor accessor i))))
(define mutators (build-vector #,nr-of-fields (lambda (i) (make-struct-field-mutator mutator i))))
(values name constr pred accessor mutator accessors mutators)))
(define-syntax def
(syntax-rules ()
((def var (expr (... ...)))
(begin (define var (constr expr (... ...)))
(define-struct-trafos var constr (field ...) accessors mutators))))))))))
(define-syntax (define-struct-trafos stx)
(syntax-case stx ()
((define-struct-trafos var constr (field ...) accessors mutators)
(let*
((fields (syntax->list #'(field ...)))
(nr-of-fields (length fields))
(indices (build-list nr-of-fields identity)))
#`(begin
#,@(map (lambda (field index) #`(define-struct-trafo var #,field #,index accessors mutators))
fields indices))))))
(define-syntax (define-struct-trafo stx)
(syntax-case stx ()
((define-struct-trafo var field index accessors mutators)
(with-syntax ((dotted-id (syntax-local-introduce (make-dotted-id #'stx #'var #'field))))
#`(define-syntax dotted-id
(make-set!-transformer
(lambda (tstx)
(syntax-case tstx (set!)
((set! id v) #'((vector-ref mutators index) var v))
((id x (... ...)) #'(((vector-ref accessors index) var) x (... ...)))
(id #'((vector-ref accessors index) var))))))))))
(define-syntax let-struct-type
(syntax-rules ()
((let-struct-type (binding ...) . body)
(let () (define-struct-type . binding) ... . body))))
(define-syntax let-struct-var
(syntax-rules ()
((let-struct-var ((var def (x ...)) ...) . body)
(let () (def var (x ...)) ... . body))))
(provide define-struct-type let-struct-type let-struct-var)
; the following syntaxes must be exported, but are not ment to be called explicitly by the importing program
(provide define-struct-trafos define-struct-trafo))
(require dot)
;;; tests
; Welcome to DrScheme, version 369.8-svn9mar2007 [3m].
; Language: Textual (MzScheme, includes R5RS) custom (no debugging, case insensitive)
(define-struct-type (def type constr pred) (x y z) (make-inspector)) ;--> void
(list type constr pred) ; --> (#<struct-type:type> #<primitive:make-type> #<primitive:type?>)
(def var (1 2 add1)) ;--> void
(set! var.x 10) ;--> void
(list var var.x var.y (var.z 20)) ; --> (#(struct:type 10 2 #<primitive:add1>) 10 2 21)
(let-struct-type (((d n c p) (x y z) (make-inspector)))
(let-struct-var ((v d (1 2 add1)))
(set! v.x 10)
(printf "~s ~s ~s ~s~n" v v.x v.y (v.z 20)))) ;--> #(struct:n 10 2 #<primitive:add1>) 10 2 21
(define-struct-type (dd tt cc pp (car (list type))) ()) ;--> void
(dd vv ('a 'b 'c)) ;--> void
(list vv (pred vv) (pp vv)) ;--> (#(struct:tt a b c) #t #t)
More information about the plt-scheme
mailing list