pcs/newpcs/pdefstr.s

210 lines
8.6 KiB
ArmAsm
Raw Permalink Normal View History

2023-05-20 05:57:05 -04:00
; -*- Mode: Lisp -*- Filename: pdefstr.s
; Last Revision: 30-Aug-85 1900ct
;--------------------------------------------------------------------------;
; ;
; TI SCHEME -- PCS Compiler ;
; Copyright 1985 (c) Texas Instruments ;
; ;
; Amitabh Srivastava ;
; ;
; DEFINE-STRUCTURE and Related Routines ;
; ;
;--------------------------------------------------------------------------;
;;;
;;; - syntax is similar to DEFSTRUCT in Common Lisp
;;;
;;; Syntax : (DEFINE-STRUCTURE name slot1 slot2 ...)
;;;
;;; slots may be given default values by (slot1 init-val)
;;;
;;; e.g (DEFINE-STRUCTURE SHIP (X-VEL 0) Y-VEL)
;;;
;;; objects of this structure can be generated by using
;;; MAKE-SHIP -
;;;
;;; (MAKE-SHIP 'X-VEL 10)
;;;
;;; the predicate SHIP? can be used to check if an object is an
;;; instance of ship.
;;;
;;; (SHIP-X-VEL object) can be used to get the `x-vel' of the object,
;;; which is an instance of `ship'
;;;
;;; (SET! (SHIP-X-VEL object) 11) can be used to set the `x-vel' of the
;;; object.
;;;
;;; single-inheritance : structures can inherit from other objects by
;;; using the INCLUDE option (similar to Common Lisp DEFSTRUCT)
;;;
;;; e.g. (DEFINE-STRUCTURE (SHIP (INCLUDE FLOATING-OBJECT)) slot ...)
;;;
;;; Implementation Note
;;; The Common Lisp definition requires that the slot initialization
;;; expressions be re-evaluated each time a MAKE-name operation is
;;; performed. For consistency with the spirit of Scheme, these
;;; expressions should be evaluated in the lexical environment surrounding
;;; the DEFINE-STRUCTURE itself. Thus, DEFINE-STRUCTURE must expand into
;;; at least one LAMBDA that `freezes' the initialization expressions.
;;; This is why %DEFINE-STRUCTURE expands into a BEGIN with an embedded
;;; closure for MAKE-name. (This is important only if an initialization
;;; expression involves lexical references.)
;;; Global function used to generate predicates for all structures
(define %structure-predicate ; %STRUCTURE-PREDICATE
(lambda (object tag)
(and (vector? object)
(positive? (vector-length object))
(member tag (vector-ref object 0))
#!true)))
;;; %MAKE-STRUCTURE is used by all structures to create an instance
(define %make-structure ; %MAKE-STRUCTURE
(lambda (name constructor-name structure init-list)
(letrec ((slot-number
(lambda (slot slot-values)
(apply-if (assq slot slot-values)
cadr
(error (string-append
"Structure component unknown to "
(symbol->string constructor-name))
slot)))))
(let ((slots (getprop name '%SLOT-VALUES)))
(do ((structure structure)
(init-msg init-list (cddr init-msg)))
((null? init-msg) structure)
(vector-set! structure
(slot-number (car init-msg) slots)
(cadr init-msg)))))))
;;; %DEFINE-STRUCTURE defines a structure with specified attributes. This
;;; is the procedure that expands the macro DEFINE-STRUCTURE.
(define %define-structure ; %DEFINE-STRUCTURE
(lambda (e)
(letrec
((make-symbol ; MAKE-SYMBOL
(lambda args
(string->symbol (apply string-append args))))
(generate-slots-loop ; GENERATE-SLOTS-LOOP
(lambda (tail slots n)
(if (null? slots)
tail ;;; 2/14/86
(generate-slots-loop
(cons (if (atom? (car slots))
(cons (car slots) (cons n '()))
(cons (caar slots) (cons n (cadar slots))))
tail)
(cdr slots)
(1+ n)))))
(generate-slots ; GENERATE-SLOTS
(lambda (include-struct slots)
(if include-struct
(let ((include-slots (getprop include-struct '%SLOT-VALUES)))
(generate-slots-loop include-slots
slots
(1+ (length include-slots))))
(generate-slots-loop '() slots 1))))
(init-slots ; INIT-SLOTS
(lambda (slots)
(let loop ((tail '())
(slots slots))
(if (null? slots)
tail
(loop (if (member (cddar slots) '(() '()))
tail
(cons `(vector-set! %DS0001% ,(cadar slots)
,(cddar slots))
tail))
(cdr slots))))))
(access-macros-loop ; ACCESS-MACROS-LOOP
(lambda (name-string slots tail)
(if (null? slots)
(reverse! tail)
(access-macros-loop
name-string
(cdr slots)
(let ((name (make-symbol name-string "-"
(symbol->string (caar slots))))
(index (cadar slots)))
(cons `(define-integrable ,name
(lambda (obj) (vector-ref obj ,index)))
tail))))))
(gen-access-macros ; GEN-ACCESS-MACROS
(lambda (name-string slot-names-pos)
(access-macros-loop name-string slot-names-pos '())))
(gen-make-proc ; GEN-MAKE-PROC
(lambda (name constructor-name slot-names-pos)
`(define ,constructor-name
(lambda %DS0002%
(let ((%DS0001% (make-vector ,(1+ (length slot-names-pos))
'())))
(vector-set! %DS0001% 0 (getprop ',name '%TAG))
,@(init-slots slot-names-pos)
(if (null? %DS0002%)
%DS0001%
(%make-structure ',name ',constructor-name
%DS0001% %DS0002%)))))))
)
(begin
(pcs-chk-length>= e e 2)
(let* ((name-options (cadr e))
(name (let ((n (if (atom? name-options)
name-options
(car name-options))))
(pcs-chk-id e n)
n))
(name-string (symbol->string name))
(constructor-name (make-symbol "MAKE-" name-string))
(predicate-name (make-symbol name-string "?"))
(include-struct
(cond ((atom? name-options)
'())
((and (pair? (cdr name-options))
(pair? (cadr name-options))
(eq? (car (cadr name-options)) 'INCLUDE)
(pair? (cdr (cadr name-options))))
(let ((is (cadr (cadr name-options))))
(pcs-chk-id e is)
is))
(else
(syntax-error "Invalid option list" e))))
(slots (cddr e))
(slot-names-pos (generate-slots include-struct slots))
(tag (cons '#!STRUCTURE name))
(complex-tag (if include-struct
(cons tag (getprop include-struct '%TAG))
(list tag))))
`(begin
(putprop ',name ',complex-tag '%TAG)
(putprop ',name ',slot-names-pos '%SLOT-VALUES)
,@(gen-access-macros name-string slot-names-pos)
(define ,predicate-name
(lambda (obj)
(%structure-predicate obj ',tag)))
,(gen-make-proc name constructor-name slot-names-pos)
',name))))))