;;;; ;;;; struct.stk -- Defining STklos Structures ;;;; ;;;; Copyright © 2004-2011 Erick Gallesio - I3S-CNRS/ESSI ;;;; ;;;; ;;;; This program is free software; you can redistribute it and/or modify ;;;; it under the terms of the GNU General Public License as published by ;;;; the Free Software Foundation; either version 2 of the License, or ;;;; (at your option) any later version. ;;;; ;;;; This program is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;;; GNU General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with this program; if not, write to the Free Software ;;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ;;;; USA. ;;;; ;;;; Author: Erick Gallesio [eg@essi.fr] ;;;; Creation date: 17-May-2004 23:35 (eg) ;;;; Last file update: 27-May-2011 23:08 (eg) ;;;; #| ...) * * Defines a structure type whose name is ||. Once a structure type is * defined, the following symbols are bound: * ,(itemize * (item [|| denotes the structure type.]) * * (item [|make-| is a procedure which takes 0 to |n| parameters (if there * are |n| slots defined). Each parameter is assigned to the corresponding * field (in the definition order).]) * * (item [|?| is a predicate which returns |%t| when applied to an * instance of the || structure type and |%f| otherwise.]) * * (item [|-| (one for each defined ||) to read the * content of an instance of the || structure type. Writting the * content of a slot can be done using a generalized |set!|.]) * ) * * @lisp * (define-struct point x y) * (define p (make-point 1 2)) * (point? p) => #t * (point? 100) => #f * (point-x p) => 1 * (point-y p) => 2 * (set! (point-x p) 10) * (point-x p) => 10 * @end lisp * doc> |# (define-macro (define-struct name . slots) (define (compute-offset slot slots) (let ((sublist (memq slot slots))) (- (length slots) (length sublist)))) (let* ((pred (string->symbol (format "~a?" name))) (arg (gensym)) (val (gensym))) `(begin ;; Build the structure (define ,name (make-struct-type ',name #f ',slots)) ;; Build the constructor (define (,(string->symbol (format "make-~a" name)) . ,arg) (apply make-struct ,name ,arg)) ;; Build the predicate (define (,pred ,arg) (and (struct? ,arg) (struct-is-a? ,arg ,name))) ;; Build the slot readers ,@(map (lambda (x) (let ((fname (string->symbol (format "~a-~a" name x)))) `(define ,fname (lambda (,arg) (%fast-struct-ref ,arg ,name ',fname ,(compute-offset x slots)))))) slots) ;; Build the slot setters ,@(map (lambda (x) (let ((fname (string->symbol (format "~a-~a" name x)))) `(set! (setter ,fname) (lambda (,arg ,val) (%fast-struct-set! ,arg ,name ',fname ,(compute-offset x slots) ,val))))) slots) ;; Build the toplevel result (values (void) ',name))))