## 6.26 Unit: tinyclos

This unit is a port of Gregor Kiczales TinyCLOS with numerous modifications.

This unit uses the `extras` unit.

### 6.26.1 Defining forms

[syntax] (define-class NAME (SUPERCLASS1 ...) (SLOTNAME1 ...) [METACLASS])
  Sets the variable `NAME` to a new class (a new instance of the class `<class>`). `SUPERCLASS1 ...` is a list of superclasses of the newly created class. If no superclasses are given, then `<object>` is assumed. `SLOTNAME1 ...` are the names of the direct slots of the class. if `METACLASS` is provided, then the new class-instance is an instance of `METACLASS` instead of `<class>`.

      (define-class NAME (SUPER) (SLOT1 SLOT2) META)

  is equivalent to

      (define NAME
        (make META
          'name 'NAME
          'direct-supers (list SUPER)
          'direct-slots (list 'SLOT1 'SLOT2)) )

  Note that slots-names are not required to be symbols, so the following is perfectly valid:

      (define hidden-slot (list 'hidden))
      (define <myclass>
        (make <class>
           'direct-supers (list <object>)
           'direct-slots (list hidden-slot) ) )
      (define x1 (make <myclass>)
      (slot-set! x1 hidden-slot 99)

[syntax] (define-generic NAME)
  Sets the variable `NAME` to contain a fresh generic function object without associated methods.

[syntax] (define-method (NAME (VARIABLE1 CLASS1) ... PARAMETERS ...) BODY ...)
  Adds a new method with the code `BODY ...` to the generic function that was assigned to the variable `name`. `CLASS1 ...` is a list if classes that specialize this particular method. The method can have additional parameters `PARAMETERS`, which do not specialize the method any further. Inside the body of the method the identifier `call-next-method` names a procedure of zero arguments that can be invoked to call the next applicable method with the same arguments. If no generic function is defined under this name, then a fresh generic function object is created and assigned to `NAME`.

### 6.26.2 Base language

[procedure] (add-method GENERIC METHOD)
  Adds the method object `METHOD` to the list of applicable methods for the generic function `GENERIC`.

[procedure] (instance? X)
  Returns `#t` if `X` is an instance of a non-primitive class.

[procedure] (make CLASS INITARG ...)
  Creates a new instance of `CLASS` and passes `INITARG ...` to the `initialize` method of this class.

[procedure] (make-class SUPERCLASSES SLOTNAMES)
  Creates a new class object, where `SUPERCLASSES` should be the list of direct superclass objects and `SLOTNAMES` should be a list of symbols naming the slots of this class.

[procedure] (make-generic [NAME])
  Creates a new generic function object. If `NAME` is specified, then it should be a string.

[procedure] (make-method SPECIALIZERS PROC)
  Creates a new method object specialized to the list of classes in `SPECIALIZERS`.

      (define-method (foo (<bar> x)) 123)
         <=> (add-method foo (make-method (list <bar>) (lambda (call-next-method x) 123)))

[procedure] (slot-ref INSTANCE SLOTNAME)
  Returns the value of the slot `SLOTNAME` of the object `INSTANCE`.

[procedure] (slot-set! INSTANCE SLOTNAME VALUE)
  Sets the value of the slot `SLOTNAME` of the object `INSTANCE` to `VALUE`.

### 6.26.3 Introspection

[procedure] (class-cpl CLASS)
  Returns the class-precedence-list of `CLASS` as a list of classes.

[procedure] (class-direct-slots CLASS)
  Returns the list of direct slots of `CLASS` as a list of lists, where each sublist contains the name of the slot.

[procedure] (class-direct-supers CLASS)
  Returns the list of direct superclasses of `CLASS`.

[procedure] (class-of X)
  Returns the class that the object `X` is an instance of.

[procedure] (class-name CLASS)
  Returns name of `CLASS`.

[procedure] (class-slots CLASS)
  Returns the list of all slots of `CLASS` and it's superclasses as a list of lists, where each sublist contains the name of the slot.

[procedure] (generic-methods GENERIC)
  Returns the list of all methods associated with the generic function `GENERIC`.

[procedure] (method-specializers METHOD)
  Returns the list of classes that specialize `METHOD`.

[procedure] (method-procedure METHOD)
  Returns the procedure that contains the body of `METHOD`.

[procedure] (subclass? CLASS1 CLASS2)
  Returns `#t` is `CLASS1` is a subclass of `CLASS2`, or `#f` otherwise. Note that the following holds:

      (subclass? X X) ==> #t

### 6.26.4 Intercessory protocol

[generic] (allocate-instance CLASS)
  Allocates storage for an instance of `CLASS` and returns the instance.

[generic] (compute-apply-generic GENERIC)
[generic] (compute-apply-methods GENERIC)
[generic] (compute-methods GENERIC)
  These are used to compute the actual methods to be called on the invocation of the generic function `GENERIC`.

[generic] (compute-cpl CLASS)
  Computes and returns the class-precedence-list of `CLASS`.

[generic] (compute-getter-and-setter CLASS SLOT ALLOCATOR)
  Returns two values, the procedures that get and set the contents of the slot `SLOT`. `ALLOCATOR` is a procedure of one argument (I currently don't know what it does).

[generic] (compute-method-more-specific? GENERIC)
  Returns a procedure of three arguments (two methods and a list of arguments) that returns `#t` if the first method is more specific than the second one with respect to the list of arguments. Otherwise the returned predicate returns `#f`.

[generic] (compute-slots CLASS)
  Computes and returns the list of slots of `CLASS`.

[generic] (initialize INSTANCE INITARGS)
  Initializes the object `INSTANCE`. `INITARGS` is the list of initialization arguments that were passed to the `make` procedure.

### 6.26.5 Additional protocol

[generic] (describe-object INSTANCE PORT)
  Writes a description of `INSTANCE` to `PORT`. Execution of the interpreter command `,d` will invoke this generic function.

[generic] (print-object INSTANCE PORT)
  Writes a textual representation of `INSTANCE` to `PORT`. Any output of an instance with `display, write` and `print` will invoke this generic function.

### 6.26.6 Utility procedures

[procedure] (initialize-slots INSTANCE INITARGS)
  This procedure takes a sequence of alternating slot-names and initialization values in `INITARGS` and initializes the corresponding slots in `INSTANCE`.

      (define-class <pos> () (x y))

      (define-method (initialize (<pos> pos) initargs)
        (call-next-method)
        (initialize-slots pos initargs))

      (define p1 (make <pos> 'x 1 'y 2))
      (define p2 (make <pos> 'x 3 'y 5))

### 6.26.7 Builtin classes

The class hierarchy of builtin classes looks like this:

    <top>
      <object>
        <class>
          <procedure-class>
            <procedure>
            <entity-class>
              <generic>
          <primitive-class>
      <primitive>
        <void>
        <boolean>
        <symbol>
        <char>
        <vector>
        <pair>
        <number>
          <exact>
          <inexact>
        <string>
        <port>
          <input-port>
          <output-port>
        <pointer>
          <tagged-pointer>
        <locative>
        <byte-vector>
          <u8vector>
          <s8vector>
          <u16vector>
          <s16vector>
          <u32vector>
          <s32vector>
          <f32vector>
          <f64vector>
        <structure>
          <array>
          <char-set>
          <condition>
          <environment>
          <hash-table>
          <lock>
          <mmap>
          <promise>
          <queue>
          <tcp-listener>
          <time>
        <end-of-file>

[class] <primitive> -> <top>
  The parent class of the classes of all primitive Scheme objects.

[class] <boolean> -> <primitive>
[class] <symbol> -> <primitive>
[class] <char> -> <primitive>
[class] <vector> -> <primitive>
[class] <null> -> <primitive>
[class] <pair> -> <primitive>
[class] <number> -> <primitive>
[class] <exact> -> <number>
[class] <inexact> -> <number>
[class] <string> -> <primitive>
[class] <port> -> <primitive>
[class] <environment> -> <structure>
[class] <end-of-file> -> <primitive>
[class] <input-port> -> <port>
[class] <output-port> -> <port>
[class] <procedure> -> <procedure-class>
  The classes of primitive Scheme objects.

[class] <byte-vector> -> <primitive>
[class] <structure> -> <primitive>
[class] <hash-table> -> <structure>
[class] <queue> -> <structure>
  The classes of extended data types provided by the various library units.

[class] <class> -> <object>
  The parent class of all class objects.

[class] <entity-class> -> <class>
  The parent class of objects that can be invoked as a procedure and have slots.

[class] <generic> -> <entity-class>
  The parent class of generic function objects.

[class] <method> -> <class>
  The parent class of method objects.

[class] <object> -> <class>
  The parent class of all objects.

[class] <procedure-class> -> <class>
  The parent class of objects that can be invoked as a procedure.

[class] <condition> -> <structure>
  Class of condition objects.

[class] <array> -> <structure>
[class] <char-set> -> <structure>
[class] <time> -> <structure>
[class] <u8vector> -> <byte-vector>
[class] <s8vector> -> <byte-vector>
[class] <u16vector> -> <byte-vector>
[class] <s16vector> -> <byte-vector>
[class] <u32vector> -> <byte-vector>
[class] <s32vector> -> <byte-vector>
[class] <f32vector> -> <byte-vector>
[class] <f64vector> -> <byte-vector>
  The classes of data objects provided by the various supported SRFIs.

[class] <lock> -> <structure>
[class] <mmap> -> <structure>
  Classes of objects used in the `posix` library unit.

[class] <pointer> -> <primitive>
[class] <tagged-pointer> -> <pointer>
  A machine pointer (untagged, or tagged).

[class] <locative> -> <primitive>
  A locative.

[class] <promise> -> <structure>
  The class of objects returned by `delay`.

[class] <tcp-listener> -> <structure>
  The class of an object returned by `tcp-listen`.