src/: Add commentary to the generated code.
[sod] / doc / concepts.tex
index 46d99b1..20402dc 100644 (file)
@@ -110,6 +110,7 @@ appropriate C declarations, tables, and functions.  An object cannot
 (usually) change its direct class, and the direct class of an object is not
 affected by, for example, the static type of a pointer to it.
 
+
 \subsection{Superclasses and inheritance}
 \label{sec:concepts.classes.inherit}
 
@@ -232,6 +233,7 @@ Classes have a number of other attributes:
   then all the superclasses of $C$ must have distinct nicknames.
 \end{itemize}
 
+
 \subsection{Slots} \label{sec:concepts.classes.slots}
 
 Each class defines a number of \emph{slots}.  Much like a structure member, a
@@ -257,6 +259,7 @@ expressions if the generated code is expected to be processed by a
 implementation of C89.  Initializers will be evaluated once each time an
 instance is initialized.
 
+
 \subsection{C language integration} \label{sec:concepts.classes.c}
 
 For each class~$C$, the Sod translator defines a C type, the \emph{class
@@ -278,7 +281,7 @@ about these slot members: C code can access them in the usual way.
 For example, if @|MyClass| has the nickname @|mine|, and defines a slot @|x|
 of type @|int|, then the simple function
 \begin{prog}
-  int get_x(MyClass *m) \{ return (m->mine.x); \}
+  int get_x(MyClass *m) \{ return (m@->mine.x); \}
 \end{prog}
 will extract the value of @|x| from an instance of @|MyClass|.
 
@@ -346,15 +349,15 @@ interim approach is to specify slot initializers where appropriate and send
 class-specific messages for more complicated parametrized initialization.
 
 Automatic-duration instances can be conveniently constructed and initialized
-using the @|SOD_DECL| macro (page~\pageref{mac:SOD-DECL}).  No special
-support is currently provided for dynamically allocated instances.  A simple
-function using @|malloc| might work as follows.
+using the \descref{SOD_DECL}[macro]{mac}.  No special support is currently
+provided for dynamically allocated instances.  A simple function using
+@|malloc| might work as follows.
 \begin{prog}
   void *new_instance(const SodClass *c) \\
   \{ \\ \ind
-    void *p = malloc(c->cls.initsz); \\
+    void *p = malloc(c@->cls.initsz); \\
     if (!p) return (0); \\
-    c->cls.init(p); \\
+    c@->cls.init(p); \\
     return (p); \- \\
   \}
 \end{prog}
@@ -363,26 +366,27 @@ function using @|malloc| might work as follows.
 There is currently no provided assistance for finalization or deallocation.
 It is the programmer's responsibility to decide and implement an appropriate
 protocol.  Note that to free an instance allocated from the heap, one must
-correctly find its base address: the @|SOD_INSTBASE| macro
-(page~\pageref{mac:SOD-INSTBASE}) will do this for you.
+correctly find its base address: the \descref{SOD_INSTBASE}[macro]{mac} will
+do this for you.
 
 The following simple mixin class is suggested.
 \begin{prog}
-  [nick = disposable] \\*
-  class DisposableObject : SodObject \{ \\*[\jot] \ind
-    void release() \{ ; \} \\*
-    \quad /\=\+* Release resources held by the receiver. */ \-\- \\*[\jot]
-  \} \\[\bigskipamount]
-  code c : user \{ \\* \ind
-    /\=\+* Free object p's instance storage.  If p is a DisposableObject \\*
-       {}* then release its resources beforehand. \\*
-       {}*/ \- \\*
-    void free_instance(void *p) \\*
-    \{ \\* \ind
-      DisposableObject *d = SOD_CONVERT(DisposableObject, p); \\*
-      if (d) DisposableObject_release(d); \\*
-      free(d); \- \\*
-    \} \- \\*
+  [nick = disposable] \\
+  class DisposableObject : SodObject \{ \\- \ind
+    void release() \{ ; \} \\
+    \quad /* Release resources held by the receiver. */ \- \\-
+  \}
+  \\+
+  code c : user \{ \\- \ind
+    /\=\+* Free object p's instance storage.  If p is a DisposableObject \\
+       {}* then release its resources beforehand. \\
+       {}*/ \- \\
+    void free_instance(void *p) \\
+    \{ \\ \ind
+      DisposableObject *d = SOD_CONVERT(DisposableObject, p); \\
+      if (d) DisposableObject_release(d); \\
+      free(d); \- \\
+    \} \- \\
   \}
 \end{prog}
 
@@ -403,13 +407,13 @@ There are three main cases to distinguish.
   a lookup at runtime to find the appropriate offset by which to adjust the
   pointer.  The conversion can be performed using the appropriate generated
   upcast macro (see below); the general case is handled by the macro
-  @|SOD_XCHAIN| (page~\pageref{mac:SOD-XCHAIN}).
+  \descref{SOD_XCHAIN}{mac}.
 \item If $B$ is a subclass of~$C$ then the conversion is an \emph{upcast};
   otherwise the conversion is a~\emph{cross-cast}.  In either case, the
   conversion can fail: the object in question might not be an instance of~$B$
-  at all.  The macro @|SOD_CONVERT| (page~\pageref{mac:SOD-CONVERT}) and the
-  function @|sod_convert| (page~\pageref{fun:sod-convert}) perform general
-  conversions.  They return a null pointer if the conversion fails.
+  at all.  The macro \descref{SOD_CONVERT}{mac} and the function
+  \descref{sod_convert}{fun} perform general conversions.  They return a null
+  pointer if the conversion fails.
 \end{itemize}
 The Sod translator generates macros for performing both in-chain and
 cross-chain upcasts.  For each class~$C$, and each proper superclass~$B$
@@ -473,6 +477,7 @@ contains a copy of the direct method body.  Within the body of a direct
 method defined for a class $C$, the variable @|me|, of type pointer to class
 type of $C$, refers to the receiving object.
 
+
 \subsection{Effective methods and method combinations}
 \label{sec:concepts.methods.combination}
 
@@ -507,9 +512,9 @@ argument lists which \emph{match} the message's argument list:
 \item if the message accepts a variable-length argument suffix then the
   direct method must instead have a final argument of type @|va_list|.
 \end{itemize}
-Primary and around methods must have the same return type as the message;
-before and after methods must return @|void| regardless of the message's
-return type.
+Primary and @|around| methods must have the same return type as the message;
+@|before| and @|after| methods must return @|void| regardless of the
+message's return type.
 
 If there are no applicable primary methods then no effective method is
 constructed: the vtables contain null pointers in place of pointers to method
@@ -523,21 +528,22 @@ follows.
   specific such method, with respect to the class of the receiving object, is
   invoked.
 
-  Within the body of an around method, the variable @|next_method| is
+  Within the body of an @|around| method, the variable @|next_method| is
   defined, having pointer-to-function type.  The method may call this
   function, as described below, any number of times.
 
-  If there any remaining around methods, then @|next_method| invokes the next
-  most specific such method, returning whichever value that method returns;
-  otherwise the behaviour of @|next_method| is to invoke the before methods
-  (if any), followed by the most specific primary method, followed by the
-  around methods (if any), and to return whichever value was returned by the
-  most specific primary method.  That is, the behaviour of the least specific
-  around method's @|next_method| function is exactly the behaviour that the
-  effective method would have if there were no around methods.
+  If there any remaining @|around| methods, then @|next_method| invokes the
+  next most specific such method, returning whichever value that method
+  returns; otherwise the behaviour of @|next_method| is to invoke the before
+  methods (if any), followed by the most specific primary method, followed by
+  the @|around| methods (if any), and to return whichever value was returned
+  by the most specific primary method.  That is, the behaviour of the least
+  specific @|around| method's @|next_method| function is exactly the
+  behaviour that the effective method would have if there were no @|around|
+  methods.
 
-  The value returned by the most specific around method is the value returned
-  by the effective method.
+  The value returned by the most specific @|around| method is the value
+  returned by the effective method.
 
 \item If any applicable methods have the @|before| role, then they are all
   invoked, starting with the most specific.
@@ -554,20 +560,21 @@ follows.
   invoke the next most specific applicable primary method, and to return
   whichever value that method returns.
 
-  If there are no applicable around methods, then the value returned by the
-  most specific primary method is the value returned by the effective method;
-  otherwise the value returned by the most specific primary method is
-  returned to the least specific around method, which called it via its own
-  @|next_method| function.
+  If there are no applicable @|around| methods, then the value returned by
+  the most specific primary method is the value returned by the effective
+  method; otherwise the value returned by the most specific primary method is
+  returned to the least specific @|around| method, which called it via its
+  own @|next_method| function.
 
 \item If any applicable methods have the @|after| role, then they are all
   invoked, starting with the \emph{least} specific.  (Hence, the most
-  specific after method is invoked with the most `afterness'.)
+  specific @|after| method is invoked with the most `afterness'.)
 
 \end{enumerate}
 
-A typical use for around methods is to set up the dynamic environment
-appropriately for the primary methods, e.g., by claiming a lock.
+A typical use for @|around| methods is to allow a base class to set up the
+dynamic environment appropriately for the primary methods of its subclasses,
+e.g., by claiming a lock, and restore it afterwards.
 
 The @|next_method| function provided to methods with the @|primary| and
 @|around| roles accepts the same arguments, and returns the same type, as the
@@ -598,8 +605,8 @@ the applicable primary methods in turn and aggregate the return values from
 each.
 
 The aggregating method combinations accept the same four roles as the
-standard method combination, and around, before, and after methods work in
-the same way.
+standard method combination, and @|around|, @|before|, and @|after| methods
+work in the same way.
 
 The aggregating method combinations provided are as follows.
 \begin{description} \let\makelabel\code
@@ -619,14 +626,15 @@ The aggregating method combinations provided are as follows.
 \item[max] The message must return a scalar type.  The applicable primary
   methods are invoked in turn.  The final result is the largest of the
   individual values.
-\item[and] The message must return @|int|.  The applicable primary methods
-  are invoked in turn.  If any method returns zero then the final result is
-  zero and no further methods are invoked.  If all of the applicable primary
-  methods return nonzero, then the final result is a nonzero value.
-\item[or] The message must return @|int|.  The applicable primary methods are
-  invoked in turn.  If any method returns nonzero then the final result is a
-  nonzero value and no further methods are invoked.  If all of the applicable
-  primary methods return zero, then the final result is zero.
+\item[and] The message must return a scalar type.  The applicable primary
+  methods are invoked in turn.  If any method returns zero then the final
+  result is zero and no further methods are invoked.  If all of the
+  applicable primary methods return nonzero, then the final result is the
+  result of the last primary method.
+\item[or] The message must return a scalar type.  The applicable primary
+  methods are invoked in turn.  If any method returns nonzero then the final
+  result is that nonzero value and no further methods are invoked.  If all of
+  the applicable primary methods return zero, then the final result is zero.
 \end{description}
 
 There is also a @|custom| aggregating method combination, which is described