Commit | Line | Data |
---|---|---|
1f1d88f5 MW |
1 | %%% -*-latex-*- |
2 | %%% | |
3 | %%% Tutorial information | |
4 | %%% | |
5 | %%% (c) 2009 Straylight/Edgeware | |
6 | %%% | |
7 | ||
8 | %%%----- Licensing notice --------------------------------------------------- | |
9 | %%% | |
10 | %%% This file is part of the Simple Object Definition system. | |
11 | %%% | |
12 | %%% SOD is free software; you can redistribute it and/or modify | |
13 | %%% it under the terms of the GNU General Public License as published by | |
14 | %%% the Free Software Foundation; either version 2 of the License, or | |
15 | %%% (at your option) any later version. | |
16 | %%% | |
17 | %%% SOD is distributed in the hope that it will be useful, | |
18 | %%% but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | %%% GNU General Public License for more details. | |
21 | %%% | |
22 | %%% You should have received a copy of the GNU General Public License | |
23 | %%% along with SOD; if not, write to the Free Software Foundation, | |
24 | %%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
25 | ||
1f7d590d | 26 | \chapter{Tutorial} \label{ch:tutorial} |
1f1d88f5 MW |
27 | |
28 | This chapter provides a tutorial introduction to the Sod object system. It | |
29 | intentionally misses out nitty-gritty details. If you want those, the | |
30 | remaining chapters provide a complete reference to Sod. | |
31 | ||
32 | The author isn't terribly good at writing tutorial-style documentation. | |
33 | You'll have to bear with him. If you think you can do a better job, I'm sure | |
34 | that he'll be grateful for your contribution. | |
35 | ||
36 | %%%-------------------------------------------------------------------------- | |
1f7d590d | 37 | \section{Introduction} \label{sec:tutorial.intro} |
1f1d88f5 MW |
38 | |
39 | Sod is an object system for the C~programming language. Because it doesn't | |
40 | have enough already. Actually, that's not right: it's got plenty already. | |
41 | But Sod is a Sensible Object Design, and C doesn't have any of those. | |
42 | ||
43 | What does that mean when the author's not off on one of his tirades? It | |
44 | means that is has the following features. | |
45 | \begin{itemize} | |
46 | \item It has a \emph{minimal runtime system}. Sod isn't likely to interfere | |
47 | with other language runtimes or be difficult to deal with from a practical | |
48 | point of view. | |
49 | \item It provides \emph{multiple inheritance}. Rather than having a single | |
50 | superclass, Sod allows a class to specify any number of superclasses. | |
51 | Moreover, it implements multiple inheritance using \emph{superclass | |
52 | linearization}, which means that it's not a nightmare to deal with. | |
53 | \item It provides multiple \emph{method rĂ´les}, including `before', `after' | |
54 | and `around' methods, which makes constructing object protocols rather more | |
55 | straightforward. | |
56 | \item It provides a number of \emph{method combinations}. For those coming | |
57 | from languages other than Lisp, a method combination is a rule for deciding | |
58 | how to invoke the various methods which might be used to respond to a | |
59 | message. (This might still sound like a strange idea. We'll deal with it | |
60 | in detail later.) | |
61 | \item It allows \emph{user-defined method combinations}. It does a whole lot | |
62 | more: there's an entire translation-time \emph{meta-object protocol}, so | |
63 | that extensions can modify many different aspects of the object system. | |
64 | The downside is that you have to learn Common Lisp and roll up your sleeves | |
65 | if you want to do any of this. | |
66 | \end{itemize} | |
67 | There's a good chance that half of that didn't mean anything to you. Bear | |
68 | with me, though, because we'll explain it all eventually. | |
69 | ||
1f7d590d | 70 | \subsection{Building programs with Sod} \label{sec:tutorial.intro.build} |
1f1d88f5 MW |
71 | |
72 | Sod is basically a fancy preprocessor, in the same vein as Lex and Yacc. It | |
73 | reads source files written in a vaguely C-like language. It produces output | |
74 | files which are actually C code (both header files and standalone sources), | |
75 | and which contain chunks of the input files verbatim. | |
76 | ||
77 | The main consequences of this are as follows. | |
78 | \begin{itemize} | |
79 | \item The output is completely portable between different machines and | |
80 | compilers. If you're preparing a source distribution for general release, | |
81 | it's probably a good idea to provide the generated C~source as well as your | |
82 | Sod sources. | |
83 | \item Sod hasn't made any attempt to improve C's syntax. It's just as | |
84 | hostile to object-oriented programming as it ever was. This means that | |
85 | you'll end up writing ugly things like | |
1f7d590d | 86 | \begin{prog} |
c18d6aba | 87 | thing@->_vt@->foo.frob(thing, mumble); |
1f1d88f5 MW |
88 | \end{prog} |
89 | fairly frequently. This can be made somewhat less painful using macros, | |
90 | but we're basically stuck with C. The upside is that you know exactly what | |
91 | you're getting. A common complaint about \Cplusplus\ is that it has a | |
92 | tendency to hide arbitrarily complicated runtime behaviour behind | |
93 | apparently innocent syntax: you don't get any of that with Sod. Some | |
94 | people might even think this is a benefit. | |
95 | \end{itemize} | |
96 | Of course, this means that your build system needs to become more | |
97 | complicated. If you use \man{make}{1}, then something like | |
1f7d590d | 98 | \begin{prog} |
020b9e2b MW |
99 | SOD = sod \\+ |
100 | ||
101 | .SUFFIXES: .sod .c .h \\ | |
102 | .sod.c:; \$(SOD) -tc \$< \\ | |
fca95fc1 | 103 | .sod.h:; \$(SOD) -th \$< |
1f1d88f5 MW |
104 | \end{prog} |
105 | ought to do the job. | |
106 | ||
107 | %%%-------------------------------------------------------------------------- | |
108 | \section{A traditional trivial introduction} | |
109 | ||
110 | The following is a simple Sod input file. | |
1f7d590d | 111 | \begin{prog} |
020b9e2b MW |
112 | /* -*-sod-*- */ \\+ |
113 | ||
114 | code c : includes \{ \\ | |
115 | \#include "greeter.h" \\ | |
116 | \} \\+ | |
117 | ||
118 | code h : includes \{ \\ | |
119 | \#include <stdio.h> \\ | |
120 | \#include <sod/sod.h> \\ | |
121 | \} \\+ | |
122 | ||
123 | class Greeter : SodObject \{ \\ \ind | |
124 | void greet(FILE *fp) \{ \\ \ind | |
125 | fputs("Hello, world!\textbackslash n", fp); \-\\ | |
126 | \} \-\\ | |
ebf5ae2e | 127 | \} |
1f1d88f5 MW |
128 | \end{prog} |
129 | Save it as @"greeter.sod", and run | |
1f7d590d | 130 | \begin{prog} |
ebf5ae2e | 131 | sod --gc --gh greeter |
1f1d88f5 MW |
132 | \end{prog} |
133 | This will create files @"greeter.c" and @"greeter.h" in the current | |
134 | directory. Here's how we might use such a simple thing. | |
1f7d590d | 135 | \begin{prog} |
020b9e2b MW |
136 | \#include "greeter.h" \\+ |
137 | ||
138 | int main(void) \\ | |
139 | \{ \\ \ind | |
140 | SOD_DECL(Greeter, g); \\+ | |
141 | ||
142 | Greeter_greet(g, stdout); \\ | |
143 | return (0); \-\\ | |
ebf5ae2e | 144 | \} |
1f1d88f5 MW |
145 | \end{prog} |
146 | Compare this to the traditional | |
1f7d590d | 147 | \begin{prog} |
020b9e2b MW |
148 | \#include <stdio.h> \\+ |
149 | ||
150 | int main(void) \\ \ind | |
ebf5ae2e | 151 | \{ fputs("Hello, world@\\n", stdout); return (0); \} |
1f1d88f5 MW |
152 | \end{prog} |
153 | and I'm sure you'll appreciate the benefits of using Sod already -- mostly to | |
154 | do with finger exercise. Trust me, it gets more useful. | |
155 | ||
156 | The @".sod" file was almost comprehensible. There are two important parts to | |
157 | it (after the comment which tells Emacs how to cope with it). | |
158 | ||
159 | The first part consists of the two @"code" stanzas. Both of them define | |
160 | gobbets of raw C code to copy into output files. The first one, @"code~: | |
161 | c"~\ldots, says that | |
1f7d590d MW |
162 | \begin{prog} |
163 | \#include "greeter.h" | |
1f1d88f5 MW |
164 | \end{prog} |
165 | needs to appear in the generated @|greeter.c| file; the second says that | |
1f7d590d | 166 | \begin{prog} |
020b9e2b | 167 | \#include <stdio.h> \\ |
1f7d590d | 168 | \#include <sod/sod.h> |
1f1d88f5 MW |
169 | \end{prog} |
170 | needs to appear in the header file @|greeter.h|. The generated C files need | |
171 | to get declarations for external types and functions (e.g., @"FILE" and | |
172 | @"fputs") from somewhere, and the generated @".c" file will need the | |
173 | declarations from the corresponding @".h" file. Sod takes a very simple | |
174 | approach to all of this: it expects you, the programmer, to deal with it. | |
175 | ||
176 | The basic syntax for @"code" stanzas is | |
1f7d590d | 177 | \begin{prog} |
020b9e2b MW |
178 | code @<file-label> : @<section> \{ \\ \ind |
179 | @<code> \-\\ | |
1f7d590d | 180 | \} |
1f1d88f5 MW |
181 | \end{prog} |
182 | The @<file-label> is either @"c" or @"h", and says which output file the code | |
183 | wants to be written to. The @<section> is a name which explains where in the | |
184 | output file to place the code. The @"includes" section is the usual choice: | |
185 | it's the `right' place for @`\#include' directives and similar declarations. | |
186 | ||
187 | The remaining part, the `meat' of the file, defines a class called | |
188 | @"greeter". The class can respond to a single message, named @"greet", and | |
189 | in response, it writes a traditional greeting to the file passed in with the | |
190 | message. | |
191 | ||
192 | So far, so good. The C code, which we thought we understood, contains some | |
193 | bizarre looking runes. Let's take it one step at a time. | |
1f7d590d MW |
194 | \begin{prog} |
195 | struct Greeter__ilayout g_obj; | |
1f1d88f5 MW |
196 | \end{prog} |
197 | allocates space for an instance of class @"Greeter". We're not going to use | |
198 | this space directly. Instead, we do this frightening looking thing. | |
1f7d590d | 199 | \begin{prog} |
c18d6aba | 200 | Greeter *g = Greeter__class@->cls.init(\&g_obj); |
1f1d88f5 MW |
201 | \end{prog} |
202 | Taking it slowly: @"Greeter__class" is a pointer to the object that | |
203 | represents our class @"Greeter". This object contains a member, named | |
204 | @"cls.init", which points to a function whose job is to turn uninitialized | |
205 | storage space into working instances of the class. It returns a pointer to | |
206 | the instance, which we use in preference to grovelling about in the | |
207 | @"ilayout" structure. | |
208 | ||
209 | Having done this, we `send the instance a message': | |
1f7d590d | 210 | \begin{prog} |
c18d6aba | 211 | g@->_vt@->greeter.greet(g, stdout); |
1f1d88f5 MW |
212 | \end{prog} |
213 | This looks horrific, and seems to repeat itself quite unnecessarily. The | |
214 | first @"g" is the recipient of our `message'. The second is indeed a copy of | |
215 | the first: we have to tell it who it is. (Sod doesn't extend C's syntax, so | |
216 | this is the sort of thing we just have to put up with.) The lowercase | |
217 | @"greeter" is our class's `nickname': we didn't choose one explicitly, so Sod | |
218 | picked one by forcing the classname to lowercase. | |
219 | ||
220 | %%%----- That's all, folks -------------------------------------------------- | |
221 | ||
222 | %%% Local variables: | |
223 | %%% mode: LaTeX | |
224 | %%% TeX-master: "sod.tex" | |
225 | %%% TeX-PDF-mode: t | |
226 | %%% End: |