From 71efc5247bf809b4941b88e3b3182e181e6a20ab Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 27 Jul 2019 14:44:43 +0100 Subject: [PATCH] doc/concepts.tex: Start work on documenting metaclasses. --- doc/concepts.tex | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/doc/concepts.tex b/doc/concepts.tex index 2e3bead..b452f3c 100644 --- a/doc/concepts.tex +++ b/doc/concepts.tex @@ -1126,6 +1126,111 @@ determined using the \descref{SOD_INSTBASE}[macro]{mac}. %%%-------------------------------------------------------------------------- \section{Metaclasses} \label{sec:concepts.metaclasses} +In Sod, every object is an instance of some class, and -- unlike, say, +\Cplusplus\ -- classes are proper objects. It follows that, in Sod, every +class~$C$ is itself an instance of some class~$M$, which is called $C$'s +\emph{metaclass}. Metaclass instances are usually constructed statically, at +compile time, and marked read-only. + +As an added complication, Sod classes, and other metaobjects such as +messages, methods, slots and so on, also have classes \emph{at translation +time}. These translation-time metaclasses are not Sod classes; they are CLOS +classes, implemented in Common Lisp. + + +\subsection{Runtime metaclasses} +\label{sec:concepts.metaclasses.runtime} + +Like other classes, metaclasses can declare messages, and define slots and +methods. Slots defined by the metaclass are called \emph{class slots}, as +opposed to \emph{instance slots}. Similarly, messages and methods defined by +the metaclass are termed \emph{class messages} and \emph{class methods} +respectively, though these are used much less frequently. + +\subsubsection{The braid} +Every object is an instance of some class. There are only finitely many +classes. + +\begin{figure} + \centering + \begin{tikzpicture} + \node[lit] (obj) {SodObject}; + \node[lit] (cls) [right=10mm of obj] {SodClass}; + \draw [->, dashed] (obj) to[bend right] (cls); + \draw [->] (cls) to[bend right] (obj); + \draw [->, dashed] (cls) to[loop right] (cls); + \end{tikzpicture} + \qquad + \fbox{\ \begin{tikzpicture} + \node (subclass) {subclass of}; + \node (instance) [below=\jot of subclass] {instance of}; + \draw [->] ($(subclass.west) - (10mm, 0)$) -- ++(8mm, 0); + \draw [->, dashed] ($(instance.west) - (10mm, 0)$) -- ++(8mm, 0); + \end{tikzpicture}} + \caption{The Sod braid} \label{fig:concepts.metaclasses.braid} +\end{figure} + +Consider the directed graph whose nodes are classes, and where there is an +arc from $C$ to $D$ if and only if $C$ is an instance of $D$. There are only +finitely many nodes. Every node has an arc leaving it, because every object +-- and hence every class -- is an instance of some class. Therefore this +graph must contain at least one cycle. + +In Sod, this situation is resolved in the simplest manner possible: +@|SodClass| is the only predefined metaclass, and it is an instance of +itself. The only other predefined class is @|SodObject|, which is also an +instance of @|SodClass|. There is exactly one root class, namely +@|SodObject|; consequently, @|SodClass| is a direct subclass of @|SodObject|. + +\Xref{fig:concepts.metaclasses.braid} shows a diagram of this situation. + +\subsubsection{Class slots and initializers} +Instance initializers were described in \xref{sec:concepts.classes.slots}. A +class can also define \emph{class initializers}, which provide values for +slots defined by its metaclass. The initial value for a class slot is +determined as follows. +\begin{itemize} +\item Nonstandard slot classes may be initialized by custom Lisp code. For + example, all of the slots defined by @|SodClass| are of this kind. User + initializers are not permitted for such slots. +\item If the class or any of its superclasses defines a class initializer for + the slot, then the class initializer defined by the most specific such + superclass is used. +\item Otherwise, if the metaclass or one of its superclasses defines an + instance initializer, then the instance initializer defined by he most + specific such class is used. +\item Otherwise there is no initializer, and an error will be reported. +\end{itemize} +Initializers for class slots must be constant expressions (for scalar slots) +or aggregate initializers containing constant expressions. + +\subsubsection{Metaclass selection and consistency} +Sod enforces a \emph{metaclass consistency rule}: if $C$ has metaclass $M$, +then any subclass $C$ must have a metaclass which is a subclass of $M$. + +The definition of a new class can name the new class's metaclass explicitly, +by defining a @|metaclass| property; the Sod translator will verify that the +choice of metaclass is acceptable. + +If no @|metaclass| property is given, then the translator will select a +default metaclass as follows. Let $C_1$, $C_2$, \dots, $C_n$ be the direct +superclasses of the new class, and let $M_1$, $M_2$, \dots, $M_n$ be their +respective metaclasses (not necessarily distinct). If there exists exactly +one minimal metaclass $M_i$, i.e., there exists an $i$, with $1 \le i \le n$, +such that $M_i$ is a subclass of every $M_j$, for $1 \le j \le n$, then $M_i$ +is selected as the new class's metaclass. Otherwise the situation is +ambiguous and an error will be reported. Usually, the ambiguity can be +resolved satisfactorily by defining a new class $M^*$ as a direct subclass of +the minimal $M_j$. + + +\subsection{Translation-time metaobjects} +\label{sec:concepts.metaclasses.compile-time} + + + +\fixme{unwritten} + %%%-------------------------------------------------------------------------- \section{Compatibility considerations} \label{sec:concepts.compatibility} -- 2.11.0