hostile to object-oriented programming as it ever was. This means that
you'll end up writing ugly things like
\begin{prog}
- thing->_vt->foo.frob(thing, mumble);
+ thing@->_vt@->foo.frob(thing, mumble);
\end{prog}
fairly frequently. This can be made somewhat less painful using macros,
but we're basically stuck with C. The upside is that you know exactly what
Of course, this means that your build system needs to become more
complicated. If you use \man{make}{1}, then something like
\begin{prog}
- SOD = sod \\
- \\
- .SUFFIXES: .sod .c .h \\
- .sod.c:; \$(SOD) -tc \$< \\
+ SOD = sod \\+
+
+ .SUFFIXES: .sod .c .h \\
+ .sod.c:; \$(SOD) -tc \$< \\
.sod.h:; \$(SOD) -th \$<
\end{prog}
ought to do the job.
The following is a simple Sod input file.
\begin{prog}
-/* -*-sod-*- */ \\
-\\
-code c : includes \{ \\
-\#include "greeter.h" \\
-\} \\
-\\
-code h : includes \{ \\
-\#include <stdio.h> \\
-\#include <sod/sod.h> \\
-\} \\
-\\
-class Greeter : SodObject \{ \\ \ind
- void greet(FILE *fp) \{ \\ \ind
- fputs("Hello, world!\textbackslash n", fp); \- \\
- \} \- \\
-\}
+ /* -*-sod-*- */ \\+
+
+ code c : includes \{ \\
+ \#include "greeter.h" \\
+ \} \\+
+
+ code h : includes \{ \\
+ \#include <stdio.h> \\
+ \#include <sod/sod.h> \\
+ \} \\+
+
+ class Greeter : SodObject \{ \\ \ind
+ void greet(FILE *fp) \{ \\ \ind
+ fputs("Hello, world!\textbackslash n", fp); \-\\
+ \} \-\\
+ \}
\end{prog}
Save it as @"greeter.sod", and run
\begin{prog}
-sod --gc --gh greeter
+ sod --gc --gh greeter
\end{prog}
This will create files @"greeter.c" and @"greeter.h" in the current
directory. Here's how we might use such a simple thing.
\begin{prog}
-\#include "greeter.h" \\
-\\
-int main(void) \\
-\{ \\ \ind
- SOD_DECL(Greeter, g); \\
- \\
- Greeter_greet(g, stdout); \\
- return (0); \- \\
-\}
+ \#include "greeter.h" \\+
+
+ int main(void) \\
+ \{ \\ \ind
+ SOD_DECL(Greeter, g); \\+
+
+ Greeter_greet(g, stdout); \\
+ return (0); \-\\
+ \}
\end{prog}
Compare this to the traditional
\begin{prog}
-\#include <stdio.h> \\
-\\
-int main(void) \\ \ind
- \{ fputs("Hello, world@\\n", stdout); return (0); \}
+ \#include <stdio.h> \\+
+
+ int main(void) \\ \ind
+ \{ fputs("Hello, world@\\n", stdout); return (0); \}
\end{prog}
and I'm sure you'll appreciate the benefits of using Sod already -- mostly to
do with finger exercise. Trust me, it gets more useful.
\end{prog}
needs to appear in the generated @|greeter.c| file; the second says that
\begin{prog}
- \#include <stdio.h> \\
+ \#include <stdio.h> \\
\#include <sod/sod.h>
\end{prog}
needs to appear in the header file @|greeter.h|. The generated C files need
The basic syntax for @"code" stanzas is
\begin{prog}
- code @<file-label> : @<section> \{ \\ \ind
- @<code> \- \\
+ code @<file-label> : @<section> \{ \\ \ind
+ @<code> \-\\
\}
\end{prog}
The @<file-label> is either @"c" or @"h", and says which output file the code
allocates space for an instance of class @"Greeter". We're not going to use
this space directly. Instead, we do this frightening looking thing.
\begin{prog}
- Greeter *g = Greeter__class->cls.init(\&g_obj);
+ Greeter *g = Greeter__class@->cls.init(\&g_obj);
\end{prog}
Taking it slowly: @"Greeter__class" is a pointer to the object that
represents our class @"Greeter". This object contains a member, named
Having done this, we `send the instance a message':
\begin{prog}
- g->_vt->greeter.greet(g, stdout);
+ g@->_vt@->greeter.greet(g, stdout);
\end{prog}
This looks horrific, and seems to repeat itself quite unnecessarily. The
first @"g" is the recipient of our `message'. The second is indeed a copy of