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

  1.  
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;
  4. ; File:         co-dtype.l
  5. ; RCS:          $Revision: 1.1 $
  6. ; SCCS:         %A% %G% %U%
  7. ; Description:  CommonObjects types.
  8. ; Author:       James Kempf
  9. ; Created:      March 10, 1987
  10. ; Modified:     12-Mar-87 09:58:43 (James Kempf)
  11. ; Language:     Lisp
  12. ; Package:      COMMON-OBJECTS
  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. ;;;-*-Mode:LISP; Package:(CO (PCL LISP)); Base:10; Syntax: Common-lisp-*-
  33. ;;;
  34. ;;; *************************************************************************
  35. ;;; Copyright (c) 1985 Xerox Corporation.  All rights reserved.
  36. ;;;
  37. ;;; Use and copying of this software and preparation of derivative works
  38. ;;; based upon this software are permitted.  Any distribution of this
  39. ;;; software or derivative works must comply with all applicable United
  40. ;;; States export control laws.
  41. ;;; 
  42. ;;; This software is made available AS IS, and Xerox Corporation makes no
  43. ;;; warranty about the software, its performance or its conformity to any
  44. ;;; specification.
  45. ;;; 
  46. ;;; Any person obtaining a copy of this software is requested to send their
  47. ;;; name and post office or electronic mail address to:
  48. ;;;   CommonLoops Coordinator
  49. ;;;   Xerox Artifical Intelligence Systems
  50. ;;;   2400 Hanover St.
  51. ;;;   Palo Alto, CA 94303
  52. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  53. ;;;
  54. ;;; Suggestions, comments and requests for improvements are also welcome.
  55. ;;; *************************************************************************
  56.  
  57. (in-package 'common-objects :nicknames '(co) :use '(lisp pcl walker))
  58.  
  59. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  60. ;  Define-Type
  61. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  62.  
  63. ;;define-type-Define a CommonObjects type
  64.  
  65. (defmacro define-type (&rest body)
  66.  
  67.      (internal-define-type body)
  68.  
  69. ) ;end define-type
  70.  
  71. ;;internal-define-type-Parse a CommonObjects type definition and
  72. ;;  generate code for creating the type.
  73.  
  74. (defun internal-define-type (body)
  75.  
  76.    (let
  77.      (
  78.        (doc-string NIL) ;;documentation string, if any
  79.        (name NIL)    ;;type name
  80.        (parents NIL)    ;;list of parents
  81.        (slots   NIL)    ;;list of instance variables
  82.        (options NIL)    ;;options list
  83.        (phonytiv NIL)    ;;phony type info vector. Used to
  84.                         ;;  hold type definition during
  85.                         ;;  parsing.
  86.        (assignments NIL);;variable initializations
  87.        (settables NIL)    ;;settable method names
  88.        (gettables NIL)    ;;gettable method names
  89.        (inherited NIL)    ;;inherited methods w. parents
  90.        (keywords NIL)   ;;keywords for initialization
  91.        (init-key-check  ;;T if a check should occur
  92.         NIL
  93.        )
  94.        (dont-define NIL)  ;;methods to not define
  95.      )
  96.  
  97.   
  98.      ;;Get name and options
  99.  
  100.      (multiple-value-setq
  101.       (name doc-string options)
  102.         (co-parse-define-type-call (cons 'define-type body) 
  103.                    name doc-string options
  104.         )
  105.      )
  106.  
  107.      ;;Make a phony type info for use with options parsing code
  108.  
  109.      (setf phonytiv (build-phony-type-info name))     
  110.  
  111.      ;;Get variable names, assignments, and other options
  112.  
  113.      (multiple-value-setq
  114.       (slots assignments options)
  115.       (co-process-var-options phonytiv options slots assignments)
  116.      )
  117.  
  118.      ;;Fill in phony type info with option information
  119.  
  120.      (co-parse-options phonytiv slots options)
  121.  
  122.      (setf parents (svref phonytiv $PARENT-TYPES-SLOT))
  123.  
  124.      (setf gettables (svref phonytiv $GETTABLE-VARIABLES-SLOT))
  125.      (setf settables (svref phonytiv $SETTABLE-VARIABLES-SLOT))
  126.      (setf inherited (svref phonytiv $METHODS-TO-INHERIT-SLOT))
  127.      (setf init-key-check 
  128.     (not (svref phonytiv $NO-INIT-KEYWORD-CHECK-SLOT))
  129.      )
  130.      (setf dont-define 
  131.        (svref phonytiv $METHODS-TO-NOT-DEFINE-SLOT)
  132.      )
  133.  
  134.      ;;Make keywords out of initiable variables and merge with
  135.      ;;  keywords
  136.  
  137.      (setf keywords 
  138.            (append
  139.          (svref phonytiv  $INIT-KEYWORDS-SLOT)
  140.              (mapcar 
  141.                #'(lambda (x) 
  142.                  (intern (symbol-name x) (find-package 'keyword))
  143.                )
  144.                (svref phonytiv $INITABLE-VARIABLES-SLOT)
  145.              )
  146.            )
  147.  
  148.     ) ;setf
  149.  
  150.     ;;All compile-time checking must be done BEFORE the compile-time
  151.     ;;  class definition is done, so that errors don't leave
  152.     ;;  around a bogus class.
  153.  
  154.     ;;Merge duplicate method names and check for inheritance
  155.     ;;  funny business
  156.  
  157.     (merge-duplicates name gettables settables inherited dont-define)
  158.  
  159.      ;;Fully define the class at compile-time, so that 
  160.      ;;  method definition works. Note that this means that
  161.      ;;  any pre-existing definition will be clobbered.
  162.      ;;  Compile time definition is needed for
  163.      ;;  any other methods which are defined in the same
  164.      ;;  file as a type definition. This is necessary because
  165.      ;;  the metaobject protocol doesn't distinguish between
  166.      ;;  a partially defined type and a fully defined one.
  167.      ;;  Compile-time definition is no longer needed for
  168.      ;;  definition of inherited, universal, and get/set
  169.      ;;  methods, since the metaobject protocol is gone
  170.      ;;  around for these, except for the :INITIALIZE-VARIABLES
  171.      ;;  method, which is still generated in full.
  172.  
  173.      (fully-define-type name slots parents keywords init-key-check)
  174.  
  175.      ;;Generate code for the class definition. This code
  176.      ;;  defines the class at load time and the universal
  177.      ;;  methods.
  178.  
  179.     `(progn
  180.  
  181.        ;;This only needs to get done at load time, since
  182.        ;;  class definition at compile time (to take
  183.        ;;  care of :INITIALIZE-VARIABLES method generation
  184.        ;;  and others in the file) is done during the macro
  185.        ;;  expansion. Also, it need not get done if the
  186.        ;;  definition is being evaluated, since the macro
  187.        ;;  has already done in.
  188.  
  189.        (eval-when (load)
  190.      (fully-define-type ',name 
  191.                     ',slots 
  192.                 ',parents
  193.                 ',keywords
  194.                 ',init-key-check
  195.      )
  196.        )
  197.  
  198.         ;;Define the initialization, get/set, and inherited methods.
  199.  
  200.         ;;Variable initialization is handled by generating an
  201.         ;;  initialization method. The :INITIALIZE-VARIABLES method 
  202.         ;;  is the only universal one  generated on a type by type basis.
  203.         ;;  Since the user can insert anything into the initialization
  204.         ;;  forms, the code must go through the full processing
  205.         ;;  for method definition, including code walking of
  206.         ;;  WITH-SLOTS. This requires that the PCL class be
  207.         ;;  defined at compile time.
  208.  
  209.         ,(if (not (member ':initialize-variables dont-define))
  210.           (build-init-vars-method
  211.             name
  212.             (svref phonytiv $INITABLE-VARIABLES-SLOT)
  213.         assignments
  214.           )
  215.         )
  216.  
  217.     ;;Universal methods are no longer defined on a per type
  218.         ;;  basis, but rather default methods are defined
  219.         ;;  for all CommonObjects types. The user can define
  220.     ;;  their own methods which override the default ones,
  221.     ;;  but the defaults can't be undefined or renamed.
  222.     ;;  Using defaults saves time during type definition.
  223.  
  224.         ;;Inherited methods  must be defined
  225.         ;;  at compile time, otherwise the CLASS-DIRECT-METHODS
  226.         ;;  call in METHOD-ALIST won't find the gettable and
  227.         ;;  settable methods during compilation. This is
  228.         ;;  also true for gettable and settable methods.
  229.         ;;  Note, however, that other methods defined in
  230.         ;;  the same file will NOT get inherited, because
  231.         ;;  they are not fully defined at compile time.
  232.         ;;  This means that users should avoid defining
  233.         ;;  parent and child types in the same file.
  234.         ;;  In particular, the ADD-METHOD call generated
  235.         ;;  by the PCL method generation code only gets
  236.         ;;  done at load time, and hence seperately defined
  237.         ;;  methods are only returned by CLASS-DIRECT-METHODS
  238.         ;;  after loading. The code below  will cause the 
  239.         ;;  (EVAL-WHEN (LOAD) ...) top level forms returned 
  240.         ;;  by the PCL method code generation to be overridden.
  241.  
  242.  
  243.           ;;Inherited methods
  244.  
  245.           ,@(build-inherited-methods name inherited dont-define parents slots)
  246.  
  247.           ;;Gettables and settables
  248.  
  249.       ,@(build-gs-methods name gettables settables dont-define parents slots)
  250.  
  251.           ',name
  252.  
  253.        ) ;progn
  254.  
  255.  
  256.   ) ;end let
  257. ) ;end internal-define-type
  258.  
  259. ;;fully-define-type-Fully define the CommonObjects type 
  260.  
  261. (defun fully-define-type (name slots parents keywords init-key-check)
  262.  
  263.   (let
  264.     (
  265.       (classprot (class-prototype (class-named 'common-objects-class)))
  266.     )
  267.  
  268.     ;;Check for redefinition incompatibility, if any.
  269.  
  270.     (check-for-redefinition-incompatibility name parents slots)
  271.  
  272.     (add-named-class classprot
  273.              name
  274.              parents
  275.              slots
  276.              NIL
  277.     )
  278.  
  279.  
  280.     ;;Now set the slots for the initialization keywords and
  281.     ;;  the check flag
  282.  
  283.     (setf classprot (class-named name))
  284.     (setf (class-init-keywords classprot) keywords)      
  285.     (setf (class-init-keywords-check classprot) init-key-check)
  286.  
  287.   ) ;let
  288.  
  289. ) ;end fully-define-type
  290.  
  291. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  292. ;  Auxillary Type Definition Functions
  293. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  294.  
  295. ;;build-phony-type-info-Make a phony type info vector, to hold the
  296. ;;  information while the DEFINE-TYPE call is being parsed.
  297.  
  298. (defun build-phony-type-info (name)
  299.  
  300. ;;Check if the name is OK first
  301.  
  302.   (unless (co-legal-type-or-method-name name)
  303.     (co-deftype-error "legal type names must be symbols and NOT the symbol NIL."
  304.       name
  305.     )
  306.   )
  307.  
  308.   ;;Set the name and origin slots and return
  309.  
  310.   (let
  311.     (
  312.       (phonytiv 
  313.     (make-array 
  314.       $INFO-NUMBER-OF-SLOTS
  315.       :initial-element NIL
  316.         )
  317.       )
  318.     )
  319.  
  320.     (setf (svref phonytiv $TYPE-NAME-SLOT) name)
  321.  
  322.     phonytiv
  323.  
  324.     ;;Note that we don't check for predefined type info's here
  325.     ;;  because that should (eventually!) be handled by
  326.     ;;  the CommonLoops kernel
  327.  
  328.   ) ;end let
  329.  
  330. ) ;end build-phony-type-info
  331.  
  332. ;;check-for-redefinition-incompatibility-Check to see if redefining
  333. ;;  will cause an incompatible change
  334.  
  335. (defun check-for-redefinition-incompatibility (name newparents newslots)
  336.  
  337.   (let*
  338.     (
  339.       (oldclass (class-named name T))
  340.     )
  341.  
  342.  
  343.     ;;If no class object, then this is new      
  344.  
  345.     (when oldclass
  346.  
  347.       ;;Check instance variable incompatibility
  348.  
  349.       (if (not (slots-compatible-p newslots (class-user-visible-slots oldclass)))
  350.         (co-deftype-error
  351.         "please rename, since changing instance variables is incompatible.~%"
  352.         name
  353.         )
  354.       )
  355.  
  356.       ;;Check for parent incompatibility
  357.  
  358.       (if (not 
  359.         (slots-compatible-p 
  360.           newparents 
  361.           (class-local-super-names oldclass)
  362.             )
  363.           )
  364.         (co-deftype-error
  365.         "please rename, since changing parents is incompatible.~%"
  366.         name
  367.         )
  368.       )
  369.  
  370.     ) ;when
  371.  
  372.   ) ;let
  373.  
  374. ) ;end check-for-redefinition-incompatibility
  375.  
  376. ;;slots-compatible-p-Check if the number and ordering
  377. ;;  of the slots in the old and new lists is the same
  378.  
  379. (defun slots-compatible-p (newslots oldslots)
  380.  
  381.   ;;Check that number of slots is the same
  382.  
  383.   (when (not (= (length oldslots) (length newslots)))
  384.     (return-from slots-compatible-p NIL) 
  385.   )
  386.  
  387.   ;;Check slot names
  388.     
  389.   (do
  390.     (
  391.       (ns newslots (cdr ns))
  392.       (os oldslots (cdr os))
  393.     )
  394.     ( (or (null ns) (null os)) )
  395.  
  396.     (if (not (eq (car ns) (car os)))
  397.       (return-from slots-compatible-p NIL)
  398.     ) ;if
  399.   ) ;do
  400.  
  401.   T
  402. ) ;end slots-compatible-p
  403.  
  404. ;;merge-duplicates-Merge duplicates and check for conflicts
  405. ;;   in parents.
  406.  
  407. (defun merge-duplicates (name gettables settables parents dont-define)
  408.  
  409.   ;;Destructively modify gettables and settables
  410.   ;;to get rid of duplicates
  411.  
  412.   (merge-methods gettables settables)
  413.  
  414.   ;;Check for funny business in inheritance
  415.  
  416.   (check-for-funny-inheritance name parents)
  417.  
  418.   ;;Check if any conflicts with parents and among parents
  419.  
  420.   (check-for-method-conflicts name gettables parents dont-define)
  421.  
  422.   NIL
  423. ) ;end merge-duplicates
  424.  
  425. ;;merge-methods-Put settables on gettable list
  426.  
  427. (defun merge-methods (gettables settables)
  428.  
  429.   (dolist (meth settables)
  430.  
  431.     (when (not (member meth gettables :test #'equal))
  432.       (setf (cdr (last gettables)) (list meth ) )
  433.     )
  434.   ) ;dolist
  435.  
  436. ) ;end merge-methods
  437.  
  438. ;;check-for-funny-inheritance-Check for attempts to inherit
  439. ;;  from yourself
  440.  
  441. (defun check-for-funny-inheritance (name parents)
  442.  
  443.   ;;Check me
  444.  
  445.   (dolist (p parents)
  446.  
  447.     ;; Check me
  448.  
  449.     (if (eq name (class-name (car p)))
  450.       (co-deftype-error"this type has itself as an ancestor.~%" name)
  451.     )
  452.  
  453.     ;;Check parent
  454.  
  455.     (check-for-funny-inheritance name (mapcar #'list (class-local-supers (car p))))
  456.   )
  457.  
  458. ) ;end check-for-funny-inheritance
  459.  
  460. ;;check-for-method-conflicts-Merge gettable and parent lists and
  461. ;;  check for conflicts.
  462.  
  463. (defun check-for-method-conflicts (name gettables parents dont-define)
  464.  
  465.   (let
  466.     (
  467.       (kwp (find-package 'keyword))
  468.       (meths NIL)
  469.     )
  470.  
  471.     ;;Intern the gettable names in the keyword package
  472.  
  473.     (dolist (g gettables)
  474.       (setf meths (cons (intern (symbol-name g) kwp) meths))
  475.     ) ;dolist
  476.  
  477.     ;;Concatenate the parent methods onto the end
  478.  
  479.     (dolist (p parents)
  480.  
  481.       (setf meths 
  482.     (concatenate 
  483.       'list 
  484.       meths 
  485.       (cdr p)
  486.     )
  487.       )
  488.  
  489.     ) ;dolist
  490.  
  491.     ;;Now check for duplicates
  492.  
  493.     (check-for-conflicts name meths dont-define)
  494.  
  495.   ) ;let
  496.  
  497. ) ;end check-for-method-conflicts
  498.  
  499. ;;check-for-conflicts-Check if any generated methods
  500. ;;  conflict
  501.  
  502. (defun check-for-conflicts (name list dont-define)
  503.  
  504.     (setf list (sort list #'(lambda (x y) (string-lessp (symbol-name x) (symbol-name y)))))
  505.  
  506.     (do*
  507.       (
  508.         (item (car list) (car clist))
  509.         (clist (cdr list) (cdr clist))
  510.       )
  511.       ((eq clist NIL))
  512.  
  513.       ;;Check if a method already exists and isn't on the don't define
  514.       ;;  list
  515.  
  516.       (if (and (equal item (car clist)) (not (member item dont-define)))
  517.         (co-deftype-error
  518.       "two methods ~S exist during method generation.~%~
  519.            Please undefine one or the other.~%"
  520.       name item
  521.         )
  522.       )
  523.     ) ;do
  524.  
  525. ) ;end check-for-conflicts
  526.  
  527. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  528. ;  Top Level Method Building Functions
  529. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  530.  
  531. ;;build-inherited-methods-Build the list of inherited methods by using
  532. ;;  apply-method
  533.  
  534. (defun build-inherited-methods (name parents dont-define parent-names slots)
  535.  
  536.   (let
  537.     (
  538.       (methcode NIL)
  539.     )
  540.  
  541.     ;;Do all the parents
  542.  
  543.     (dolist (p parents)
  544.  
  545.       ;;Do this parent's list
  546.  
  547.       (dolist (m (cdr p))
  548.  
  549.         ;;Check first to be sure it should be defined
  550.  
  551.         (if (not (member m dont-define))
  552.  
  553.       (push
  554.             (build-inherited-method 
  555.               name 
  556.               m 
  557.               (class-name (car p)) 
  558.               parent-names 
  559.               slots
  560.             )
  561.             methcode
  562.           )
  563.  
  564.         )
  565.  
  566.       ) ;dolist
  567.     ) ;dolist
  568.  
  569.     methcode
  570.  
  571.   ) ;let
  572.  
  573. ) ;build-inherited-methods
  574.  
  575. ;;build-gs-methods-Build gettable and settable methods
  576.  
  577. (defun build-gs-methods (typename gettables settables dont-define parents slots)
  578.  
  579.   (let
  580.     (
  581.       (methcode NIL)
  582.       (kwp (find-package 'keyword))
  583.       (meth NIL)
  584.     )
  585.  
  586.     ;;First do gettables
  587.  
  588.     (dolist (g gettables)
  589.  
  590.       (setf meth (intern (symbol-name g) kwp))
  591.  
  592.       ;;Check first to be sure it must be defined
  593.  
  594.       (if (not (member meth dont-define))
  595.  
  596.         (push  
  597.           (build-get-method typename 
  598.                             meth
  599.                             g 
  600.                             parents 
  601.                             slots
  602.            )
  603.           methcode
  604.         )
  605.       )
  606.  
  607.  
  608.     ) ;dolist
  609.  
  610.     ;;Now do settables
  611.  
  612.     (dolist (s settables)
  613.  
  614.       (setf meth 
  615.             (intern (concatenate 'simple-string "SET-" (symbol-name s)) kwp)
  616.       )
  617.  
  618.       ;;Check first to be sure it must be defined
  619.  
  620.       (if (not (member s dont-define))
  621.         (push
  622.       (build-set-method 
  623.         typename 
  624.             meth 
  625.         s
  626.             parents
  627.             slots
  628.           )
  629.       methcode
  630.         )
  631.       )
  632.  
  633.     ) ;dolist
  634.  
  635.     methcode
  636.  
  637.   ) ;let
  638. ) ;end build-gs-methods  
  639.  
  640. ;;build-init-vars-method-Return code for the :INITIALIZE-VARIABLES
  641. ;;  method. Note that this must be a fully-blown CommonObjects
  642. ;;  method, because the users can put anthing they want into
  643. ;;  the initialization code, including CALL-METHOD.
  644.  
  645. (defun build-init-vars-method
  646.   (name initable-slots assignments)
  647.  
  648.   (let
  649.     (    
  650.       (form NIL)
  651.       (kwpak (find-package 'keyword))
  652.       (code NIL)
  653.     )
  654.  
  655.  
  656.     ;;This code is stolen from DEFINE-METHOD and is
  657.     ;;  inserted in line here so that, when it
  658.     ;;  gets returned to the top level, PCL::EXPAND-DEFMETH-INTERNAL
  659.     ;;  gets invoked while the DEFINE-TYPE macro is executing,
  660.     ;;  rather than at the top level, when the macro has
  661.     ;;  finished executing.
  662.  
  663.     (setf code
  664.       `(compiler-let
  665.         (
  666.           (*current-method-class-name* ',name)
  667.         )   
  668.  
  669.  
  670.         (let ((self (self-from-inner-self)))
  671.            (declare (optimize (speed 3) (safety 0)))
  672.  
  673.           (with*
  674.             (
  675.               (.inner-self. "" ,name)
  676.             )
  677.  
  678.             ,(if initable-slots
  679.  
  680.               `(do*
  681.                 (
  682.               (unprocessed-keys keylist (cddr unprocessed-keys))
  683.               (keyword (car unprocessed-keys) (car unprocessed-keys))
  684.               (value (cadr unprocessed-keys) (cadr unprocessed-keys))
  685.                 )
  686.                 ( (null unprocessed-keys) )
  687.                 (case keyword
  688.                 ,@(dolist (var initable-slots form)
  689.                   (push 
  690.                         `(
  691.                           (,(intern (symbol-name var) kwpak) ) 
  692.                           (setf ,var value)
  693.                         ) 
  694.                 form
  695.                       )
  696.                 )
  697.                   )
  698.               )
  699.  
  700.            ) ;if
  701.  
  702.             ,@assignments
  703.  
  704.           ) ;with*
  705.  
  706.       ) ;let
  707.       ) ;compiler-let
  708.     ) ;setf
  709.  
  710.     ;;Now define as a full blown CommonObjects method, with code
  711.     ;; walking and everything. Add in CALL-METHOD processing.
  712.  
  713.     `(progn
  714.  
  715.       ,(defcommon-objects-meth 
  716.         'keyword-standin::initialize-variables
  717.         `((.inner-self. ,name) &rest keylist)
  718.         code
  719.       )
  720.  
  721.      ) ;progn
  722.  
  723.    ) ;end let
  724.  
  725. ) ;end build-init-vars-method
  726.  
  727. ;;build-pcl-method-def-Build a PCL method definition without
  728. ;; all the overhead of code walking and method object creation
  729. ;; at compile time
  730.  
  731. (defun build-pcl-method-def (type method func-args code)
  732.  
  733.   (setf method
  734.         (if (keywordp method)
  735.             (keyword-standin method)
  736.             method
  737.         )
  738.   )
  739.  
  740.   (let*
  741.     (
  742.       (type-spec (list type))
  743.       (method-function-name (pcl::make-method-name method type-spec))
  744.     )
  745.  
  746.     ;;The extra list is so the forms get inserted at the
  747.     ;;  top level OK
  748.  
  749.    `(
  750.      (eval-when (compile load eval)
  751.        (pcl::record-definition 
  752.          ',method 'pcl::method ',type-spec NIL
  753.        )
  754.        (defun ,method-function-name ,func-args
  755.          (declare (optimize (speed 3) (safety 0)))
  756.     ,code
  757.        )
  758.      )
  759.  
  760.      ;;Note that this must be done at compile time
  761.      ;;  as well, since inherited methods must
  762.      ;;  be there for other types in the file
  763.  
  764.      (eval-when (compile load eval)
  765.        (let
  766.          (
  767.            (method 
  768.              (pcl::load-method-1
  769.                'pcl::discriminator
  770.                'common-objects-method
  771.                ',method
  772.                ',type-spec
  773.                ',func-args
  774.                NIL
  775.              )
  776.  
  777.            )
  778.  
  779.         )
  780.  
  781.         (setf (method-function method)
  782.               (symbol-function ',method-function-name)
  783.         )
  784.  
  785.         (add-method (discriminator-named ',method) method NIL)
  786.       )
  787.  
  788.     )
  789.  
  790.    )
  791.  
  792.   ) ;let*
  793.  
  794. ) ;build-pcl-method-def
  795.  
  796. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  797. ; Get/Set and Inherited Method Building Functions
  798. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  799.  
  800. ;;build-get-method-Build a gettable method
  801.  
  802. (defun build-get-method (name methname var parents slots)
  803.  
  804.   `(progn
  805.     ,@(build-pcl-method-def 
  806.       name 
  807.       methname 
  808.       '(.inner-self.) 
  809.       `(%instance-ref .inner-self. ,(calculate-slot-index var parents slots))
  810.     )
  811.   )
  812.  
  813. ) ;end build-get-method
  814.  
  815. ;;build-set-method-Build a settable method
  816.  
  817. (defun build-set-method (name methname var parents slots)
  818.  
  819.   `(progn
  820.     ,@(build-pcl-method-def 
  821.       name 
  822.       methname
  823.       '(.inner-self. .new-value.)
  824.       `(setf 
  825.         (%instance-ref .inner-self. ,(calculate-slot-index var parents slots))
  826.         .new-value.
  827.        )
  828.     )
  829.   )
  830.  
  831. ) ;end build-set-method
  832.  
  833. ;;build-inherited-method-Return code for an inherited method.
  834.  
  835. (defun build-inherited-method (name m p parents slots)
  836.  
  837.   ;;Now generate code
  838.  
  839.   `(progn
  840.     ,@(build-pcl-method-def
  841.         name
  842.         m
  843.         '(.inner-self. &rest .arg-list.)
  844.         `(apply
  845.         (symbol-function 
  846.               ',(generate-method-function-symbol
  847.                p m
  848.                 )
  849.         )
  850.             (%instance-ref
  851.           .inner-self.
  852.           ,(calculate-slot-index 
  853.             p
  854.             parents
  855.                 slots
  856.               )
  857.            )
  858.        .arg-list.
  859.  
  860.          )
  861.       )
  862.  
  863.   )
  864.  
  865. ) ;end build-inherited-method
  866.  
  867. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  868. ; Default Universal Methods
  869. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  870.  
  871. ;;define-universal-method-Macro to define universal methods. Note that
  872. ;;  DEFCOMMON-OBJECTS-METH could probably be used directly, but this
  873. ;;  tells what we're doing. We need a CommonObjects method here because
  874. ;;  we may need a symbol for CALL-METHOD
  875.  
  876. (defmacro define-universal-method (name arglist &body body)
  877.  
  878.    ;;Check for undefined type in body
  879.  
  880.     (setf body 
  881.       `(progn 
  882.         (if (eq (class-name (class-of ,(first (first arglist)))) 
  883.                 $UNDEFINED-TYPE-NAME
  884.             )
  885.              (no-matching-method (discriminator-named ',name))
  886.         )
  887.         ,@body
  888.       )
  889.     )
  890.  
  891.   (defcommon-objects-meth name arglist body)
  892.  
  893.  ) ;define-universal-method
  894.  
  895. ;;keyword-standin::init-Default :INIT method does nothing
  896.  
  897. (define-universal-method keyword-standin::init 
  898.   ((self common-objects-class) &rest keylist)
  899.  
  900.  
  901. ) ;keyword-standin::init
  902.  
  903. ;;keyword-standin::initialize-Default :INITIALIZE initializes
  904. ;;  parents, then variables
  905.  
  906. (define-universal-method keyword-standin::initialize 
  907.   ((self common-objects-class) &rest keylist)
  908.  
  909.     (let
  910.       (
  911.         (class (class-of self))
  912.       )
  913.  
  914.       (dolist (l (class-local-super-slot-names class))
  915.  
  916.         ;;GET-SLOT is inserted in-line here
  917.  
  918.         (apply 'keyword-standin::initialize 
  919.           (%instance-ref self (slot-index class l))
  920.           keylist
  921.         )
  922.       )
  923.  
  924.       ;;Now initialize variables
  925.  
  926.       (apply 'keyword-standin::initialize-variables self (car keylist))
  927.       (apply 'keyword-standin::init self (car keylist))
  928.  
  929.   ) ;let
  930.  
  931. ) ;keyword-standin::initialize
  932.  
  933. ;;print-instance-Print the instance
  934.  
  935. (define-universal-method print-instance
  936.   ((self common-objects-class) output-stream integer)
  937.  
  938.   (if (or (not integer) 
  939.           (not *print-level*) 
  940.           (< integer *print-level*)
  941.       )
  942.  
  943.       (pcl::printing-random-thing (self output-stream)
  944.     (format output-stream  "~A" (class-name (class-of self)))
  945.       )
  946.               
  947.   )
  948.  
  949. ) ;print-instance
  950.  
  951. ;;keyword-standin::describe-Default :DESCRIBE method
  952.  
  953. (define-universal-method keyword-standin::describe 
  954.   ((self common-objects-class) &optional describe-inner-loop)
  955.  
  956.   (let
  957.     (
  958.       (class (class-of self))
  959.     )
  960.  
  961.     (when (equal 
  962.             (class-name (class-of class))
  963.             'common-objects-class
  964.            )
  965.  
  966.       ;;Give name of this guy
  967.  
  968.       (if (not describe-inner-loop)
  969.         (format T 
  970.             "This object of type ~A has variables:~%" 
  971.             (class-name (class-of self))
  972.         )
  973.         (format T 
  974.                 "For parent ~A:~%"
  975.             (class-name (class-of self))
  976.         )
  977.       ) ;if
  978.  
  979.       ;;Now print instance variables
  980.  
  981.       (dolist (slot (class-user-visible-slots class))
  982.         (format T "    ~A: ~S~%" slot (get-slot-using-class class self slot))
  983.       )
  984.  
  985.       ;;Now print for parents
  986.  
  987.       (dolist (lss (class-local-super-slot-names class))
  988.         (keyword-standin::describe (get-slot-using-class class self lss) T)
  989.       )
  990.  
  991.     ) ;when
  992.  
  993.   ) ;let
  994.  
  995. ) ;keyword-standin::describe
  996.  
  997. ;;keyword-standin::eql-Default :EQL predicate method
  998.  
  999. (define-universal-method keyword-standin::eql 
  1000.   ((self common-objects-class) .any.)
  1001.  
  1002.       (eq self .any.)
  1003.  
  1004. ) ;keyword-standin::eql
  1005.  
  1006. ;;keyword-standin::equal-Default :EQUAL predicate method
  1007.                                              
  1008. (define-universal-method keyword-standin::equal 
  1009.   ((self common-objects-class) .any.)
  1010.  
  1011.    (keyword-standin::eql self .any.)
  1012.  
  1013. ) ;keyword-standin::equal
  1014.  
  1015. ;;keyword-standin::equalp-Default :EQUALP predicate method
  1016.  
  1017. (define-universal-method keyword-standin::equalp 
  1018.   ((self common-objects-class) .any.)
  1019.  
  1020.   (keyword-standin::equal self .any.)
  1021.  
  1022. ) ;keyword-standin::equalp
  1023.  
  1024. ;;keyword-standin::typep-Default :TYPEP predicate method
  1025.  
  1026. (define-universal-method keyword-standin::typep 
  1027.   ((self common-objects-class) .any.)
  1028.  
  1029.   (or (equal (class-name (class-of self)) .any.)
  1030.       (eq .any. 'instance)
  1031.       (eq .any. 't)
  1032.   )
  1033.  
  1034. ) ;keyword-standin::typep
  1035.  
  1036. ;;keyword-standin::copy-Default :COPY method 
  1037.  
  1038. (define-universal-method keyword-standin::copy 
  1039.   ((self common-objects-class))
  1040.  
  1041.       self
  1042.  
  1043. ) ;keyword-standin::copy
  1044.  
  1045. ;;keyword-standin::copy-instance-Default :COPY-INSTANCE method
  1046.  
  1047. (define-universal-method keyword-standin::copy-instance 
  1048.   ((self common-objects-class))
  1049.  
  1050.   (let
  1051.     (
  1052.       (class (class-of self))
  1053.       (inst NIL)
  1054.     )
  1055.  
  1056.     (when (equal 
  1057.             (class-name (class-of class))
  1058.             'common-objects-class
  1059.            )
  1060.  
  1061.       (setf inst (make-instance (class-name class)))
  1062.  
  1063.       ;Copy state from inner-self to instance
  1064.  
  1065.       (co::set-slot-values self inst class)
  1066.  
  1067.       inst
  1068.    ) ;when
  1069.  
  1070.   ) ;let
  1071.  
  1072. ) ;keyword-standin::copy-instance
  1073.  
  1074. ;;keyword-standin::copy-state-Default :COPY-STATE method
  1075.  
  1076. (define-universal-method keyword-standin::copy-state 
  1077.   ((self common-objects-class))
  1078.  
  1079.       self
  1080.  
  1081. ) ;keyword-standin::copy-state
  1082.  
  1083. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1084. ;  Support Methods and Functions for Universal Methods
  1085. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1086.  
  1087. ;;set-slot-values-Set the slot values in OBJECT to those in .INNER-SELF.
  1088.  
  1089. (defmeth set-slot-values (.inner-self. object class)
  1090.  
  1091.   ;;Set in this guy
  1092.  
  1093.   (dolist (slot (class-user-visible-slots class))
  1094.     (setf (get-slot object slot) (get-slot .inner-self. slot))
  1095.   )
  1096.  
  1097.   ;;Now set in parents
  1098.  
  1099.   (dolist (lss (class-local-super-slot-names class))
  1100.       (set-slot-values 
  1101.     (get-slot .inner-self. lss) 
  1102.     (get-slot object lss) 
  1103.     (class-of (get-slot .inner-self. lss))
  1104.       )
  1105.   )
  1106.  
  1107. ) ;end set-slot-values
  1108.  
  1109. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1110. ;  Renaming and Undefining Types and Methods
  1111. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1112.  
  1113. ;;rename-type-Rename type1 to type2
  1114.  
  1115. (defun rename-type (type1 type2)
  1116.   (declare (type symbol type1 type2))
  1117.  
  1118.   (let
  1119.     (
  1120.       (class (class-named type1 T))
  1121.       (newclass (class-named type2 T))
  1122.     )
  1123.  
  1124.     ;;Signal an error for special cases
  1125.  
  1126.     (when (or (null type2) (eq type2 't))
  1127.       (error "RENAME-TYPE: New name cannot be NIL or T.~%")
  1128.     )
  1129.  
  1130.     ;;Signal an error when arguments aren't symbols
  1131.  
  1132.     (when (or (not (symbolp type1)) (not (symbolp type2)))
  1133.       (error "RENAME-TYPE: Arguments must be symbols.~%")
  1134.     )
  1135.  
  1136.     ;;Signal error if TYPE2 already exists
  1137.  
  1138.     (when newclass
  1139.       (error "RENAME-TYPE: Type ~S already exists.~%" type2)
  1140.     )
  1141.  
  1142.     ;;Signal an error if class isn't CommonObjects class
  1143.  
  1144.     (when (not (eq (class-name (class-of class)) 'common-objects-class))
  1145.       (error "RENAME-TYPE: Can't rename a built-in type or nonCommonObjects class ~S.~%" type1)
  1146.     )
  1147.  
  1148.     ;;Signal an error if the class is not defined
  1149.  
  1150.     (if class
  1151.       (progn
  1152.     (rename-class class type2)
  1153.         type2
  1154.  
  1155.       ) ;progn
  1156.       (error "RENAME-TYPE: The type ~S is not defined.~%" type1)
  1157.     ) ;if
  1158.  
  1159.   ) ;let
  1160.  
  1161. ) ;end rename-type
  1162.  
  1163. ;;undefine-type-Undefine type typename
  1164.  
  1165. (defun undefine-type (typename)
  1166.   (declare (type symbol typename))
  1167.  
  1168.   ;;Check if typename is a symbol
  1169.  
  1170.   (when (not (symbolp typename))
  1171.     (error "UNDEFINE-TYPE: Argument must be a symbol.~%")
  1172.   )
  1173.  
  1174.   (let
  1175.     (
  1176.      (class (class-named typename T))
  1177.     )
  1178.  
  1179.     (if (and class (eq (class-name (class-of class)) 'common-objects-class))
  1180.      (progn
  1181.  
  1182.         ;;Undefine all the methods first
  1183.  
  1184.         (undefine-methods class)
  1185.  
  1186.         ;;Now set the class name
  1187.  
  1188.         (setf (class-name class) $UNDEFINED-TYPE-NAME)
  1189.     (setf (class-named typename) NIL)
  1190.         T
  1191.       ) ;progn
  1192.  
  1193.       NIL
  1194.  
  1195.     ) ;if
  1196.  
  1197.   ) ;let
  1198.  
  1199. ) ;end undefine-type
  1200.  
  1201. ;;undefine-methods-Undefine all the methods on class
  1202.  
  1203. (defun undefine-methods (class)
  1204.  
  1205.   (dolist (meth (class-direct-methods class))
  1206.  
  1207.     ;;Remove the method from the discriminator
  1208.  
  1209.     (remove-method (method-discriminator meth) meth)
  1210.  
  1211.     ;;Now unbind the symbol cell, so call-methods don't work
  1212.  
  1213.     (fmakunbound (method-function-symbol meth))
  1214.   )
  1215.  
  1216. ) ;undefine-methods
  1217.  
  1218. ;;undefine-method-Use PCL remove-method to get
  1219. ;;  rid of method.
  1220.  
  1221. (defun undefine-method (typename operation)
  1222.   (declare (type symbol typename operation))
  1223.  
  1224.   ;;Check if the arguments are symbols
  1225.  
  1226.   (when (not (symbolp typename)) 
  1227.     (error "UNDEFINE-METHOD: Type name must be a symbol.~%")
  1228.   )
  1229.  
  1230.   ;;If the operation is not a symbol, just return.
  1231.  
  1232.   (when (not (symbolp operation))
  1233.     (return-from undefine-method NIL)
  1234.   )
  1235.  
  1236.   (let*
  1237.     (
  1238.  
  1239.       ;;The class object
  1240.  
  1241.       (class (class-named typename))
  1242.  
  1243.       ;;The operation
  1244.  
  1245.       (opname (if (keywordp operation)
  1246.                 (keyword-standin operation)
  1247.                 operation
  1248.               )
  1249.       )
  1250.  
  1251.       ;;The discriminator (if any)
  1252.  
  1253.       (disc (discriminator-named opname))
  1254.  
  1255.       ;;The method (if any)
  1256.  
  1257.       (meth 
  1258.         (if disc
  1259.           (find-method disc (list typename) NIL T)
  1260.         )
  1261.       )
  1262.  
  1263.     )
  1264.  
  1265.  
  1266.     ;;Check if the class is a CommonObjects class
  1267.  
  1268.     (when (not (eq (class-name (class-of class)) 'common-objects-class))
  1269.       (error "UNDEFINE-TYPE: Tried to undefine ~S ~  
  1270.               which is not a CommonObjects class.~%"
  1271.               typename
  1272.       )
  1273.     )
  1274.  
  1275.     ;;Check if the method is a universal method and there
  1276.     ;; is no type specific method. Warn the user.
  1277.  
  1278.     (when (and 
  1279.             (null meth) 
  1280.             (member operation *universal-methods* :test #'eq)
  1281.           )
  1282.       (warn
  1283.         (format 
  1284.           NIL
  1285.           "UNDEFINE-TYPod NIL)
  1286.   )
  1287.  
  1288.   (let*
  1289.     (
  1290.  
  1291.       ;;The class ob% which cannot be undefined."
  1292.       typename
  1293.           operation
  1294.         )
  1295.       )
  1296.       (return-from undefine-method NIL)
  1297.     )            
  1298.  
  1299.     ;;If a method was found, undefine it
  1300.  
  1301.     (if (and meth disc)
  1302.       (progn
  1303.     (remove-method disc meth)
  1304.  
  1305.         ;;Now unbind the symbol cell, so CALL-METHODs don't work
  1306.  
  1307.     (fmakunbound (method-function-symbol meth))
  1308.  
  1309.         ;;Remove the symbol from the package, so that future
  1310.     ;;  attempts to create CALL-METHODs can't find it.
  1311.     ;;  But hopefully, existing CALL-METHODs will still
  1312.         ;;  work.
  1313.  
  1314.         (unintern (method-function-symbol meth) 
  1315.            (symbol-package (method-function-symbol meth))
  1316.         )
  1317.  
  1318.         T
  1319.       ) ;progn
  1320.  
  1321.       NIL
  1322.  
  1323.     ) ;if
  1324.  
  1325.   ) ;let
  1326.  
  1327. ) ;end undefine-method
  1328.  
  1329. ;;assignedp-Indicate whether or not an instance variable is
  1330. ;;  assigned
  1331.  
  1332. (defmacro assignedp (var)
  1333.  
  1334.   (declare (special co::*current-method-class-name*))
  1335.  
  1336.   ;;Check for attempt to access outside of a method
  1337.  
  1338.   (if (null (boundp 'co::*current-method-class-name*))
  1339.     (error "DEFINE-METHOD: Attempt to use assignedp outside of a method.~%")
  1340.   )
  1341.  
  1342.   ;;Check for attempt to use on something other than an instance variable
  1343.  
  1344.   (unless (has-slot-p (class-named *current-method-class-name*) var)
  1345.     (error "DEFINE-METHOD: Argument ~S to assignedp ~
  1346.            must be an instance variable name.~%" 
  1347.            var
  1348.      )
  1349.   )
  1350.  
  1351.   `(not (equal ,var ',$UNINITIALIZED-VARIABLE-FLAG))
  1352.     
  1353. ) ;;end assignedp
  1354.  
  1355. ;;instancep-Return T if this thing is an instance and has a CommonObjects
  1356. ;;  class
  1357.  
  1358. (defun instancep (thing)
  1359.  
  1360.   ;;Check first if thing is NIL
  1361.  
  1362.   (if (not thing)
  1363.     NIL
  1364.     (eq (class-name (class-of (class-of thing))) 'common-objects-class)
  1365.   )
  1366.  
  1367.  
  1368. ) ;end instancep
  1369.  
  1370. ;;supports-operation-p-Return T if method operation METH is supported on type
  1371. ;;  of OBJ
  1372.  
  1373. (defun supports-operation-p (obj meth)
  1374.   (declare (special *universal-methods*))
  1375.  
  1376.   (let
  1377.     (
  1378.       (class (if obj (class-of obj) obj))
  1379.     )
  1380.  
  1381.     ;;If not a CommonObjects class, then return NIL
  1382.  
  1383.     (when (or (not class) 
  1384.               (not (eq (class-name (class-of class)) 'common-objects-class))
  1385.           )
  1386.       (return-from supports-operation-p NIL)
  1387.     )
  1388.  
  1389.     ;;Check first if its a universal method
  1390.  
  1391.     (if (member meth *universal-methods*)
  1392.  
  1393.       T
  1394.  
  1395.       ;;Otherwise, check in the class object if it's got them
  1396.  
  1397.       (dolist (methobj (class-direct-methods class))
  1398.  
  1399.         (when (eq (unkeyword-standin (method-name methobj)) meth)
  1400.           (return-from supports-operation-p T)
  1401.         )
  1402.  
  1403.       ) ;dolist
  1404.  
  1405.     ) ;if
  1406.  
  1407.   ) ;let
  1408.  
  1409. ) ;end supports-operation-p
  1410.  
  1411. ;;Define the instance type
  1412.  
  1413. (deftype instance ()
  1414.   (list 'apply 'instancep)
  1415.  
  1416. ) ;end deftype
  1417.  
  1418.  
  1419.  
  1420. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1421. ;  Make-Instance
  1422. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1423.  
  1424. ;;make-instance-Make an instance given the CommonObjects type name
  1425.  
  1426. (defmeth make-instance ((class-name symbol) &rest keylist)
  1427.  
  1428.     ;;Check if the key list and class are OK.
  1429.  
  1430.     (if (null (listp keylist))
  1431.       (error "Make-instance requires a list for the keyword list.~%")
  1432.     )
  1433.  
  1434.     (if (null (class-named class-name T))
  1435.       (error "~S is not a defined type.~%" class-name)
  1436.     )
  1437.  
  1438.    (make-instance (class-named class-name) keylist)
  1439.  
  1440. ) ;end make-instance
  1441.  
  1442. ;;make-instance-Make an instance given the CommonObjects class object
  1443.  
  1444. (defmeth make-instance ((class common-objects-class) &rest keylist)
  1445.   (declare (special *outer-self*))
  1446.   
  1447.   (let*
  1448.     (
  1449.       (instance NIL)
  1450.       (numslots (length (class-user-visible-slots class)))
  1451.       (start-slots 
  1452.     (+ $START-OF-PARENTS (length (class-local-supers class)))
  1453.       )
  1454.     )
  1455.       (let 
  1456.     (
  1457.           (*outer-self* (and (boundp '*outer-self*) *outer-self*))
  1458.         )
  1459.         (declare (special *outer-self*))
  1460.  
  1461.         (setf instance (%make-instance (class-of class)
  1462.                        (+ 2 (class-instance-size class))
  1463.                        )
  1464.         )
  1465.         (setf (%instance-ref instance $CLASS-OBJECT-INDEX) class
  1466.           (%instance-ref instance $SELF-INDEX) (or *outer-self*
  1467.                                     (setq *outer-self* instance)
  1468.                             )
  1469.         )
  1470.  
  1471.         ;;Initialize the slots with the uninitialized flag
  1472.  
  1473.         (dotimes (i numslots)
  1474.           (setf 
  1475.         (%instance-ref instance (+ i start-slots))
  1476.             $UNINITIALIZED-VARIABLE-FLAG
  1477.           )
  1478.         )
  1479.  
  1480.         ;;Now go through and make parent objects
  1481.  
  1482.         (do 
  1483.           (
  1484.             (supers (class-local-supers class) (cdr supers))
  1485.         (index $START-OF-PARENTS (1+ index))
  1486.           )
  1487.       ((null supers))
  1488.       (setf (%instance-ref instance index)
  1489.             (make-instance (car supers) (car keylist))
  1490.           )
  1491.         ) ;do
  1492.  
  1493.     ) ;end let for dynamic binding
  1494.  
  1495.     ;;Check initialization keywords and initialize, but only if
  1496.     ;;  creating outer self object.
  1497.  
  1498.     (when (not (boundp '*outer-self*))
  1499.  
  1500.       ;;If keyword check needed, then check keyword list
  1501.  
  1502.       (if (class-init-keywords-check class)
  1503.         (check-init-keywords class keylist)
  1504.       )
  1505.       ;;Now initialize, if doing outer self.
  1506.  
  1507.       (keyword-standin::initialize instance (car keylist))
  1508.  
  1509.     ) ;when
  1510.  
  1511.     instance
  1512.  
  1513.   ) ;end let for lexical binding
  1514.  
  1515. ) ;end make-instance
  1516.  
  1517.