chiark / gitweb /
doc/refintro.tex: Introduction to reference section.
[sod] / doc / concepts.tex
index 8151014cdd0ed369688f4cf1a664a034bf4bb5c0..84e4062a512f8001529d05289d551f89898f40b1 100644 (file)
 
 \chapter{Concepts} \label{ch:concepts}
 
-%%%--------------------------------------------------------------------------
-\section{Operational model} \label{sec:concepts.model}
-
-The Sod translator runs as a preprocessor, similar in nature to the
-traditional Unix \man{lex}{1} and \man{yacc}{1} tools.  The translator reads
-a \emph{module} file containing class definitions and other information, and
-writes C~source and header files.  The source files contain function
-definitions and static tables which are fed directly to a C~compiler; the
-header files contain declarations for functions and data structures, and are
-included by source files -- whether hand-written or generated by Sod -- which
-makes use of the classes defined in the module.
-
-Sod is not like \Cplusplus: it makes no attempt to `enhance' the C language
-itself.  Sod module files describe classes, messages, methods, slots, and
-other kinds of object-system things, and some of these descriptions need to
-contain C code fragments, but this code is entirely uninterpreted by the Sod
-translator.\footnote{%
-  As long as a code fragment broadly follows C's lexical rules, and properly
-  matches parentheses, brackets, and braces, the Sod translator will copy it
-  into its output unchanged.  It might, in fact, be some other kind of C-like
-  language, such as Objective~C or \Cplusplus.  Or maybe even
-  Objective~\Cplusplus, because if having an object system is good, then
-  having three must be really awesome.} %
-
-The Sod translator is not a closed system.  It is written in Common Lisp, and
-can load extension modules which add new input syntax, output formats, or
-altered behaviour.  The interface for writing such extensions is described in
-\xref{p:lisp}.  Extensions can change almost all details of the Sod object
-system, so the material in this manual must be read with this in mind: this
-manual describes the base system as provided in the distribution.
-
 %%%--------------------------------------------------------------------------
 \section{Modules} \label{sec:concepts.modules}
 
@@ -704,7 +673,7 @@ the platform's strictest alignment requirement applies.
 The following simple function correctly allocates and returns space for an
 instance of a class given a pointer to its class object @<cls>.
 \begin{prog}
-  void *allocate_instance(const SodClass *cls) \\ \ind
+  void *allocate_instance(const SodClass *cls)                  \\ \ind
     \{ return malloc(cls@->cls.initsz); \}
 \end{prog}
 
@@ -728,7 +697,7 @@ of any use unless they've been written specifically for the purpose.
 The following simple function imprints storage at address @<p> as an instance
 of a class, given a pointer to its class object @<cls>.
 \begin{prog}
-  void imprint_instance(const SodClass *cls, void *p) \\ \ind
+  void imprint_instance(const SodClass *cls, void *p)           \\ \ind
     \{ cls@->cls.imprint(p); \}
 \end{prog}
 
@@ -745,11 +714,10 @@ Initialization is performed by sending the imprinted instance an @|init|
 message, defined by the @|SodObject| class.  This message uses a nonstandard
 method combination which works like the standard combination, except that the
 \emph{default behaviour}, if there is no overriding method, is to initialize
-the instance's slots using the initializers defined in the class and its
-superclasses, and to invoke each superclass's initialization fragments.  This
-default behaviour may be invoked multiple times if some method calls on its
-@|next_method| more than once, unless some other method takes steps to
-prevent this.
+the instance's slots, as described below, and to invoke each superclass's
+initialization fragments.  This default behaviour may be invoked multiple
+times if some method calls on its @|next_method| more than once, unless some
+other method takes steps to prevent this.
 
 Slots are initialized in a well-defined order.
 \begin{itemize}
@@ -771,19 +739,53 @@ definition.  It is possible for an initialization fragment to use @|return|
 or @|goto| for special control-flow effects, but this is not likely to be a
 good idea.
 
-Note that an initialization fragment defined in a class is copied literally
-into each subclass's initialization method.  This is fine for simple cases
-but wasteful if the initialization logic is complicated.  More complex
-initialization behaviour should be added either by having an initialization
-fragments call functions (necessarily with external linkage), or by defining
-@|after| methods on the @|init| message.  These will be run after the slot
-initializers have been applied, in reverse precedence order.
-
-Initialization is \emph{parametrized}, so the caller may select from a space
-of possible initial states for the new instance, or to inform the new
-instance about some other objects known to the caller.  Specifically, the
-@|init| message accepts keyword arguments (\xref{sec:concepts.keywords})
-which can be defined and used by methods defined on it.
+The @|init| message accepts keyword arguments
+(\xref{sec:concepts.methods.keywords}).  The set of acceptable keywords is
+determined by the applicable methods as usual, but also by the
+\emph{initargs} defined by the receiving instance's class and its
+superclasses, which are made available to slot initializers and
+initialization fragments.
+
+There are two kinds of initarg definitions.  \emph{User initargs} are defined
+by an explicit @|initarg| item appearing in a class definition: the item
+defines a name, type, and (optionally) a default value for the initarg.
+\emph{Slot initargs} are defined by attaching an @|initarg| property to a
+slot or slot initializer item: the property's determines the initarg's name,
+while the type is taken from the underlying slot type; slot initargs do not
+have default values.  Both kinds define a \emph{direct initarg} for the
+containing class.
+
+Initargs are inherited.  The \emph{applicable} direct initargs for an @|init|
+effective method are those defined by the receiving object's class, and all
+of its superclasses.  Applicable direct initargs with the same name are
+merged to form \emph{effective initargs}.  An error is reported if two
+applicable direct initargs have the same name but different types.  The
+default value of an effective initarg is taken from the most specific
+applicable direct initarg which specifies a defalt value; if no applicable
+direct initarg specifies a default value then the effective initarg has no
+default.
+
+All initarg values are made available at runtime to user code --
+initialization fragments and slot initializer expressions -- through local
+variables and a @|suppliedp| structure, as in a direct method
+(\xref{sec:concepts.methods.keywords}).  Furthermore, slot initarg
+definitions influence the initialization of slots.
+
+The process for deciding how to initialize a particular slot works as
+follows.
+\begin{enumerate}
+\item If there are any slot initargs defined on the slot, or any of its slot
+  initializers, \emph{and} the sender supplied a value for one or more of the
+  corresponding effective initargs, then the value of the most specific slot
+  initarg is stored in the slot.
+\item Otherwise, if there are any slot initializers defined which include an
+  initializer expression, then the initializer expression from the most
+  specific such slot initializer is evaluated and its value stored in the
+  slot.
+\item Otherwise, the slot is left uninitialized.
+\end{enumerate}
+Note that the default values (if any) of effective initargs do \emph{not}
+affect this procedure.
 
 
 \subsection{Destruction}
@@ -820,16 +822,16 @@ program may be in an inconsistent state and should not continue.
 This simple protocol can be used, for example, to implement a reference
 counting system, as follows.
 \begin{prog}
-  [nick = ref] \\
-  class ReferenceCountedObject \{ \\ \ind
-    unsigned nref = 1; \\-
-    void inc() \{ me@->ref.nref++; \} \\-
-    [role = around] \\
-    int obj.teardown() \\
-    \{ \\ \ind
-      if (--\,--me@->ref.nref) return (1); \\
-      else return (CALL_NEXT_METHOD); \- \\
-    \} \- \\
+  [nick = ref]                                                  \\
+  class ReferenceCountedObject \{                               \\ \ind
+    unsigned nref = 1;                                          \\-
+    void inc() \{ me@->ref.nref++; \}                           \\-
+    [role = around]                                             \\
+    int obj.teardown()                                          \\
+    \{                                                          \\ \ind
+      if (--\,--me@->ref.nref) return (1);                      \\
+      else return (CALL_NEXT_METHOD);                         \-\\
+    \}                                                        \-\\
   \}
 \end{prog}