home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume10 / comobj.lisp / part13 / co-parse.l
Encoding:
Text File  |  1987-08-02  |  55.5 KB  |  1,757 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;
  3. ; File:         co-parse.l
  4. ; RCS:          $Revision: 1.1 $
  5. ; SCCS:         %A% %G% %U%
  6. ; Description:  Commonobjects parser for the Commonobjects-Commonloops
  7. ;               interface.
  8. ; Author:       Roy D'Souza, HPL/DCC
  9. ; Created:      20-Nov-86
  10. ; Modified:     4-Mar-87 11:22:29 (James Kempf)
  11. ; Mode:         Lisp
  12. ; Package:      COMMON-OBJECTS-PARSER
  13. ; Status:       Distribution
  14. ;
  15. ; (c) Copyright 1987, HP Labs, all rights reserved.
  16. ;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18. ;
  19. ; Copyright (c) 1987 Hewlett-Packard Corporation. All rights reserved.
  20. ;
  21. ; Use and copying of this software and preparation of derivative works based
  22. ; upon this software are permitted.  Any distribution of this software or
  23. ; derivative works must comply with all applicable United States export
  24. ; control laws.
  25. ; This software is made available AS IS, and Hewlett-Packard Corporation makes
  26. ; no warranty about the software, its performance or its conformity to any
  27. ; specification.
  28. ;
  29. ; Suggestions, comments and requests for improvement may be mailed to
  30. ; aiws@hplabs.HP.COM
  31.  
  32. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  33. ; Preliminaries
  34. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  35.  
  36. (provide "co-parse")
  37.  
  38. ;;;Package COMMON-OBJECTS-PARSER contains the parser. For ease of
  39. ;;;  typing, CO-PARSER can be used.
  40.  
  41. ;;;These symbols from the COMMON-OBJECTS package are needed at compile
  42. ;;;  time. Create the package if not there. Note that I don't want
  43. ;;;  to export them, because a user of the COMMON-OBJECTS package
  44. ;;;  shouldn't know about them. I therefore use fully qualified
  45. ;;;  symbols in the code.
  46.  
  47. (in-package :common-objects :nicknames '(co) :use '(lisp pcl))
  48. (intern "ASSIGNEDP")
  49. (intern "METHOD-ALIST")
  50. (intern "SELF")
  51. (intern "INIT-KEYWORDS")
  52. (intern "LEGAL-PARENT-P")
  53. (in-package 'common-objects-parser :nicknames '(co-parser) :use '(lisp pcl))
  54.  
  55. ;;Export functions needed for parsing
  56.  
  57. (export
  58.   '(
  59.     co-parse-define-type-call
  60.     co-parse-method-macro-call
  61.     co-parse-call-to-method
  62.     co-process-var-options
  63.     co-parse-options
  64.     co-deftype-error
  65.     co-legal-type-or-method-name
  66.     $UNDEFINED-TYPE-NAME
  67.     $TYPE-INFO-SLOT
  68.     $TYPE-NAME-SLOT
  69.     $VARIABLE-NAMES-SLOT
  70.     $INITABLE-VARIABLES-SLOT
  71.     $SETTABLE-VARIABLES-SLOT
  72.     $GETTABLE-VARIABLES-SLOT
  73.     $PARENT-TYPES-SLOT
  74.     $PARENTS-INFO-SLOT
  75.     $A-LIST-METHOD-TABLE-SLOT
  76.     $TREAT-AS-VARIABLES-SLOT
  77.     $INIT-KEYWORDS-SLOT
  78.     $NO-INIT-KEYWORD-CHECK-SLOT
  79.     $METHODS-TO-NOT-DEFINE-SLOT
  80.     $METHODS-TO-INHERIT-SLOT
  81.     $LET-PSEUDO-INFO-SLOT
  82.     $INFO-NUMBER-OF-SLOTS
  83.  
  84.   )
  85. )
  86.  
  87. ;;Need the PCL and pcl-patches module
  88. (require "pcl")
  89. (require "pcl-patches")
  90.  
  91.  
  92. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  93. ; Constant Definition
  94. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  95.  
  96. ;;Type names are set to this when types are undefined.
  97.  
  98. (defconstant $UNDEFINED-TYPE-NAME '*now-an-undefined-type*)
  99.  
  100. ;;Offsets into the vector used to parse type definitions.
  101.  
  102. (defconstant $TYPE-INFO-SLOT 0)
  103.  
  104. (defconstant $TYPE-NAME-SLOT 1)
  105.  
  106. (defconstant $VARIABLE-NAMES-SLOT 2)
  107.  
  108. (defconstant $INITABLE-VARIABLES-SLOT 3)
  109.  
  110. (defconstant $SETTABLE-VARIABLES-SLOT 4)
  111.  
  112. (defconstant $GETTABLE-VARIABLES-SLOT 5)
  113.  
  114. (defconstant $PARENT-TYPES-SLOT 6)
  115.  
  116. (defconstant $PARENTS-INFO-SLOT 7)
  117.       
  118. (defconstant $A-LIST-METHOD-TABLE-SLOT 8)
  119.  
  120. (defconstant $TREAT-AS-VARIABLES-SLOT 9)
  121.  
  122. (defconstant $INIT-KEYWORDS-SLOT 10)
  123.  
  124. (defconstant $NO-INIT-KEYWORD-CHECK-SLOT 11)
  125.  
  126. (defconstant $METHODS-TO-NOT-DEFINE-SLOT 12)
  127.  
  128. (defconstant $METHODS-TO-INHERIT-SLOT 13)
  129.  
  130. (defconstant $LET-PSEUDO-INFO-SLOT 14)
  131.       
  132. (defconstant $EXPLICITLY-LISTED-METHODS-SLOT 15)
  133.  
  134. ;;List of all universal method names
  135.  
  136. (defconstant
  137.  $DEFINE-TYPE-UNIVERSAL-METHODS
  138.  '(:describe
  139.    :print
  140.    :initialize
  141.    :initialize-variables
  142.    :init
  143.    :eql
  144.    :equal
  145.    :equalp
  146.    :typep
  147.    :copy
  148.    :copy-state
  149.    :copy-instance)
  150. )
  151.  
  152. ;;Size of the vector used in type definition parsing.
  153.  
  154. (defconstant $INFO-NUMBER-OF-SLOTS 16)
  155.  
  156. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  157. ; General Macro Definitions
  158. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  159.  
  160. (defmacro get-parents-info (type-info)
  161.  
  162. ; Allow for more convenient access of parent information.
  163.  
  164.  `(aref ,type-info $parents-info-slot))
  165.  
  166. (defmacro set-parents-info (type-info new-value)
  167.  `(setf (aref ,type-info $parents-info-slot) ,new-value))
  168.  
  169. (defmacro co-deftype-error (format &rest arguments)
  170.  
  171.   `(error (concatenate 'simple-string
  172.                "DEFINE-TYPE: In type '~s', "
  173.                ,format)
  174.         ,@arguments))
  175.  
  176.  
  177. (defmacro define-method-error (format &rest arguments)
  178.  
  179.  `(error
  180.     (format nil
  181.             (concatenate 'simple-string "DEFINE-METHOD: " ,format)
  182.             ,@arguments)))
  183.  
  184. (defmacro return-keyword-from-variable (var)
  185.     `(intern ,var (find-package "KEYWORD"))
  186. )
  187.  
  188. ;;type-partially-defined?-Find out if a CommonLoops class is
  189. ;;  defined and return the class object if so. 
  190.  
  191. (defmacro type-partially-defined? (name)
  192.  
  193.  `(class-named ,name T))
  194.  
  195. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  196. ; General Function and Method Definitions
  197. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  198.  
  199. ;;type-name-Return the name of the type
  200.  
  201. (defun type-name (tinfo) 
  202.  
  203.    (if (%instancep tinfo)
  204.      (class-name tinfo)
  205.      (svref tinfo $TYPE-NAME-SLOT)
  206.    )
  207.  
  208. ) ;type-name
  209.  
  210. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  211. ; Top Level Type Definition
  212. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  213.  
  214.  
  215. (defun co-parse-define-type-call
  216.  (define-type-call type-name doc-string options-list)
  217.  
  218. ; Parse the various pieces of the call to DEFINE-TYPE.  Return multiple values
  219. ; of the form: (TYPE-NAME DOC-STRING OPTIONS-LIST) OPTIONS-LIST doesn't have to
  220. ; exist.  If it doesn't, NIL is returned for it value (assuming NIL is
  221. ; given as their initial value passed into the routine).  In either
  222. ; case it is disreguarded.  Example call, DEFINE-TYPE-CALL =
  223. ; (DEFINE-TYPE NOSE (:INHERIT-FROM PARENT)).
  224.  
  225.  (setf define-type-call (cdr define-type-call))
  226.  
  227. ; This should now be the list of arguments to the DEFINE-TYPE.
  228. ; Example define-type-call = (NOSE (:INHERIT-FROM PARENT)).
  229.  
  230.  (unless (proper-list define-type-call)
  231.  
  232.  ; THEN The call to DEFINE-TYPE is not a proper list.
  233.  
  234.    (error
  235.     (format nil
  236.             "DEFINE-TYPE: The call,~% (DEFINE-TYPE '~S'),~% is missing arguments or is not a proper list."
  237.             define-type-call)))
  238.  
  239. ; Get the name of the type
  240.  
  241.  (setf type-name (first define-type-call))
  242.  (setf define-type-call (cdr define-type-call))
  243.  
  244. ; see if there is a documentation string
  245.  
  246.  (when
  247.    (setq doc-string
  248.           (and (consp define-type-call)
  249.                (stringp (car (the cons define-type-call)))
  250.                (list (car (the cons define-type-call)))
  251.           ; list form for ,@ substitution
  252.           ))
  253.    (setf define-type-call (cdr define-type-call)))
  254.  
  255. ; Example, define-type-call = ((:INHERIT-FROM PARENT)).
  256. ; Now look for options.
  257.  
  258.  (when (consp define-type-call)
  259.  
  260.  ; THEN We have options.
  261.  
  262.    (setf options-list define-type-call))
  263.  
  264. ; Return the parsed fields as a list for MULTIPLE-VALUE-SETQ
  265.  
  266.  (values type-name doc-string options-list)
  267.  
  268. ) ;co-parse-define-type-call
  269.  
  270. ;;proper-list-Return T if X is a proper list, i.e., no dotted tail
  271.  
  272. (defun proper-list (x)
  273.  
  274. ; Return T on if x is a proper list (i.e., not (a b c . d)).  NIL is
  275. ; not considered a proper list.
  276.  
  277.  (and (consp x) (not (cdr (last x)))))
  278.  
  279. (defun co-process-var-options
  280.  (type-info options-list var-names var-assignments)
  281.  
  282. ; Returns multiple values.  These values are:
  283. ;    (VAR-NAMES VAR-ASSIGNMENTS OPTIONS-LIST)
  284. ; Go through OPTIONS-LIST and find all the :VAR options.  Take
  285. ; these and process them producing the list of variable names, the
  286. ; variable assignment code and the list of options without the :VAR
  287. ; options.
  288.  
  289.   (let
  290.    (
  291.      (variable nil)
  292.      (var-assignment nil)
  293.      (new-options-list nil)
  294.      (option-name nil)
  295.      (option-info nil)
  296.    )
  297. ;;;;    (Declare (ignore option-name))
  298.  
  299.    (dolist (option options-list 
  300.             (values var-names var-assignments new-options-list)
  301.            )
  302.  
  303.    (multiple-value-setq (option-name  option-info)
  304.             (option-ok? option type-info 'regular-option)
  305.    )
  306.  
  307.    ; Will only return to here if we didn't get an error.
  308.  
  309.    ; Check if spec is an instance variable spec
  310.  
  311.    (if (not (member 'variable-option (cdr option-info) :test #'eq))
  312.  
  313.     ;;THEN Add this non-:VAR option to the options list
  314.  
  315.     (setf new-options-list (nconc new-options-list (list option)))
  316.  
  317.  
  318.  
  319.    ; ELSE We have a instance variable specification.
  320.    ;      Now return the name of the variable and initialization
  321.    ;      code.
  322.  
  323.    
  324.     (progn
  325.       (multiple-value-setq (variable var-assignment)
  326.                    (parse-option
  327.                  type-info
  328.                  var-names
  329.                  option
  330.                  option-info
  331.                            )
  332.       )
  333.  
  334.  
  335.       (setf var-names (nconc var-names (list variable)))
  336.  
  337.       (when var-assignment
  338.  
  339.         ; THEN Add the assignment to the list of assignments.
  340.  
  341.         (setf var-assignments
  342.            (nconc var-assignments (list var-assignment))
  343.         )
  344.       ) ;when
  345.  
  346.     ) ;progn
  347.  
  348.   ) ;if
  349.  ); dolist
  350.  
  351.  ) ;let
  352.  
  353. ); end co-process-var-options
  354.  
  355. (defun co-parse-options (type-info var-names options)
  356.  
  357. ; It is legal for OPTIONS to be NIL.
  358. ; Example: OPTIONS = ((:REDEFINED-METHODS m1 m2 m3)
  359. ;                     :ALL-INITABLE)
  360.  
  361.  (let ((options-so-far nil)
  362.        (option-name nil)
  363.        (option-info nil))
  364.  
  365.    (dolist (option options)
  366.  
  367.    ; OPTION-INFO will be NIL if OPTION-NAME is not a legal
  368.    ; option, or a list of information that tells what
  369.    ; characteristics this option has.  Note that currently, if an
  370.    ; error occurs in OPTION-OK? we will NOT return to this
  371.    ; function.  The check for '(WHEN OPTION-INFO...' is for future
  372.    ; continuable errors. If 'ONCE' is on this list, it means the
  373.    ; option can only occur once.
  374.  
  375.            (multiple-value-setq (option-name  option-info)
  376.                           (option-ok? option type-info 'regular-option))
  377.            (when option-info
  378.  
  379.            ; THEN The OPTION is a real one.
  380.            ;      Now make sure it doesn't occur more then once.
  381.  
  382.              (if
  383.                (and (member option-name options-so-far :test #'eq)
  384.  
  385.                     (member 'once (cdr option-info) :test #'eq))
  386.  
  387.              ; THEN We have duplicate options.  Give an error.
  388.  
  389.                (co-deftype-error
  390.                 "duplicate option,~% '~s',~% specified."
  391.                 (type-name type-info)
  392.                 option)
  393.  
  394.              ; ELSE Everything is ok.
  395.  
  396.                (progn
  397.                  (setf options-so-far (cons option-name options-so-far))
  398.                  (parse-option type-info var-names option option-info)))))
  399.  ))
  400.  
  401. (defun parse-option (type-info var-names option option-info)
  402.  
  403. ; This routine calls the right function to parse OPTION.  This
  404. ; function is the first element of OPTION-INFO.  Example: OPTION =
  405. ; (:REDEFINED-METHODS M1 M2 M3) The option given is either a symbol
  406. ; or a list.  When a list, the rest of the arguments will be passed to
  407. ; the function (may be NIL).  If a symbol, NIL is passed as arguments.
  408. ; NOTE: Should make sure that the value returned by the option is
  409. ;       the value of this routine, since some code may want to use
  410. ;       the value returned (like the caller of the :VAR option).
  411.  
  412.  (apply (car option-info)
  413.         (list var-names (if (consp option) (cdr option) nil) type-info)))
  414.  
  415. (defun option-ok? (option type-info type-of-option)
  416.  
  417. ; Return the information about this option or NIL.  Return the name of
  418. ; the option followed by the information for the option as a pair.  If
  419. ; the option is not of the correct form give an error message.  Check
  420. ; to make sure the option exists.  Also check that the form of option
  421. ; is legal according to the information returned.  This includes
  422. ; whether the option is allowed as a symbol or in list form.  And
  423. ; whether it is allowed to not have any arguments when in the list
  424. ; form.  Also if a list, check if each element is a symbol, and not NIL.
  425. ; This is done if CHECK-ARGUMENTS was included in the option
  426. ; information.  If the KEYWORDS option is also included with
  427. ; CHECK-ARGUMENTS, each of the symbols given must also be in the
  428. ; keyword package.  If VARIABLES is included in the option information,
  429. ; SELF is also checked for each option element.  The
  430. ; option CAN-HAVE-LIST-ELEMENTS causes list element arguments to be
  431. ; ignored. If this option is not there and a list element is
  432. ; found, an error message is issued.  Type-info is used strictly for
  433. ; error messages.  Will return NIL for the error conditions.  Sample,
  434. ;
  435. ; OPTION = '(:REDEFINED-METHODS A B C)' or ':ALL-SETTABLE'
  436. ;
  437. ; TYPE-OF-OPTION is used to decide wheter we are dealing with an
  438. ; option or a suboption of :INHERIT-FROM.  NOTE: Currently, this
  439. ; function will never return if an error occurs but we prepare for
  440. ; future continuable errors.  
  441.  
  442.  (let*
  443.    ((option-info
  444.      (if (consp option)
  445.  
  446.      ; THEN Use the first element of the option as the option name.
  447.  
  448.        (return-option-info (car option) type-of-option)
  449.  
  450.      ; ELSE Use the option itself as the option name.
  451.  
  452.        (return-option-info option type-of-option)))
  453.  
  454.     (type-name (type-name type-info))
  455.     (check-as-variables (member 'variable option-info :test #'eq))
  456.     (can-have-list-elements
  457.      (member 'can-have-list-elements option-info :test #'eq))
  458.     (keyword-arguments (member 'keywords option-info :test #'eq)))
  459.  
  460.  
  461.    (unless option-info
  462.  
  463.    ; THEN We have an illegal option.
  464.  
  465.      (co-deftype-error
  466.       "no such option (or suboption) as:~% '~s'."
  467.       type-name
  468.       option))
  469.  
  470.  ; We have a real option.  Make sure it is of the right form.
  471.  
  472.    (if (consp option)
  473.  
  474.    ; THEN Check to make sure it can be a pair.
  475.  
  476.      (if
  477.        (not (member 'list (cdr option-info) :test #'eq))
  478.  
  479.      ; THEN Wrong form for option.
  480.  
  481.        (co-deftype-error
  482.         "option,~% '~S',~% must occur as a symbol."
  483.         type-name
  484.         option)
  485.  
  486.      ; ELSE Ok so far.  Make sure the list form is a proper list.
  487.      ; Now check if the option has no arguments and if
  488.      ; if does make sure it can.
  489.  
  490.        (progn
  491.          (unless (proper-list option)
  492.          ; THEN Not a proper list.
  493.            (co-deftype-error
  494.             "the option,~% '~S',~% must be a proper list."
  495.             type-name
  496.             option))
  497.          (if
  498.            (and (not (cdr option))
  499.                 (not (member 'no-arguments (cdr option-info) :test #'eq)))
  500.          
  501.          ; THEN Arguments must be specified to option.
  502.          
  503.            (co-deftype-error
  504.             "option,~% '~S',~% requires arguments."
  505.             type-name
  506.             option)
  507.  
  508.          ; ELSE Check each element of the list, if necessary, to
  509.          ; make sure it is a symbol, not NIL. Also check for 
  510.          ; SELF if VARIABES is in the
  511.          ; option info.
  512.          ; Return the information.
  513.  
  514.            (progn
  515.              (when (member 'check-arguments (cdr option-info) :test #'eq)
  516.  
  517.              ; THEN Check the arguments.
  518.  
  519.                (dolist (option-arg (cdr option))
  520.                        (if (consp option-arg)
  521.                          (unless can-have-list-elements
  522.  
  523.                          ; THEN List arguments are not allowed.
  524.  
  525.                            (co-deftype-error
  526.                             "illegal argument '~S' found in option,~% '~S'."
  527.                             type-name
  528.                             option-arg
  529.                             option))
  530.  
  531.                        ; ELSE Check if a correct symbol.
  532.  
  533.                          (if
  534.                            (or
  535.                              (not (co-legal-type-or-method-name option-arg))
  536.                              (and check-as-variables
  537.                                   (not
  538.                                     (legal-instance-variable))))
  539.  
  540.                          ; THEN Illegal argument in option.
  541.  
  542.                            (co-deftype-error
  543.                             "illegal argument '~S' found in option,~% '~S'."
  544.                             type-name
  545.                             option-arg
  546.                             option)
  547.  
  548.                          ; ELSE Check if the option-arg must be a keyword.
  549.  
  550.                            (when
  551.                              (and keyword-arguments
  552.                                   (not (keywordp option-arg)))
  553.  
  554.                            ; THEN We have a DEFINE-TYPE in which the
  555.                            ;      arguments must all be symbols in the
  556.                            ;      keyword package.
  557.                              (co-deftype-error
  558.                               "'~S' of the option,~%'~S'~%is illegal.  Must be a symbol from the keyword package."
  559.                               type-name
  560.                               option-arg
  561.                               option))))))
  562.              (values (car option) option-info)))))
  563.  
  564.    ; ELSE We have the symbol form of the option.
  565.  
  566.      (if (member 'symbol (cdr option-info) :test #'eq)
  567.  
  568.      ; THEN Return the information.
  569.  
  570.        (values option option-info)
  571.  
  572.      ; ELSE Wrong form for option.
  573.  
  574.        (co-deftype-error
  575.         "option,~% '~S',~% must occur in list form."
  576.         type-name
  577.         option)))))
  578.  
  579.  
  580. (defun co-legal-type-or-method-name (type-or-method-name)
  581.  
  582. ; Return T only if the name given is a non-nil symbol.
  583.  
  584.  (and (symbolp type-or-method-name) type-or-method-name))
  585.  
  586. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  587. ; Detailed Option Parsing
  588. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  589.  
  590. (defun return-option-info (option-name option-type)
  591.  
  592. ; Whenever a new option is added, this function must be updated.
  593. ; Should return NIL, if garbage option-names are given.  The option
  594. ; information returned has the form:
  595. ;     (FUNCTION-NAME . INFORMATION).
  596. ; FUNCTION-NAME is the name of the function to call that parses the
  597. ; given option.  INFORMATION is a list of information to use in
  598. ; syntaxing the option.  This list includes:
  599. ;    SYMBOL          - option can occur in symbol form.
  600. ;    LIST            - option can occur in list form.
  601. ;    CHECK-ARGUMENTS - When an option is in list form, this specifies that
  602. ;                      each element of the option list is to be checked to 
  603. ;                      be a symbol which is not NIL.
  604. ;    KEYWORDS        - An addition to the CHECK-ARGUMENTS option, this says
  605. ;                      that each element must be a symbol from the keyword 
  606. ;                      package.  Must occur with the CHECK-ARGUMENTS option.
  607. ;    NO-ARGUMENTS    - This specifies that a list form of the option can 
  608. ;                      occur without any arguments (i.e.,
  609. ;                      (:METHODS).
  610. ;    VARIABLE        - The items in this options list are instance variables.
  611. ;                      Check that they are not SELF or MYSELF.Make sure 
  612. ;               they are not symbols from the
  613. ;                      keyword package.
  614. ;    CAN-HAVE-LIST-ELEMENTS - This option says that having list elements is 
  615. ;                             legal. These elements are simply ignored.
  616. ;    ONCE            - This option can only occur once.
  617. ;    VARIABLE-OPTION - Currently used in the :VAR option.  Tells whether
  618. ;                      an option is a variable option (:VAR) without
  619. ;                      using the name of the option.  This allows easy
  620. ;                      renaming of the :VAR option.
  621. ;    VALUE-RETURNED-SUBOPTION - States that this suboption returns a
  622. ;                               value that is needed.  A test is made
  623. ;                               to save the return value when a suboption
  624. ;                               has this characteristic.
  625. ;    
  626. ; Note that this list is used for parsing suboptions as well as
  627. ; options.  The handling of suboptions and options in the same way is
  628. ; done for flexibility and understandability even though some of the
  629. ; options may not currently apply to both options and suboptions.
  630. ;
  631.  
  632.  (case option-type
  633.  
  634.    (var-suboption (return-var-suboption-info option-name))
  635.  
  636.    (inherit-from-suboption
  637.     (return-inherit-from-suboption-info option-name))
  638.  
  639.    (regular-option (return-regular-option-info option-name))))
  640.  
  641. (defun return-var-suboption-info (option-name)
  642.  
  643. ; Return information as stated in comments of RETURN-OPTION-INFO
  644. ; about the suboptions of the :VAR option.
  645.  
  646.  (case option-name
  647.  
  648.    (:init '(parse-var-init-suboption list once value-returned-suboption))
  649.  
  650.    (:type '(parse-var-type-suboption list once))
  651.  
  652.    (:initable '(parse-var-initable-suboption symbol once))
  653.  
  654.    (:settable '(parse-var-settable-suboption symbol once))
  655.  
  656.    (:gettable '(parse-var-gettable-suboption symbol once))
  657.  
  658.    (otherwise nil)
  659.  ))
  660.  
  661. (defun parse-var-initable-suboption (args initable-variable type-info)
  662.   (declare (ignore args))
  663.  
  664. ; ARGS will always be NIL.
  665.  
  666.  (setf (svref type-info $initable-variables-slot)
  667.         (add-to-set
  668.          (svref type-info $initable-variables-slot)
  669.          initable-variable)))
  670.  
  671. (defun parse-var-gettable-suboption (args gettable-variable type-info)
  672.   (declare (ignore args))
  673.  
  674. ; ARGS will always be NIL.
  675.  
  676.  (setf (svref type-info $gettable-variables-slot)
  677.         (add-to-set
  678.          (svref type-info $gettable-variables-slot)
  679.          gettable-variable)))
  680.  
  681. (defun parse-var-settable-suboption (args settable-variable type-info)
  682.   (declare (ignore args))
  683.  
  684. ; ARGS will always be NIL.
  685.  
  686.  (setf (svref type-info $initable-variables-slot)
  687.         (add-to-set
  688.          (svref type-info $initable-variables-slot)
  689.          settable-variable))
  690.  
  691.  (setf (svref type-info $gettable-variables-slot)
  692.         (add-to-set
  693.          (svref type-info $gettable-variables-slot)
  694.          settable-variable))
  695.  
  696.  (setf (svref type-info $settable-variables-slot)
  697.         (add-to-set
  698.          (svref type-info $settable-variables-slot)
  699.          settable-variable)))
  700.  
  701. (defun add-to-set (set new-elements)
  702.  
  703. ; Add the elements in NEW-ELEMENTS to SET if they are not already
  704. ; there.  NEW-ELEMENTS can be a list of id's or an id.  It is assumed
  705. ; that the order of the elements within the set is NOT important.  If
  706. ; NEW-ELEMENTS is NIL, simply return set.
  707.  
  708.  (cond ((null new-elements) set)
  709.        ((symbolp new-elements)
  710.  
  711.        ; THEN Add the element to the set, if necessary.
  712.  
  713.         (adjoin new-elements set :test #'eq))
  714.  
  715.        (t 
  716.  
  717.        ; ELSE Add each element of the list of elements.
  718.  
  719.           (let ((new-set set))
  720.             (dolist (element new-elements)
  721.                     (setf new-set (adjoin element new-set :test #'eq)))
  722.             new-set))))
  723.  
  724.  
  725. (defun parse-var-type-suboption (args variable type-info)
  726.  
  727. ; Example, ARGS = (FIXNUM).  A declaration like (:TYPE FIXNUM) =>
  728. ; (DECLARE (TYPE FIXNUM A)).
  729.  
  730.  (unless (and (consp args) (= (length args) 1))  ;rds 3/8 eq->=
  731.  
  732.  ; THEN We have something like (:TYPE . 2).
  733.  
  734.    (co-deftype-error
  735.     "'~S'~% is an illegal form of :TYPE suboption."
  736.     (type-name type-info)
  737.     (cons :type args)))
  738.  
  739. ; Add this declaration to the list of declarations.
  740. ; Note that more will be added to this slot when :VARIABLES suboptions are
  741. ; parsed, and at the end parsing the type. :VARIABLES is, however,
  742. ; currently unsupported.
  743.  
  744.  (setf (svref type-info $let-pseudo-info-slot)
  745.         (nconc (svref type-info $let-pseudo-info-slot)
  746.                (list `(declare (type ,(car args) ,variable))))))
  747.  
  748.  
  749. (defun parse-var-init-suboption (args variable type-info)
  750.  
  751. ; Return the variable initialization form. For example, if VARIABLE = 
  752. ; REAL-PART and ARGS = (0.0), would return:
  753. ;      (unless
  754. ;             (assignedp real-part)
  755. ;             (setf real-part 0.0))         
  756.  
  757.  (unless (and (consp args) (= (length args) 1)) ;rds 3/8 eq->= 
  758.  
  759.  ; THEN We have something like (:INIT 1 2).
  760.  
  761.    (co-deftype-error
  762.     "illegal initialization form,~%'~S',~%given for instance variable '~S'."
  763.     (type-name type-info)
  764.     (cons :init args)
  765.     variable))
  766.  
  767.  (let ((default-value (first args)))
  768.    `(unless 
  769.        (co::assignedp ,variable)
  770.  
  771.     ; THEN
  772.  
  773.       (setf ,variable ,default-value))))
  774.  
  775. (defun return-inherit-from-suboption-info (option-name)
  776.  
  777. ; Return information as stated in comments of RETURN-OPTION-INFO
  778. ; about the suboptions of the :INHERIT-FROM option.
  779.  
  780.  (case option-name
  781.  
  782.    (:init-keywords
  783.     '(parse-init-keywords-suboption
  784.       symbol
  785.       list
  786.       once
  787.       check-arguments
  788.       keywords))
  789.  
  790.    ;;:VARIABLES suboption not allowed in COOL. This is due to
  791.    ;;  lack of code walker hooks.
  792.  
  793. #|
  794.    (:variables
  795.     '(parse-variables-suboption
  796.       list
  797.       once
  798.       no-arguments
  799.       check-arguments
  800.       variable
  801.       can-have-list-elements))
  802. |#
  803.  
  804.    (:methods
  805.     '(parse-methods-suboption list once check-arguments no-arguments))
  806.  
  807.    (otherwise nil)))
  808.  
  809. (defun return-regular-option-info (option-name)
  810.  
  811. ; Return information as stated in comments of RETURN-OPTION-INFO
  812. ; about the options of DEFINE-TYPE.
  813.  
  814.  (case option-name
  815.  
  816.  
  817.    ;;:FAST-METHODS not supported in COOL. Implementation dependent.
  818.  
  819. #|
  820.    (:fast-methods
  821.     '(parse-fast-methods-option list once check-arguments no-arguments))
  822. |#
  823.  
  824.    ;;In line methods are not supported in COOL. Implementation dependent.
  825.  
  826. #|
  827.    (:inline-methods
  828.     '(parse-inline-methods-option list once check-arguments no-arguments))
  829.  
  830.    (:notinline-methods
  831.     '(parse-notinline-methods-option
  832.       list
  833.       once
  834.       check-arguments
  835.       no-arguments))
  836.  
  837. |#
  838.  
  839.    (:init-keywords
  840.     '(parse-init-keywords-option
  841.       list
  842.       once
  843.       check-arguments
  844.       no-arguments
  845.       keywords))
  846.  
  847.    (:no-init-keyword-check
  848.     '(parse-no-init-keyword-check-option symbol once))
  849.  
  850.    (:inherit-from '(parse-inherit-from-option list))
  851.  
  852.    (:var '(parse-var-option list variable-option))
  853.  
  854.    (:redefined-methods
  855.     '(parse-redefined-methods-option
  856.       list
  857.       once
  858.       check-arguments
  859.       no-arguments))
  860.  
  861.    (:all-settable '(parse-all-settable-option symbol once))
  862.  
  863.    (:all-gettable '(parse-all-gettable-option symbol once))
  864.  
  865.    (:all-initable '(parse-all-initable-option symbol once))
  866.  
  867.    (otherwise nil)))
  868.  
  869. (defun parse-init-keywords-suboption (type-info parent-type-info args)
  870.  
  871. ; If ARGS is NIL, we have the symbol form.  If ARGS is a list, we have
  872. ; the list form.  Examples: ARGS = NIL
  873. ;                           ARGS = (:EXCEPT j k l), (:EXCEPT)
  874. ; (:INIT-KEYWORDS :EXCEPT) is treated as all keywords.  If this
  875. ; function returns, then everything went ok as far as errors.  If ARGS
  876. ; is a list, we know it is proper, and each init keyword is a symbol and
  877. ; not NIL.  This function may change the $INIT-KEYWORDS-SLOT of
  878. ; type-info.
  879.  
  880.  (let*
  881.    ((parent-init-keywords
  882.      (co::init-keywords parent-type-info))
  883.     (keywords-to-add parent-init-keywords))
  884.  
  885.    (when args
  886.  
  887.    ; THEN We have the except form.
  888.    ;      Check and make sure the :EXCEPT is found.
  889.  
  890.      (if
  891.        (not (eq (car args) ':except))
  892.  
  893.      ; THEN We have an error.
  894.  
  895.        (co-deftype-error
  896.         "~%'~S'~% was found following the :INIT-KEYWORDS suboption, expected to see 'EXCEPT'."
  897.         (type-name type-info)
  898.         (car args))
  899.  
  900.      ; ELSE ok so far.
  901.  
  902.        (progn (setq args (cdr args))
  903.               (when (consp args)
  904.  
  905.               ; THEN There is something following the :EXCEPT.
  906.  
  907.                 (dolist (keyword args)
  908.  
  909.                 ; See if the keyword is in the list of REAL 
  910.                 ; keywords for the parent.
  911.  
  912.                         (if
  913.                           (not
  914.                             (member keyword
  915.                                     parent-init-keywords
  916.                                     :test
  917.                                     #'eq))
  918.  
  919.                         ; THEN Print a warning message is ignore.
  920.  
  921.                           (warn
  922.                             (format
  923.                               NIL
  924.                               "DEFINE-TYPE: Init keyword, '~A', is not a keyword of '~A' in :INIT-KEYWORDS suboption."
  925.                               keyword
  926.                               (type-name parent-type-info)))
  927.  
  928.                         ; ELSE The keyword is legit.
  929.  
  930.                           (setf keywords-to-add
  931.                                  (remove keyword
  932.                                          keywords-to-add
  933.                                          :test
  934.                                          #'eq
  935.                                          :count
  936.                                          1))))))))
  937.  
  938.  ; keywords-to-add should be correctly setup now.
  939.  ; Add the elements of this list that are not already there, to the
  940.  ; existing list of keywords for this type.
  941.  
  942.    (setf (svref type-info $INIT-KEYWORDS-SLOT)
  943.           (add-to-set
  944.            (svref type-info $INIT-KEYWORDS-SLOT)
  945.            keywords-to-add))))
  946.  
  947. (defun parse-methods-suboption (type-info parent-type-info args)
  948.  
  949. ; At this point, we know that ARGS is a proper list where each element
  950. ; is a symbol that is not NIL.  Sample, args = (:EXCEPT M1 M2 M3),
  951. ; (:EXCEPT), ().  If method names are duplicated, the duplicates are
  952. ; ignored.  This function should change the $METHODS-TO-INHERIT-SLOT as
  953. ; in the following example:
  954. ;    PARENT-TYPE-INFO for PARENT2 and the total methods for PARENT2
  955. ;    are M1, M2,...,M6 and if ARGS = (:EXCEPT M1 M2 M3), and if
  956. ; $METHODS-TO-INHERIT-SLOT looked like:
  957. ;       ((<parent1 type info object> .(M1 M2 M3))), then
  958. ; $METHODS-TO-INHERIT-SLOT would look like:
  959. ;     ((<parent1 type info object> .  (M1 M2 M3))
  960. ;      (<parent2 type info object> . (M4 M5 M6)))
  961. ; after this routine completes.  When this routine finishes, we are
  962. ; guaranteed that each method added to the $METHODS-TO-INHERIT-SLOT is an
  963. ; existing methods of the parent.
  964.  
  965.  (let
  966.    ((parent-methods
  967.      (co::method-alist parent-type-info))
  968.     (methods-to-inherit nil)
  969.     (except-form?
  970.      (when (and args (eq (car args) ':except))
  971.  
  972.      ; THEN Skip over the :EXCEPT argument.
  973.  
  974.        (setf args (cdr args))
  975.        t)))
  976.  
  977.  ; ARGS will be NIL or a list at this point.  If NIL, we have (:METHODS)
  978.  ; or (:METHODS :EXCEPT).
  979.  
  980.    (dolist (method args)
  981.            (unless (assoc method parent-methods :test #'eq)
  982.  
  983.            ; THEN The method doesn't exits, give a warning.
  984.  
  985.              (warn
  986.                (format nil
  987.                        "DEFINE-TYPE: Method '~S' of the :METHODS suboption doesn't~% exist in parent '~S'."
  988.                        method
  989.                        (type-name parent-type-info)))))
  990.  
  991.    (if except-form?
  992.  
  993.    ; THEN We have the :EXCEPT form. List all methods that are not
  994.    ;      specified and are not universal methods.  If 
  995.    ;      (:METHODS :EXCEPT), all methods not universal methods are
  996.    ;      added.
  997.  
  998.      (dolist (method-function-pair parent-methods)
  999.  
  1000.      ; As long as the method is not an exception (:EXCEPT)
  1001.      ; and not a universal method of the parent, inherit it.
  1002.  
  1003.              (unless
  1004.                (or (member (car method-function-pair) args :test #'eq)
  1005.                    (member (car method-function-pair)
  1006.                $DEFINE-TYPE-UNIVERSAL-METHODS
  1007.                            :test
  1008.                            #'eq))
  1009.  
  1010.              ; THEN The method we are looking at is desired 
  1011.              ;      for inheritance.
  1012.  
  1013.                (setf methods-to-inherit
  1014.                       (add-to-set
  1015.                        methods-to-inherit
  1016.                        (car method-function-pair)))))
  1017.  
  1018.    ; ELSE We have the normal form.  If some of the args were not real
  1019.    ;      methods. If (:METHODS), nothing is done.
  1020.  
  1021.      (dolist (method args)
  1022.              (when (assoc method parent-methods :test #'eq)
  1023.  
  1024.              ; THEN The method really exists.
  1025.  
  1026.                (setf methods-to-inherit
  1027.                       (add-to-set methods-to-inherit method))
  1028.  
  1029.              ; Add to the list of explicitly stated methods to inherit.
  1030.              ; This is used for error checking with methods to not
  1031.              ; redefine later.
  1032.  
  1033.                (setf
  1034.                  (svref type-info $EXPLICITLY-LISTED-METHODS-SLOT)
  1035.                   (add-to-set
  1036.                    (svref type-info
  1037.                           $EXPLICITLY-LISTED-METHODS-SLOT)
  1038.                    method)))))
  1039.  
  1040.  ; Now add this list of methods to the type-info vector.
  1041.  ; 'methods-to-inherit' may be NIL.
  1042.  
  1043.    (setf (svref type-info $METHODS-TO-INHERIT-SLOT)
  1044.           (append (svref type-info $METHODS-TO-INHERIT-SLOT)
  1045.                   (list (cons parent-type-info methods-to-inherit))))))
  1046.  
  1047.  
  1048. (defun parse-var-option (var-names args type-info)
  1049.  
  1050. ; ARGS = (IV1 (:TYPE INTEGER) (:INIT 0.0) :SETTABLE) Return something
  1051. ; of the form:
  1052. ;    (VARIABLE-NAME . VAR-ASSIGNMENT)
  1053. ; VARIABLE-NAME is the name of the instance variable.  VAR-ASSIGNMENT
  1054. ; is the code needed to initialize this instance variable.
  1055.  
  1056.  (unless (and (consp args) (symbolp (car args)))
  1057.  
  1058.  ; THEN We have an error.
  1059.  
  1060.    (co-deftype-error
  1061.     "a symbol must follow a :VAR option."
  1062.     (type-name type-info)))
  1063.  
  1064.  (let ((variable (car args))
  1065.        (var-assignment nil))
  1066.  
  1067.  ; Make sure the instance variable name is legal.
  1068.  
  1069.    (instance-variable-ok? variable var-names (type-name type-info))
  1070.  
  1071.  ; Now parse all the suboptions of the :VAR option.
  1072.  ; VAR-ASSIGNMENT will be NIL if there is no :INIT suboption.
  1073.  
  1074.    (setf var-assignment
  1075.           (parse-var-suboptions type-info (cdr args) variable))
  1076.    (values variable var-assignment)))
  1077.  
  1078. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1079. ; Detailed :VAR Suboption Parsing
  1080. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1081.  
  1082. (defun parse-var-suboptions (type-info suboptions variable)
  1083.  
  1084. ; This routine returns the code for initialization of the instance
  1085. ; variable VARIABLE.  It is legal for suboptions to be NIL.  For
  1086. ; understandibility, expandability, and consistancy the parsing of
  1087. ; suboptions uses the same techniques with the same keywords that option
  1088. ; option parsing does.  This is true even though some of the option
  1089. ; information may not be shared between options and suboptions.  See
  1090. ; CO-PARSE-OPTIONS and its constituent routines.
  1091. ;
  1092. ; Example: SUBOPTIONS = ((:INIT 0.0)
  1093. ;                        (:TYPE INTEGER)
  1094. ;                        :SETTABLE)
  1095.  
  1096.  (let ((suboptions-so-far nil)
  1097.        (suboption-name nil)
  1098.        (suboption-info nil)
  1099.        (init-info nil)
  1100.       )
  1101.  
  1102.    (dolist (suboption suboptions)
  1103.  
  1104.                ; SUBOPTION-INFO will be NIL if SUBOPTION-NAME is not a
  1105.                ; legal suboption, or a list of information that tells what
  1106.                ; characteristics this suboption has.  Note that currently,
  1107.                ; if an error occurs in SUBOPTION-OK? we will NOT return
  1108.                ; to this function. The check for '(WHEN SUBOPTION-INFO...)'
  1109.                ; is for future continuable errors. If 'ONCE' is on this
  1110.                ; list, it means the suboption can only occur once.
  1111.  
  1112.                 (multiple-value-setq (suboption-name suboption-info)
  1113.                                (option-ok?
  1114.                                 suboption
  1115.                                 type-info
  1116.                                 'var-suboption))
  1117.                 (when suboption-info
  1118.  
  1119.                 ; THEN The suboption is a real one.
  1120.                 ;      Now make sure it doesn't occur more then once.
  1121.  
  1122.                   (if
  1123.                     (and
  1124.                       (member suboption-name suboptions-so-far :test #'eq)
  1125.                       (member 'once (cdr suboption-info) :test #'eq))
  1126.  
  1127.                   ; THEN We have duplicate suboptions.  Give an error.
  1128.  
  1129.                     (co-deftype-error
  1130.                      "duplicate suboption,~% '~S',~% specified to :VAR option."
  1131.                      (type-name type-info)
  1132.                      suboption)
  1133.  
  1134.                   ; ELSE Everything is ok.
  1135.  
  1136.                     (progn
  1137.                       (setf suboptions-so-far
  1138.                              (cons suboption-name suboptions-so-far))
  1139.                       (if
  1140.                         (member 'value-returned-suboption
  1141.                                 (cdr suboption-info)
  1142.                                 :test
  1143.                                 #'eq)
  1144.  
  1145.                       ; THEN We must save the return value.
  1146.  
  1147.                         (setf init-info
  1148.                                (parse-var-suboption
  1149.                                 type-info
  1150.                                 variable
  1151.                                 suboption
  1152.                                 suboption-info))
  1153.  
  1154.                       ; ELSE We don't care about the return value.
  1155.  
  1156.                         (parse-var-suboption
  1157.                          type-info
  1158.                          variable
  1159.                          suboption
  1160.                          suboption-info)))))
  1161.  
  1162.       ) ;dolist
  1163.  
  1164.       ;;Return the init-info
  1165.  
  1166.       init-info
  1167.  
  1168.   ) ;let
  1169.  
  1170. ) ;end parse-var-suboptions
  1171.  
  1172. (defun parse-var-suboption (type-info variable suboption suboption-info)
  1173.  
  1174. ; This routine calls the right function to parse SUBOPTION.  This
  1175. ; function is the first element of SUBOPTION-INFO.  Example:
  1176. ; SUBOPTION = (:INIT 0.0) The SUBOPTION given is either a symbol or a
  1177. ; list.  When a list, the rest of the arguments will be passed to the
  1178. ; function (may be NIL).  If a symbol, NIL is passed as arguments.
  1179. ; NOTE: Should make sure that the value returned by the suboption is
  1180. ;       the value of this routine, since some code may want to use
  1181. ;       the value returned (like the value of the :INIT suboption).
  1182.  
  1183.  (apply (car suboption-info)
  1184.         (list (if (consp suboption) (cdr suboption) nil)
  1185.               variable
  1186.               type-info)))
  1187.  
  1188.  
  1189. (defun instance-variable-ok? (variable list-of-variables type-name)
  1190.  
  1191. ; Signal a standard error if the variable is SELF,
  1192. ; one of the variables that are already in the list
  1193. ; of variables, or a keyword.
  1194. ; TYPE-NAME is used for error messages by CO-DEFTYPE-ERROR.
  1195.  
  1196.  (unless (legal-instance-variable variable)
  1197.  
  1198.  ; THEN error.
  1199.  
  1200.      (co-deftype-error
  1201.       "'SELF' NIL, or symbol from the keyword package~%was found as an instance variable."
  1202.       type-name))
  1203.  
  1204.  (when (member variable list-of-variables :test #'eq)
  1205.  
  1206.  ; THEN We have a duplicate variable.
  1207.  
  1208.    (co-deftype-error
  1209.     "instance variable '~S' occurs more~%than once."
  1210.     type-name
  1211.     variable)))
  1212.  
  1213. (defun legal-instance-variable (variable)
  1214.  
  1215. ; Return T if VARIABLE satisfies restrictions on instance variables.
  1216. ; Return NIL otherwise.  Currently, the variable must be a non-NIL symbol
  1217. ; that is not SELF.
  1218. ; Must also be a symbol that is NOT in the
  1219. ; keyword package.
  1220.  
  1221.  (and (symbolp variable)
  1222.       variable
  1223.       (not (eq variable 'co::self))
  1224.       (not (keywordp variable))))
  1225.  
  1226.  
  1227. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1228. ; Parsing of :ALL-xxx
  1229. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1230.  
  1231. (defun parse-all-initable-option (var-names args type-info)
  1232.  
  1233. ; Parses: :ALL-INITABLE.  ARGS will be NIL.
  1234.  
  1235.  (parse-initable-option var-names args type-info))
  1236.  
  1237. (defun parse-all-gettable-option (var-names args type-info)
  1238.  
  1239. ; Parses: :ALL-GETTABLE.  ARGS will be NIL.
  1240.  
  1241.  (parse-gettable-option var-names args type-info))
  1242.  
  1243. (defun parse-all-settable-option (var-names args type-info)
  1244.  
  1245. ; Parses: :ALL-SETTABLE.  ARGS will be NIL.
  1246.  
  1247.  (parse-settable-option var-names args type-info))
  1248.  
  1249. (defun parse-gettable-option (var-names args type-info)
  1250.  
  1251. ; Example ARGS = (A B C D), NIL.
  1252. ; Duplicate variables specified are ignored.
  1253.  
  1254.  (dolist (gettable-variable (or args var-names))
  1255.  
  1256.          (if (member gettable-variable var-names :test #'eq)
  1257.  
  1258.          ; THEN This variable is a real instance variable.
  1259.  
  1260.            (setf (svref type-info  $gettable-variables-slot)
  1261.                   (add-to-set
  1262.                    (svref type-info $GETTABLE-VARIABLES-SLOT)
  1263.                    gettable-variable))
  1264.          ; ELSE We have an illegal variable name.
  1265.  
  1266.            (co-deftype-error
  1267.             "variable '~S' in the settable~% options list is not an instance variable.~%"
  1268.             (type-name type-info)
  1269.             gettable-variable))))
  1270.  
  1271. (defun parse-settable-option (var-names args type-info)
  1272.  
  1273. ; Example ARGS = (A B C D), NIL.  Duplicate variables specified are
  1274. ; ignored. Each settable instance variable
  1275. ; is added to the list of gettable and initable instance variables as
  1276. ; well.
  1277.  
  1278.  (dolist (settable-variable (or args var-names))
  1279.  
  1280.          (if (not (member settable-variable var-names :test #'eq))
  1281.  
  1282.          ; THEN We have an illegal variable name.
  1283.  
  1284.            (co-deftype-error
  1285.             "variable '~S' in the settable~% options list is not an instance variable~%."
  1286.             (type-name type-info)
  1287.             settable-variable)
  1288.  
  1289.          ; ELSE This variable is a real instance variable.
  1290.  
  1291.            (progn
  1292.              (setf (svref type-info $initable-variables-slot)
  1293.                     (add-to-set
  1294.                      (svref type-info $initable-variables-slot)
  1295.                      settable-variable))
  1296.              (setf (svref type-info $gettable-variables-slot)
  1297.                     (add-to-set
  1298.                      (svref type-info $gettable-variables-slot)
  1299.                      settable-variable))
  1300.              (setf (svref type-info $settable-variables-slot)
  1301.                     (add-to-set
  1302.                      (svref type-info $settable-variables-slot)
  1303.                      settable-variable))))))
  1304.  
  1305. (defun parse-initable-option (var-names args type-info)
  1306.  
  1307. ; Example ARGS = (A B C D), NIL. Duplicate
  1308. ; variables specified are ignored.
  1309.  
  1310.  (dolist (initable-variable (or args var-names))
  1311.  
  1312.          (if (member initable-variable var-names :test #'eq)
  1313.  
  1314.          ; THEN This variable is a real instance variable.
  1315.  
  1316.            (setf (svref type-info  $initable-variables-slot)
  1317.                   (add-to-set
  1318.                    (svref type-info $initable-variables-slot)
  1319.  
  1320.                    initable-variable))
  1321.          ; ELSE We have an          (svref type-info $initable-variables-serror
  1322.             "variable '~S' in the initable~% options list is not an instance variable.~%"
  1323.             (type-name type-info)
  1324.             initable-variable))))
  1325.  
  1326. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1327. ; Parsing of :INIT-KEYWORDS Option and Suboption and :REDEFINED-METHODS
  1328. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1329.  
  1330. (defun parse-init-keywords-option (var-names args type-info)
  1331.   (declare (ignore var-names))
  1332.  
  1333. ; Parses: (:INIT-KEYWORDS <symbol>).  Doesn't use VAR-NAMES.  By the
  1334. ; time this routine is called, each element of args has been checked to
  1335. ; be a symbol not equal to NIL.  ARGS is also a proper list. For
  1336. ; (:INIT-KEYWORDS), ARGS will be NIL.  We add the existing
  1337. ; init-keywords because we may have hit :INIT-KEYWORDS suboptions from
  1338. ; :INHERIT-FROM options.
  1339.  
  1340.  (setf (svref type-info $INIT-KEYWORDS-SLOT)
  1341.         (add-to-set (svref type-info $INIT-KEYWORDS-SLOT) args)))
  1342.  
  1343. (defun parse-no-init-keyword-check-option (var-names args type-info)
  1344.   (declare (ignore args var-names))
  1345.  
  1346. ; Parses: :NO-INIT-KEYWORD-CHECK. VAR-NAMES is not used.
  1347.  
  1348.  (setf (svref type-info $NO-INIT-KEYWORD-CHECK-SLOT) t))
  1349.  
  1350. (defun parse-redefined-methods-option (var-names args type-info)
  1351.  
  1352.   (declare (ignore var-names))
  1353.  
  1354. ; Parses: (:REDEFINED-METHODS M1 M2 M3), or (:REDEFINED-METHODS).  ARGS
  1355. ; = (M1 M2 M3).  At this point, ARGS is guaranteed to be a proper list
  1356. ; where each element is a symbol that is non-NIL.  For
  1357. ; (:REDEFINED-METHODS), args is NIL.  NOTE: The order of arguments are
  1358. ; stored away doesn't matter.
  1359.  
  1360.  (setf (svref type-info $methods-to-not-define-slot)
  1361.         (remove-duplicates args :test #'eq)))
  1362.  
  1363. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1364. ; Parsing of :INHERIT-FROM Option and Suboption
  1365. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1366.  
  1367. (defun parse-inherit-from-option (var-names args type-info)
  1368.   (declare (ignore var-names))
  1369.  
  1370. ; ARGS is the list of remaining stuff inside the :INHERIT-FROM option.
  1371. ; We know that ARGS is a proper list and that it has at least one element.
  1372. ; Sample: ARGS = (PARENT1 (:METHODS M1 M2 M3)
  1373. ;                         (:VARIABLES X Y Z)
  1374. ;                         (:INIT-KEYWORDS :EXCEPT Q))
  1375. ; VAR-NAMES is not used.  Note that for error handling to be changed to
  1376. ; continuable errors, these options will have to be changed, since side
  1377. ; effects to type info can occur before a syntax error occurs.  When
  1378. ; finished, the $PARENT-TYPES-SLOT and the $PARENTS-INFO-SLOT may be
  1379. ; changed.
  1380.  
  1381.  (if (and (consp args) (symbolp (car args))) 
  1382.  
  1383.  ; THEN The form of the parent is ok.
  1384.  ;      Now check if it is partially defined.
  1385.  
  1386.    (let ((parent-type-info (type-partially-defined? (car args)))
  1387.          (parents (svref type-info $PARENT-TYPES-SLOT))
  1388.          (new-parent (car args)))
  1389.  
  1390.      (if (not parent-type-info)
  1391.  
  1392.      ; THEN The parent isn't defined.  Give an error.
  1393.  
  1394.        (co-deftype-error
  1395.         "~%the parent '~s',~s of the :INHERIT-FROM option, is not defined."
  1396.         (type-name type-info)
  1397.         new-parent)
  1398.      
  1399.      ; ELSE The parent is partially defined.
  1400.      ;      First check that options specified are ok.
  1401.      ; Add the parent to the type-info slot.  We must append
  1402.      ; since the order is important -- the first :INHERIT-FROM option
  1403.      ; must be the first parent.
  1404.      ; Check that we don't have something like:
  1405.      ;      (INHERIT-FROM B...)
  1406.      ;      (INHERIT-FROM B...) within the type definition.
  1407.        (if
  1408.          (member new-parent parents :test #'eq)
  1409.  
  1410.        ; THEN Two or more parents that are the same parent.
  1411.  
  1412.          (co-deftype-error
  1413.           "~~Sarent '~s' of type '~s'~s can only be a parent once."
  1414.           (type-name type-info)
  1415.           new-parent
  1416.           (type-name type-info))
  1417.  
  1418.        ; ELSE Everything is ok.
  1419.        ; Add the parents type-info to be used later.
  1420.        ; This is stored in the same order as the parents in the
  1421.        ; $PARENT-TYPES-SLOT for consistency.
  1422.        
  1423.          (progn
  1424.            (set-parents-info
  1425.             type-info
  1426.             (append (get-parents-info type-info)
  1427.                     (list
  1428.                       (list new-parent parent-type-info '*place-holder*))))
  1429.            (setf (svref type-info $PARENT-TYPES-SLOT)
  1430.                   (append parents (list new-parent)))
  1431.            (parse-inherit-from-suboptions
  1432.             type-info
  1433.             parent-type-info
  1434.             (cdr args))))))
  1435.  
  1436.  ; ELSE The parent form is illegal.
  1437.  
  1438.    (co-deftype-error
  1439.     "~%a symbol must follow an :INHERIT-FROM~% option."
  1440.     (type-name type-info))))
  1441.  
  1442. (defun parse-inherit-from-suboptions
  1443.  (type-info parent-type-info suboptions)
  1444.  
  1445. ; It is legal for SUBOPTIONS to be NIL.  For understandibility,
  1446. ; expandability, and consistancy the parsing of subptions uses the same
  1447. ; techniques with the same keywords for option information.  This is
  1448. ; true even though some of the option information may not be shared
  1449. ; between options and suboptions.  See CO-PARSE-OPTIONS and its
  1450. ; constituent routines.  NOTE: If the name of :METHODS option is ever
  1451. ; changed (in RETURN-OPTION-INFO) the references to :METHODS must be
  1452. ; changed here as well.
  1453. ;
  1454. ; Example: SUBOPTIONS = ((:VARIABLES A B)
  1455. ;                        (:METHODS C D)
  1456. ;                        (:INIT-KEYWORDS EXCEPT J))
  1457.  
  1458.  (let ((suboptions-so-far nil)
  1459.        (suboption-name nil)
  1460.        (suboption-info nil))
  1461.  
  1462.    (dolist (suboption suboptions)
  1463.  
  1464.    ; SUBOPTION-INFO will be NIL if SUBOPTION-NAME is not a
  1465.    ; legal suboption, or a list of information that tells what
  1466.    ; characteristics this suboption has.  Note that currently,
  1467.    ; if an error occurs in SUBOPTON-OK? we will NOT return
  1468.    ; to this function. The check for (WHEN SUBOPTION-INFO...)
  1469.    ; is for future continuable errors. If 'ONCE' is on this
  1470.    ; list, it means the suboption can only occur once.
  1471.  
  1472.            (multiple-value-setq (suboption-name suboption-info)
  1473.                 (option-ok?
  1474.                  suboption
  1475.                  type-info
  1476.                  'inherit-from-suboption))
  1477.            (when suboption-info
  1478.  
  1479.            ; THEN The suboption is a real one.
  1480.            ;      Now make sure it doesn't occur more then once.
  1481.  
  1482.              (if
  1483.                (and (member suboption-name suboptions-so-far :test #'eq)
  1484.                     (member 'once (cdr suboption-info) :test #'eq))
  1485.  
  1486.              ; THEN We have duplicate suboptions.  Give an error.
  1487.  
  1488.                (co-deftype-error
  1489.                 "duplicate suboption,~s '~s',~s specified to :INHERIT-FROM option."
  1490.                 (type-name type-info)
  1491.                 suboption)
  1492.  
  1493.              ; ELSE Everything is ok.
  1494.  
  1495.                (progn
  1496.                  (setf suboptions-so-far
  1497.                         (cons suboption-name suboptions-so-far))
  1498.                  (parse-inherit-from-suboption
  1499.                   type-info
  1500.                   parent-type-info
  1501.                   suboption
  1502.                   suboption-info)))))
  1503.  
  1504.  ; Now check the one funny case: If the :METHODS option was NOT present.
  1505.  
  1506.    (unless (member ':methods suboptions-so-far :test #'eq)
  1507.  
  1508.    ; THEN We had no :METHODS suboption, so inherit all methods
  1509.    ;      (but not universal methods).  Do this by making
  1510.    ;      a suboption (:METHODS :EXCEPT), and having it parsed.
  1511.  
  1512.      (multiple-value-setq (suboption-name suboption-info)
  1513.                     (option-ok?
  1514.                      '(:methods :except)
  1515.                      type-info
  1516.                      'inherit-from-suboption))
  1517.  
  1518.      (parse-inherit-from-suboption
  1519.       type-info
  1520.       parent-type-info
  1521.       '(:methods :except)
  1522.       suboption-info))))
  1523.  
  1524. (defun parse-inherit-from-suboption
  1525.  (type-info parent-type-info suboption suboption-info)
  1526.  
  1527. ; Example: SUBOPTION = (:INIT-KEYWORDS :EXCEPT J K L) The suboption
  1528. ; given is either a symbol or a list.  When a list, the rest of the
  1529. ; arguments will be passed to the function (may be NIL).  If a symbol,
  1530. ; NIL is passed as arguments.
  1531.  
  1532.  (apply (car suboption-info)
  1533.         (list type-info
  1534.               parent-type-info
  1535.               (if (consp suboption) (cdr suboption) nil))))
  1536.  
  1537. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1538. ; Method Definition
  1539. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1540.  
  1541. (defun co-parse-method-macro-call
  1542.  (spec argument-list body)
  1543.  
  1544. ; Make sure that the type-name and method-name are ok.  Also, that the
  1545. ; call is a proper list. 
  1546. ; Note that use of instance variable names as formal
  1547. ; parameter names to the method and use of SELF as a formal parameter
  1548. ; name are not checked.
  1549.  
  1550.   (let
  1551.     (
  1552.       (type-name NIL)
  1553.       (method-name NIL)
  1554.     )
  1555.  
  1556.    ; Check to be sure the body is a proper list or NIL
  1557.  
  1558.    (unless (or (null body) (proper-list body))
  1559.  
  1560.    ; THEN the method definition is not a proper list
  1561.  
  1562.      (define-method-error
  1563.       "The call,~% '(DEFINE-METHOD ~S ~S ~S)',~% is missing arguments or is an improper list."
  1564.       spec argument-list body))
  1565.  
  1566.  ; Check the spec
  1567.  
  1568.    (unless (and (proper-list spec) (= (length spec) 2)) ;rds 3/8 eq->=
  1569.  
  1570.    ; THEN The form of the (type-name method-name) is incorrect.
  1571.  
  1572.      (define-method-error
  1573.       "The type-name and method-name in the call,~% '(DEFINE-METHOD ~S ~S ~S)',~% must be a two element proper list."
  1574.       spec argument-list body))
  1575.  
  1576.    (setf method-name (second spec))
  1577.    (setf type-name (first spec))
  1578.  
  1579.    (unless (co-legal-type-or-method-name type-name)
  1580.  
  1581.    ; THEN Invalid type.
  1582.  
  1583.      (define-method-error
  1584.       "Type name '~S' in the call,~% '(DEFINE-METHOD ~S ~S ~S)',~% must be a non-NIL symbol."
  1585.       type-name
  1586.       spec
  1587.       argument-list
  1588.       body))
  1589.  
  1590.    (unless (co-legal-type-or-method-name method-name)
  1591.  
  1592.    ; THEN Invalid method.
  1593.  
  1594.      (define-method-error
  1595.       "Method name '~S' in the call,~% '(DEFINE-METHOD ~S ~S ~S)',~% must be a non-NIL symbol."
  1596.       method-name
  1597.       spec
  1598.       argument-list
  1599.       body))
  1600.  
  1601.  ; Check that the argument-list is indeed a list.
  1602.  
  1603.    (unless (or (null argument-list) (proper-list argument-list))
  1604.      (define-method-error
  1605.       "The argument list in the call,~% '(DEFINE-METHOD ~S ~S ~S)',~%  is missing or must be a proper list."
  1606.       spec
  1607.       argument-list
  1608.       body))
  1609.  
  1610.   ) ;let
  1611. ) ;co-parse-method-macro-call 
  1612.  
  1613. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1614. ; Call-Method Support
  1615. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1616.  
  1617. (defun co-parse-call-to-method (call-method-call which-func class-name)
  1618.  
  1619. ; Parse a call to a CALL-METHOD or APPLY-METHOD. Signal any
  1620. ; errors in syntax.
  1621. ; 'which-func' is either "CALL-METHOD" or "APPLY-METHOD".
  1622.  
  1623.  (let ((method-name nil)
  1624.        (rest-of-call call-method-call))
  1625.  
  1626.    (setf rest-of-call (cdr rest-of-call))
  1627.  
  1628.  ; This should now be the list of arguments 
  1629.  
  1630.    (unless (proper-list rest-of-call)
  1631.  
  1632.    ; THEN The call to CALL-METHOD is not a proper list.
  1633.  
  1634.      (error
  1635.       (format nil
  1636.               "~A: The call,~% '~S',~% is missing arguments or is an improper list."
  1637.               which-func
  1638.               call-method-call)))
  1639.  
  1640.    ; If the form is APPLY-METHOD, check to be sure the argument list is
  1641.    ; not NIl
  1642.  
  1643.    (when (equalp which-func "APPLY-METHOD")
  1644.      (unless (cadr rest-of-call)
  1645.          
  1646.        (error
  1647.          (format nil
  1648.              "APPLY-METHOD: The call,~% '~S',~% has no argument list."
  1649.                  call-method-call
  1650.          )
  1651.        )
  1652.      )
  1653.    )
  1654.  
  1655.    (setf method-name (first rest-of-call))
  1656.  
  1657.    (cond
  1658.      ((co-legal-type-or-method-name method-name)
  1659.  
  1660.      ; THEN We have the local form of call-method (i.e.,
  1661.      ;      (CALL-METHOD MOOSE 3) ) so just return.
  1662.  
  1663.       NIL
  1664.      )
  1665.  
  1666.      ; ELSE Check if a two element list, each element a symbol.
  1667.  
  1668.     ((consp method-name)
  1669.      (unless
  1670.        (and (= (length method-name) 2)
  1671.             (proper-list method-name)
  1672.             (co-legal-type-or-method-name (first method-name))
  1673.             (co-legal-type-or-method-name (second method-name))
  1674.             (co::legal-parent-p class-name (first method-name)))
  1675.  
  1676.      ; Incorrect parent form of call-method.
  1677.  
  1678.        (error
  1679.         (format nil
  1680.                 "~A: Illegal parent reference '~S' in~% '~S'.~%  Must have the form: '(type-symbol operation-symbol)'."
  1681.                 which-func
  1682.                 method-name
  1683.                 call-method-call)
  1684.       ))
  1685.     )       
  1686.  
  1687.     ; Anything else is an error.
  1688.  
  1689.     (t
  1690.       (error
  1691.        (format nil
  1692.                "~A: Incorrect form '~S' in~% '~S'.~%  Expecting non-NIL symbol or list or two non-NIL symbols."
  1693.                which-func
  1694.                method-name
  1695.                call-method-call))))
  1696.  
  1697.     ) ;let
  1698.  
  1699. ) ;co-parse-call-to-method
  1700.  
  1701. (defun check-that-method-to-call-exists
  1702.  (possible-method-name child-name parent-name parent-methods)
  1703.  
  1704. ; Return the name of the method we will be calling.
  1705. ; The method name to use is determined as follows: First, always use the ':'
  1706. ; version of the name.  If the method with this name is not defined,
  1707. ; check if the name without the ':' is defined.  If it is, issue a
  1708. ; warning message that we are calling this method.  If it isn't
  1709. ; defined, issue a warning message that the method is not defined and
  1710. ; that we will call the ':' version when it is defined.  For example,
  1711. ; if we had the POSSIBLE-METHOD-NAME of A we would first check if a
  1712. ; method named :A existed in the PARENT-METHODS.  If it does, we
  1713. ; return :A.  If it doesn't, we see if a method with the name A
  1714. ; exists.  If it does, we return this name and give a warning.  If it
  1715. ; doesn't, we return :A and give a warning.
  1716.  
  1717.  (let*
  1718.    ((method-to-call
  1719.      (return-keyword-from-variable possible-method-name))
  1720.     (saved-method-to-call method-to-call))
  1721.  
  1722.    (unless (assoc method-to-call parent-methods :test #'eq)
  1723.  
  1724.    ; THEN The ':' version of the method doesn't exist.
  1725.    ;      Now check if the non-colon version exists.
  1726.  
  1727.      (setf method-to-call possible-method-name)
  1728.  
  1729.      (if
  1730.        (assoc method-to-call parent-methods :test #'eq)
  1731.  
  1732.      ; THEN We are calling the non-colon version of the method.
  1733.      ;      Give a warning message.
  1734.  
  1735.        (warn
  1736.          (format nil
  1737.                  "DEFINE-TYPE: In type, '~A', '~A' of :VARIABLES suboption, will reference the parent method '~A'."
  1738.                  child-name
  1739.                  possible-method-name
  1740.                  possible-method-name))
  1741.  
  1742.      ; ELSE Give a warning that we will assume calling the ':' version.
  1743.  
  1744.        (progn (setf method-to-call saved-method-to-call)
  1745.               (warn
  1746.                 (format nil
  1747.                         "DEFINE-TYPE: In type, '~A', '~A' of :VARIABLES suboption, has no corresponding method defined in parent '~A'. Will assume you want to call method '~A'."
  1748.                         child-name
  1749.                         possible-method-name
  1750.                         parent-name
  1751.                         method-to-call)))))
  1752.    method-to-call))
  1753.  
  1754. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1755.  
  1756.