Commit | Line | Data |
---|---|---|
1f7d590d MW |
1 | %%% -*-latex-*- |
2 | %%% | |
3 | %%% Module syntax | |
4 | %%% | |
5 | %%% (c) 2015 Straylight/Edgeware | |
6 | %%% | |
7 | ||
8 | %%%----- Licensing notice --------------------------------------------------- | |
9 | %%% | |
e0808c47 | 10 | %%% This file is part of the Sensible Object Design, an object system for C. |
1f7d590d MW |
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 | ||
26 | \chapter{Module syntax} \label{ch:syntax} | |
27 | ||
28 | %%%-------------------------------------------------------------------------- | |
68a620ab | 29 | \section{Lexical syntax} \label{sec:syntax.lex} |
1f7d590d MW |
30 | |
31 | Whitespace and comments are discarded. The remaining characters are | |
32 | collected into tokens according to the following syntax. | |
33 | ||
34 | \begin{grammar} | |
35 | <token> ::= <identifier> | |
36 | \alt <string-literal> | |
37 | \alt <char-literal> | |
38 | \alt <integer-literal> | |
39 | \alt <punctuation> | |
40 | \end{grammar} | |
41 | ||
42 | This syntax is slightly ambiguous, and is disambiguated by the \emph{maximal | |
43 | munch} rule: at each stage we take the longest sequence of characters which | |
44 | could be a token. | |
45 | ||
68a620ab MW |
46 | |
47 | \subsection{Identifiers} \label{sec:syntax.lex.id} | |
1f7d590d MW |
48 | |
49 | \begin{grammar} | |
50 | <identifier> ::= <id-start-char> @<id-body-char>^* | |
51 | ||
52 | <id-start-char> ::= <alpha-char> | "_" | |
53 | ||
54 | <id-body-char> ::= <id-start-char> @! <digit-char> | |
55 | ||
56 | <alpha-char> ::= "A" | "B" | \dots\ | "Z" | |
57 | \alt "a" | "b" | \dots\ | "z" | |
58 | \alt <extended-alpha-char> | |
59 | ||
60 | <digit-char> ::= "0" | <nonzero-digit-char> | |
61 | ||
cee29adc | 62 | <nonzero-digit-char> ::= "1" | "2" $| \ldots |$ "9" |
1f7d590d MW |
63 | \end{grammar} |
64 | ||
65 | The precise definition of @<alpha-char> is left to the function | |
66 | \textsf{alpha-char-p} in the hosting Lisp system. For portability, | |
67 | programmers are encouraged to limit themselves to the standard ASCII letters. | |
68 | ||
69 | There are no reserved words at the lexical level, but the higher-level syntax | |
70 | recognizes certain identifiers as \emph{keywords} in some contexts. There is | |
71 | also an ambiguity (inherited from C) in the declaration syntax which is | |
72 | settled by distinguishing type names from other identifiers at a lexical | |
73 | level. | |
74 | ||
68a620ab MW |
75 | |
76 | \subsection{String and character literals} \label{sec:syntax.lex.string} | |
1f7d590d MW |
77 | |
78 | \begin{grammar} | |
79 | <string-literal> ::= "\"" @<string-literal-char>^* "\"" | |
80 | ||
81 | <char-literal> ::= "'" <char-literal-char> "'" | |
82 | ||
83 | <string-literal-char> ::= any character other than "\\" or "\"" | |
84 | \alt "\\" <char> | |
85 | ||
86 | <char-literal-char> ::= any character other than "\\" or "'" | |
87 | \alt "\\" <char> | |
88 | ||
89 | <char> ::= any single character | |
90 | \end{grammar} | |
91 | ||
92 | The syntax for string and character literals differs from~C. In particular, | |
93 | escape sequences such as @`\textbackslash n' are not recognized. The use | |
94 | of string and character literals in Sod, outside of C~fragments, is limited, | |
95 | and the simple syntax seems adequate. For the sake of future compatibility, | |
96 | the use of character sequences which resemble C escape sequences is | |
97 | discouraged. | |
98 | ||
a59e2904 MW |
99 | |
100 | \subsection{Integer literals} \label{sec:syntax.lex.int} | |
1f7d590d MW |
101 | |
102 | \begin{grammar} | |
103 | <integer-literal> ::= <decimal-integer> | |
104 | \alt <binary-integer> | |
105 | \alt <octal-integer> | |
106 | \alt <hex-integer> | |
107 | ||
cc0bcf39 | 108 | <decimal-integer> ::= "0" | <nonzero-digit-char> @<digit-char>^* |
1f7d590d MW |
109 | |
110 | <binary-integer> ::= "0" @("b"|"B"@) @<binary-digit-char>^+ | |
111 | ||
112 | <binary-digit-char> ::= "0" | "1" | |
113 | ||
114 | <octal-integer> ::= "0" @["o"|"O"@] @<octal-digit-char>^+ | |
115 | ||
cee29adc | 116 | <octal-digit-char> ::= "0" | "1" $| \ldots |$ "7" |
1f7d590d MW |
117 | |
118 | <hex-integer> ::= "0" @("x"|"X"@) @<hex-digit-char>^+ | |
119 | ||
120 | <hex-digit-char> ::= <digit-char> | |
121 | \alt "A" | "B" | "C" | "D" | "E" | "F" | |
122 | \alt "a" | "b" | "c" | "d" | "e" | "f" | |
123 | \end{grammar} | |
124 | ||
125 | Sod understands only integers, not floating-point numbers; its integer syntax | |
126 | goes slightly beyond C in allowing a @`0o' prefix for octal and @`0b' for | |
127 | binary. However, length and signedness indicators are not permitted. | |
128 | ||
68a620ab MW |
129 | |
130 | \subsection{Punctuation} \label{sec:syntax.lex.punct} | |
1f7d590d MW |
131 | |
132 | \begin{grammar} | |
133 | <punctuation> ::= any nonalphanumeric character other than "_", "\"" or "'" | |
134 | \end{grammar} | |
135 | ||
68a620ab MW |
136 | |
137 | \subsection{Comments} \label{sec:syntax.lex.comment} | |
1f7d590d MW |
138 | |
139 | \begin{grammar} | |
140 | <comment> ::= <block-comment> | |
141 | \alt <line-comment> | |
142 | ||
143 | <block-comment> ::= | |
144 | "/*" | |
145 | @<not-star>^* @(@<star>^+ <not-star-or-slash> @<not-star>^*@)^* | |
146 | @<star>^* | |
147 | "*/" | |
148 | ||
149 | <star> ::= "*" | |
150 | ||
151 | <not-star> ::= any character other than "*" | |
152 | ||
153 | <not-star-or-slash> ::= any character other than "*" or "/" | |
154 | ||
20f9c213 | 155 | <line-comment> ::= "/\,/" @<not-newline>^* <newline> |
1f7d590d MW |
156 | |
157 | <newline> ::= a newline character | |
158 | ||
159 | <not-newline> ::= any character other than newline | |
160 | \end{grammar} | |
161 | ||
20f9c213 MW |
162 | Comments are exactly as in C99: both traditional block comments `@|/*| \dots\ |
163 | @|*/|' and \Cplusplus-style `@|/\,/| \dots' comments are permitted and | |
164 | ignored. | |
1f7d590d | 165 | |
68a620ab MW |
166 | |
167 | \subsection{Special nonterminals} \label{sec:syntax.lex.special} | |
1f7d590d MW |
168 | |
169 | Aside from the lexical syntax presented above (\xref{sec:lexical-syntax}), | |
170 | two special nonterminals occur in the module syntax. | |
171 | ||
68a620ab | 172 | \subsubsection{S-expressions} |
1f7d590d MW |
173 | \begin{grammar} |
174 | <s-expression> ::= an S-expression, as parsed by the Lisp reader | |
175 | \end{grammar} | |
176 | ||
177 | When an S-expression is expected, the Sod parser simply calls the host Lisp | |
68a620ab MW |
178 | system's @|read| function. Sod modules are permitted to modify the read |
179 | table to extend the S-expression syntax. | |
1f7d590d MW |
180 | |
181 | S-expressions are self-delimiting, so no end-marker is needed. | |
182 | ||
68a620ab | 183 | \subsubsection{C fragments} |
1f7d590d MW |
184 | \begin{grammar} |
185 | <c-fragment> ::= a sequence of C tokens, with matching brackets | |
186 | \end{grammar} | |
187 | ||
188 | Sequences of C code are simply stored and written to the output unchanged | |
189 | during translation. They are read using a simple scanner which nonetheless | |
190 | understands C comments and string and character literals. | |
191 | ||
192 | A C fragment is terminated by one of a small number of delimiter characters | |
193 | determined by the immediately surrounding context -- usually a closing brace | |
194 | or bracket. The first such delimiter character which is not enclosed in | |
195 | brackets, braces or parenthesis ends the fragment. | |
196 | ||
68a620ab MW |
197 | %%%-------------------------------------------------------------------------- |
198 | \section{Module syntax} \label{sec:syntax.module} | |
1f7d590d MW |
199 | |
200 | \begin{grammar} | |
201 | <module> ::= @<definition>^* | |
202 | ||
203 | <definition> ::= <import-definition> | |
204 | \alt <load-definition> | |
205 | \alt <lisp-definition> | |
206 | \alt <code-definition> | |
207 | \alt <typename-definition> | |
208 | \alt <class-definition> | |
209 | \end{grammar} | |
210 | ||
68a620ab MW |
211 | A @<module> is the top-level syntactic item. A module consists of a sequence |
212 | of definitions. | |
1f7d590d | 213 | |
6390b845 | 214 | \fixme{describe syntax; expand} |
8399be6f MW |
215 | Properties: |
216 | \begin{description} | |
ba375a80 | 217 | \item[@|module_class|] A symbol naming the Lisp class to use to |
8399be6f | 218 | represent the module. |
ba375a80 | 219 | \item[@|guard|] An identifier to use as the guard symbol used to prevent |
8399be6f MW |
220 | multiple inclusion in the header file. |
221 | \end{description} | |
222 | ||
223 | ||
68a620ab | 224 | \subsection{Simple definitions} \label{sec:syntax.module.simple} |
1f7d590d | 225 | |
68a620ab | 226 | \subsubsection{Importing modules} |
1f7d590d MW |
227 | \begin{grammar} |
228 | <import-definition> ::= "import" <string> ";" | |
229 | \end{grammar} | |
230 | ||
231 | The module named @<string> is processed and its definitions made available. | |
232 | ||
233 | A search is made for a module source file as follows. | |
234 | \begin{itemize} | |
235 | \item The module name @<string> is converted into a filename by appending | |
236 | @`.sod', if it has no extension already.\footnote{% | |
237 | Technically, what happens is \textsf{(merge-pathnames name (make-pathname | |
238 | :type "SOD" :case :common))}, so exactly what this means varies | |
239 | according to the host system.} % | |
240 | \item The file is looked for relative to the directory containing the | |
241 | importing module. | |
242 | \item If that fails, then the file is looked for in each directory on the | |
243 | module search path in turn. | |
244 | \item If the file still isn't found, an error is reported and the import | |
245 | fails. | |
246 | \end{itemize} | |
247 | At this point, if the file has previously been imported, nothing further | |
248 | happens.\footnote{% | |
249 | This check is done using \textsf{truename}, so it should see through simple | |
250 | tricks like symbolic links. However, it may be confused by fancy things | |
251 | like bind mounts and so on.} % | |
252 | ||
253 | Recursive imports, either direct or indirect, are an error. | |
254 | ||
68a620ab | 255 | \subsubsection{Loading extensions} |
1f7d590d MW |
256 | \begin{grammar} |
257 | <load-definition> ::= "load" <string> ";" | |
258 | \end{grammar} | |
259 | ||
260 | The Lisp file named @<string> is loaded and evaluated. | |
261 | ||
262 | A search is made for a Lisp source file as follows. | |
263 | \begin{itemize} | |
264 | \item The name @<string> is converted into a filename by appending @`.lisp', | |
265 | if it has no extension already.\footnote{% | |
266 | Technically, what happens is \textsf{(merge-pathnames name (make-pathname | |
267 | :type "LISP" :case :common))}, so exactly what this means varies | |
268 | according to the host system.} % | |
269 | \item A search is then made in the same manner as for module imports | |
270 | (\xref{sec:syntax-module}). | |
271 | \end{itemize} | |
272 | If the file is found, it is loaded using the host Lisp's \textsf{load} | |
273 | function. | |
274 | ||
275 | Note that Sod doesn't attempt to compile Lisp files, or even to look for | |
276 | existing compiled files. The right way to package a substantial extension to | |
277 | the Sod translator is to provide the extension as a standard ASDF system (or | |
ba375a80 | 278 | similar) and leave a dropping @|foo-extension.lisp| in the module path saying |
1f7d590d MW |
279 | something like |
280 | \begin{quote} | |
281 | \textsf{(asdf:load-system :foo-extension)} | |
282 | \end{quote} | |
283 | which will arrange for the extension to be compiled if necessary. | |
284 | ||
285 | (This approach means that the language doesn't need to depend on any | |
286 | particular system definition facility. It's bad enough already that it | |
287 | depends on Common Lisp.) | |
288 | ||
68a620ab | 289 | \subsubsection{Lisp escapes} |
1f7d590d MW |
290 | \begin{grammar} |
291 | <lisp-definition> ::= "lisp" <s-expression> ";" | |
292 | \end{grammar} | |
293 | ||
294 | The @<s-expression> is evaluated immediately. It can do anything it likes. | |
295 | ||
eae50115 MW |
296 | \begin{boxy}[Warning!] |
297 | This means that hostile Sod modules are a security hazard. Lisp code can | |
298 | read and write files, start other programs, and make network connections. | |
299 | Don't install Sod modules from sources that you don't trust.\footnote{% | |
300 | Presumably you were going to run the corresponding code at some point, so | |
301 | this isn't as unusually scary as it sounds. But please be careful.} % | |
302 | \end{boxy} | |
1f7d590d | 303 | |
68a620ab | 304 | \subsubsection{Declaring type names} |
1f7d590d MW |
305 | \begin{grammar} |
306 | <typename-definition> ::= | |
ea08dc56 | 307 | "typename" <list>$[\mbox{@<identifier>}]$ ";" |
1f7d590d MW |
308 | \end{grammar} |
309 | ||
310 | Each @<identifier> is declared as naming a C type. This is important because | |
311 | the C type syntax -- which Sod uses -- is ambiguous, and disambiguation is | |
312 | done by distinguishing type names from other identifiers. | |
313 | ||
314 | Don't declare class names using @"typename"; use @"class" forward | |
315 | declarations instead. | |
316 | ||
68a620ab MW |
317 | |
318 | \subsection{Literal code} \label{sec:syntax.module.literal} | |
1f7d590d MW |
319 | |
320 | \begin{grammar} | |
321 | <code-definition> ::= | |
4fc52153 | 322 | "code" <identifier> ":" <item-name> @[<constraints>@] |
1f7d590d MW |
323 | "{" <c-fragment> "}" |
324 | ||
ea08dc56 | 325 | <constraints> ::= "[" <list>$[\mbox{@<constraint>}]$ "]" |
1f7d590d | 326 | |
4fc52153 MW |
327 | <constraint> ::= @<item-name>^+ |
328 | ||
329 | <item-name> ::= <identifier> @! "(" @<identifier>^+ ")" | |
1f7d590d MW |
330 | \end{grammar} |
331 | ||
332 | The @<c-fragment> will be output unchanged to one of the output files. | |
333 | ||
334 | The first @<identifier> is the symbolic name of an output file. Predefined | |
ba375a80 | 335 | output file names are @|c| and @|h|, which are the implementation code and |
1f7d590d MW |
336 | header file respectively; other output files can be defined by extensions. |
337 | ||
4fc52153 MW |
338 | Output items are named with a sequence of identifiers, separated by |
339 | whitespace, and enclosed in parentheses. As an abbreviation, a name | |
340 | consisting of a single identifier may be written as just that identifier, | |
341 | without the parentheses. | |
1f7d590d MW |
342 | |
343 | The @<constraints> provide a means for specifying where in the output file | |
344 | the output item should appear. (Note the two kinds of square brackets shown | |
345 | in the syntax: square brackets must appear around the constraints if they are | |
346 | present, but that they may be omitted.) Each comma-separated @<constraint> | |
4fc52153 MW |
347 | is a sequence of names of output items, and indicates that the output items |
348 | must appear in the order given -- though the translator is free to insert | |
349 | additional items in between them. (The particular output items needn't be | |
350 | defined already -- indeed, they needn't be defined ever.) | |
1f7d590d | 351 | |
ba375a80 MW |
352 | There is a predefined output item @|includes| in both the @|c| and @|h| |
353 | output files which is a suitable place for inserting @|\#include| | |
1f7d590d MW |
354 | preprocessor directives in order to declare types and functions for use |
355 | elsewhere in the generated output files. | |
356 | ||
1f7d590d | 357 | |
68a620ab | 358 | \subsection{Property sets} \label{sec:syntax.module.properties} |
1f7d590d | 359 | \begin{grammar} |
ea08dc56 | 360 | <properties> ::= "[" <list>$[\mbox{@<property>}]$ "]" |
1f7d590d MW |
361 | |
362 | <property> ::= <identifier> "=" <expression> | |
363 | \end{grammar} | |
364 | ||
365 | Property sets are a means for associating miscellaneous information with | |
366 | classes and related items. By using property sets, additional information | |
367 | can be passed to extensions without the need to introduce idiosyncratic | |
368 | syntax. | |
369 | ||
370 | A property has a name, given as an @<identifier>, and a value computed by | |
371 | evaluating an @<expression>. The value can be one of a number of types, | |
372 | though the only operators currently defined act on integer values only. | |
373 | ||
68a620ab | 374 | \subsubsection{The expression evaluator} |
1f7d590d | 375 | \begin{grammar} |
20f9c213 | 376 | <expression> ::= <term> | <expression> "+" <term> | <expression> "--" <term> |
1f7d590d MW |
377 | |
378 | <term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor> | |
379 | ||
20f9c213 | 380 | <factor> ::= <primary> | "+" <factor> | "--" <factor> |
1f7d590d MW |
381 | |
382 | <primary> ::= | |
383 | <integer-literal> | <string-literal> | <char-literal> | <identifier> | |
1ad4b33a | 384 | \alt "<" <plain-type> ">" |
1f7d590d MW |
385 | \alt "?" <s-expression> |
386 | \alt "(" <expression> ")" | |
387 | \end{grammar} | |
388 | ||
389 | The arithmetic expression syntax is simple and standard; there are currently | |
390 | no bitwise, logical, or comparison operators. | |
391 | ||
392 | A @<primary> expression may be a literal or an identifier. Note that | |
393 | identifiers stand for themselves: they \emph{do not} denote values. For more | |
394 | fancy expressions, the syntax | |
395 | \begin{quote} | |
396 | @"?" @<s-expression> | |
397 | \end{quote} | |
398 | causes the @<s-expression> to be evaluated using the Lisp \textsf{eval} | |
399 | function. | |
400 | %%% FIXME crossref to extension docs | |
401 | ||
68a620ab MW |
402 | |
403 | \subsection{C types} \label{sec:syntax.module.types} | |
1f7d590d MW |
404 | |
405 | Sod's syntax for C types closely mirrors the standard C syntax. A C type has | |
406 | two parts: a sequence of @<declaration-specifier>s and a @<declarator>. In | |
407 | Sod, a type must contain at least one @<declaration-specifier> (i.e., | |
408 | `implicit @"int"' is forbidden), and storage-class specifiers are not | |
409 | recognized. | |
410 | ||
68a620ab | 411 | \subsubsection{Declaration specifiers} |
1f7d590d MW |
412 | \begin{grammar} |
413 | <declaration-specifier> ::= <type-name> | |
414 | \alt "struct" <identifier> | "union" <identifier> | "enum" <identifier> | |
415 | \alt "void" | "char" | "int" | "float" | "double" | |
416 | \alt "short" | "long" | |
417 | \alt "signed" | "unsigned" | |
2e01fd8b MW |
418 | \alt "bool" | "_Bool" |
419 | \alt "imaginary" | "_Imaginary" | "complex" | "_Complex" | |
1f7d590d | 420 | \alt <qualifier> |
db56b1d3 | 421 | \alt <storage-specifier> |
ae0f15ee | 422 | \alt <atomic-type> |
1f7d590d | 423 | |
ae0f15ee MW |
424 | <qualifier> ::= <atomic> | "const" | "volatile" | "restrict" |
425 | ||
20f9c213 MW |
426 | <plain-type> ::= @<declaration-specifier>^+ <abstract-declarator> |
427 | ||
ae0f15ee | 428 | <atomic-type> ::= |
20f9c213 | 429 | <atomic> "(" <plain-type> ")" |
ae0f15ee MW |
430 | |
431 | <atomic> ::= "atomic" | "_Atomic" | |
1f7d590d | 432 | |
db56b1d3 MW |
433 | <storage-specifier> ::= <alignas> "(" <c-fragment> ")" |
434 | ||
435 | <alignas> ::= "alignas" "_Alignas" | |
1f7d590d MW |
436 | |
437 | <type-name> ::= <identifier> | |
438 | \end{grammar} | |
439 | ||
440 | A @<type-name> is an identifier which has been declared as being a type name, | |
2e01fd8b MW |
441 | using the @"typename" or @"class" definitions. The following type names are |
442 | defined in the built-in module. | |
443 | \begin{itemize} | |
444 | \item @"va_list" | |
445 | \item @"size_t" | |
446 | \item @"ptrdiff_t" | |
447 | \item @"wchar_t" | |
448 | \end{itemize} | |
1f7d590d MW |
449 | |
450 | Declaration specifiers may appear in any order. However, not all | |
451 | combinations are permitted. A declaration specifier must consist of zero or | |
db56b1d3 MW |
452 | more @<qualifier>s, zero or more @<storage-specifier>s, and one of the |
453 | following, up to reordering. | |
1f7d590d MW |
454 | \begin{itemize} |
455 | \item @<type-name> | |
ae0f15ee | 456 | \item @<atomic-type> |
1f7d590d MW |
457 | \item @"struct" @<identifier>, @"union" @<identifier>, @"enum" @<identifier> |
458 | \item @"void" | |
2e01fd8b | 459 | \item @"_Bool", @"bool" |
1f7d590d MW |
460 | \item @"char", @"unsigned char", @"signed char" |
461 | \item @"short", @"unsigned short", @"signed short" | |
462 | \item @"short int", @"unsigned short int", @"signed short int" | |
463 | \item @"int", @"unsigned int", @"signed int", @"unsigned", @"signed" | |
464 | \item @"long", @"unsigned long", @"signed long" | |
465 | \item @"long int", @"unsigned long int", @"signed long int" | |
466 | \item @"long long", @"unsigned long long", @"signed long long" | |
467 | \item @"long long int", @"unsigned long long int", @"signed long long int" | |
468 | \item @"float", @"double", @"long double" | |
2e01fd8b MW |
469 | \item @"float _Imaginary", @"double _Imaginary", @"long double _Imaginary" |
470 | \item @"float imaginary", @"double imaginary", @"long double imaginary" | |
471 | \item @"float _Complex", @"double _Complex", @"long double _Complex" | |
472 | \item @"float complex", @"double complex", @"long double complex" | |
1f7d590d MW |
473 | \end{itemize} |
474 | All of these have their usual C meanings. | |
475 | ||
68a620ab | 476 | \subsubsection{Declarators} |
1f7d590d | 477 | \begin{grammar} |
43073476 | 478 | <declarator>$[k, a]$ ::= @<pointer>^* <primary-declarator>$[k, a]$ |
1f7d590d | 479 | |
43073476 MW |
480 | <primary-declarator>$[k, a]$ ::= $k$ |
481 | \alt "(" <primary-declarator>$[k, a]$ ")" | |
482 | \alt <primary-declarator>$[k, a]$ @<declarator-suffix>$[a]$ | |
1f7d590d MW |
483 | |
484 | <pointer> ::= "*" @<qualifier>^* | |
485 | ||
43073476 MW |
486 | <declarator-suffix>$[a]$ ::= "[" <c-fragment> "]" |
487 | \alt "(" $a$ ")" | |
1f7d590d | 488 | |
20f9c213 MW |
489 | <argument-list> ::= $\epsilon$ | "\dots" |
490 | \alt <list>$[\mbox{@<argument>}]$ @["," "\dots"@] | |
1f7d590d MW |
491 | |
492 | <argument> ::= @<declaration-specifier>^+ <argument-declarator> | |
493 | ||
f64eb323 | 494 | <abstract-declarator> ::= <declarator>$[\epsilon, \mbox{@<argument-list>}]$ |
ae0f15ee | 495 | |
43073476 MW |
496 | <argument-declarator> ::= |
497 | <declarator>$[\mbox{@<identifier> @! $\epsilon$}, \mbox{@<argument-list>}]$ | |
1f7d590d | 498 | |
43073476 MW |
499 | <simple-declarator> ::= |
500 | <declarator>$[\mbox{@<identifier>}, \mbox{@<argument-list>}]$ | |
1f7d590d MW |
501 | \end{grammar} |
502 | ||
503 | The declarator syntax is taken from C, but with some differences. | |
504 | \begin{itemize} | |
505 | \item Array dimensions are uninterpreted @<c-fragments>, terminated by a | |
506 | closing square bracket. This allows array dimensions to contain arbitrary | |
507 | constant expressions. | |
508 | \item A declarator may have either a single @<identifier> at its centre or a | |
509 | pair of @<identifier>s separated by a @`.'; this is used to refer to | |
510 | slots or messages defined in superclasses. | |
511 | \end{itemize} | |
512 | The remaining differences are (I hope) a matter of presentation rather than | |
513 | substance. | |
514 | ||
43073476 MW |
515 | There is additional syntax to support messages and methods which accept |
516 | keyword arguments. | |
517 | ||
518 | \begin{grammar} | |
519 | <keyword-argument> ::= <argument> @["=" <c-fragment>@] | |
520 | ||
521 | <keyword-argument-list> ::= | |
522 | @[<list>$[\mbox{@<argument>}]$@] | |
523 | "?" @[<list>$[\mbox{@<keyword-argument>}]$@] | |
524 | ||
525 | <method-argument-list> ::= <argument-list> @! <keyword-argument-list> | |
526 | ||
527 | <dotted-name> ::= <identifier> "." <identifier> | |
528 | ||
529 | <keyword-declarator>$[k]$ ::= | |
530 | <declarator>$[k, \mbox{@<method-argument-list>}]$ | |
531 | \end{grammar} | |
532 | ||
68a620ab MW |
533 | |
534 | \subsection{Class definitions} \label{sec:syntax.module.class} | |
1f7d590d MW |
535 | |
536 | \begin{grammar} | |
537 | <class-definition> ::= <class-forward-declaration> | |
538 | \alt <full-class-definition> | |
539 | \end{grammar} | |
540 | ||
68a620ab | 541 | \subsubsection{Forward declarations} |
1f7d590d MW |
542 | \begin{grammar} |
543 | <class-forward-declaration> ::= "class" <identifier> ";" | |
544 | \end{grammar} | |
545 | ||
546 | A @<class-forward-declaration> informs Sod that an @<identifier> will be used | |
547 | to name a class which is currently undefined. Forward declarations are | |
548 | necessary in order to resolve certain kinds of circularity. For example, | |
7119ea4e | 549 | \begin{prog} |
020b9e2b MW |
550 | class Sub; \\+ |
551 | ||
fd040f06 | 552 | class Super: SodObject \{ \\ \ind |
020b9e2b MW |
553 | Sub *sub; \-\\ |
554 | \}; \\+ | |
555 | ||
fd040f06 | 556 | class Sub: Super \{ \\ \ind |
020b9e2b | 557 | /* \dots\ */ \-\\ |
7119ea4e MW |
558 | \}; |
559 | \end{prog} | |
1f7d590d | 560 | |
68a620ab | 561 | \subsubsection{Full class definitions} |
1f7d590d MW |
562 | \begin{grammar} |
563 | <full-class-definition> ::= | |
564 | @[<properties>@] | |
ea08dc56 MW |
565 | "class" <identifier> ":" <list>$[\mbox{@<identifier>}]$ |
566 | "{" @<properties-class-item>^* "}" | |
1f7d590d | 567 | |
391c5a34 MW |
568 | <properties-class-item> ::= @[<properties>@] <class-item> |
569 | ||
570 | <class-item> ::= <slot-item> | |
571 | \alt <initializer-item> | |
b2983f35 | 572 | \alt <initarg-item> |
a42893dd | 573 | \alt <fragment-item> |
1f7d590d MW |
574 | \alt <message-item> |
575 | \alt <method-item> | |
1f7d590d MW |
576 | \end{grammar} |
577 | ||
578 | A full class definition provides a complete description of a class. | |
579 | ||
580 | The first @<identifier> gives the name of the class. It is an error to | |
581 | give the name of an existing class (other than a forward-referenced class), | |
582 | or an existing type name. It is conventional to give classes `MixedCase' | |
583 | names, to distinguish them from other kinds of identifiers. | |
584 | ||
ea08dc56 MW |
585 | The @<list>$[\mbox{@<identifier>}]$ names the direct superclasses for the new |
586 | class. It is an error if any of these @<identifier>s does not name a defined | |
8d952432 MW |
587 | class. The superclass list is required, and must not be empty; listing |
588 | @|SodObject| as your class's superclass is a good choice if nothing else | |
589 | seems suitable. It's not possible to define a \emph{root class} in the Sod | |
590 | language: you must use Lisp to do this, and it's quite involved. | |
1f7d590d MW |
591 | |
592 | The @<properties> provide additional information. The standard class | |
593 | properties are as follows. | |
594 | \begin{description} | |
ba375a80 | 595 | \item[@|lisp_class|] The name of the Lisp class to use within the translator |
1f7d590d | 596 | to represent this class. The property value must be an identifier; the |
ba375a80 | 597 | default is @|sod_class|. Extensions may define classes with additional |
1f7d590d | 598 | behaviour, and may recognize additional class properties. |
ba375a80 | 599 | \item[@|metaclass|] The name of the Sod metaclass for this class. In the |
1f7d590d MW |
600 | generated code, a class is itself an instance of another class -- its |
601 | \emph{metaclass}. The metaclass defines which slots the class will have, | |
602 | which messages it will respond to, and what its behaviour will be when it | |
603 | receives them. The property value must be an identifier naming a defined | |
ba375a80 | 604 | subclass of @|SodClass|. The default metaclass is @|SodClass|. |
9cd46aef | 605 | See \xref{sec:concepts.metaclasses} for more details. |
ba375a80 | 606 | \item[@|nick|] A nickname for the class, to be used to distinguish it from |
1f7d590d MW |
607 | other classes in various limited contexts. The property value must be an |
608 | identifier; the default is constructed by forcing the class name to | |
609 | lower-case. | |
610 | \end{description} | |
611 | ||
612 | The class body consists of a sequence of @<class-item>s enclosed in braces. | |
613 | These items are discussed on the following sections. | |
614 | ||
68a620ab | 615 | \subsubsection{Slot items} |
1f7d590d MW |
616 | \begin{grammar} |
617 | <slot-item> ::= | |
ea08dc56 | 618 | @<declaration-specifier>^+ <list>$[\mbox{@<init-declarator>}]$ ";" |
1f7d590d | 619 | |
0bc19f1c | 620 | <init-declarator> ::= <simple-declarator> @["=" <initializer>@] |
1f7d590d MW |
621 | \end{grammar} |
622 | ||
623 | A @<slot-item> defines one or more slots. All instances of the class and any | |
624 | subclass will contain these slot, with the names and types given by the | |
625 | @<declaration-specifiers> and the @<declarators>. Slot declarators may not | |
bc7dff5c | 626 | contain dotted names. |
1f7d590d MW |
627 | |
628 | It is not possible to declare a slot with function type: such an item is | |
629 | interpreted as being a @<message-item> or @<method-item>. Pointers to | |
630 | functions are fine. | |
631 | ||
8399be6f MW |
632 | Properties: |
633 | \begin{description} | |
ba375a80 | 634 | \item[@|slot_class|] A symbol naming the Lisp class to use to represent the |
8399be6f | 635 | direct slot. |
ba375a80 | 636 | \item[@|initarg|] An identifier naming an initialization argument which can |
8399be6f MW |
637 | be used to provide a value for the slot. See |
638 | \xref{sec:concepts.lifecycle.birth} for the details. | |
ba375a80 MW |
639 | \item[@|initarg_class|] A symbol naming the Lisp class to use to represent |
640 | the initarg. Only permitted if @|initarg| is also set. | |
8399be6f MW |
641 | \end{description} |
642 | ||
1f7d590d MW |
643 | An @<initializer>, if present, is treated as if a separate |
644 | @<initializer-item> containing the slot name and initializer were present. | |
645 | For example, | |
7119ea4e | 646 | \begin{prog} |
020b9e2b | 647 | [nick = eg] \\ |
fd040f06 | 648 | class Example: Super \{ \\ \ind |
020b9e2b | 649 | int foo = 17; \-\\ |
7119ea4e MW |
650 | \}; |
651 | \end{prog} | |
1f7d590d | 652 | means the same as |
7119ea4e | 653 | \begin{prog} |
020b9e2b | 654 | [nick = eg] \\ |
fd040f06 | 655 | class Example: Super \{ \\ \ind |
020b9e2b MW |
656 | int foo; \\ |
657 | eg.foo = 17; \-\\ | |
7119ea4e MW |
658 | \}; |
659 | \end{prog} | |
1f7d590d | 660 | |
68a620ab | 661 | \subsubsection{Initializer items} |
1f7d590d | 662 | \begin{grammar} |
391c5a34 | 663 | <initializer-item> ::= @["class"@] <list>$[\mbox{@<slot-initializer>}]$ ";" |
1f7d590d | 664 | |
b2983f35 | 665 | <slot-initializer> ::= <dotted-name> @["=" <initializer>@] |
1f7d590d | 666 | |
054e8f8f | 667 | <initializer> ::= <c-fragment> |
1f7d590d MW |
668 | \end{grammar} |
669 | ||
670 | An @<initializer-item> provides an initial value for one or more slots. If | |
ba375a80 | 671 | prefixed by @|class|, then the initial values are for class slots (i.e., |
1f7d590d MW |
672 | slots of the class object itself); otherwise they are for instance slots. |
673 | ||
bc7dff5c MW |
674 | The first component of the @<dotted-name> must be the nickname of one of the |
675 | class's superclasses (including itself); the second must be the name of a | |
676 | slot defined in that superclass. | |
1f7d590d | 677 | |
8399be6f MW |
678 | Properties: |
679 | \begin{description} | |
ba375a80 | 680 | \item[@|initializer_class|] A symbol naming the Lisp class to use to |
8399be6f | 681 | represent the initializer. |
ba375a80 | 682 | \item[@|initarg|] An identifier naming an initialization argument which can |
8399be6f MW |
683 | be used to provide a value for the slot. See |
684 | \xref{sec:concepts.lifecycle.birth} for the details. An initializer item | |
685 | must have either an @|initarg| property, or an initializer expression, or | |
686 | both. | |
ba375a80 MW |
687 | \item[@|initarg_class|] A symbol naming the Lisp class to use to represent |
688 | the initarg. Only permitted if @|initarg| is also set. | |
8399be6f | 689 | \end{description} |
b2983f35 MW |
690 | |
691 | Each class may define at most one initializer item with an explicit | |
692 | initializer expression for a given slot. | |
693 | ||
694 | \subsubsection{Initarg items} | |
695 | \begin{grammar} | |
696 | <initarg-item> ::= | |
697 | "initarg" | |
698 | @<declaration-specifier>^+ | |
699 | <list>$[\mbox{@<init-declarator>}]$ ";" | |
700 | \end{grammar} | |
0e5c0b9e MW |
701 | Properties: |
702 | \begin{description} | |
ba375a80 | 703 | \item[@|initarg_class|] A symbol naming the Lisp class to use to represent |
0e5c0b9e MW |
704 | the initarg. |
705 | \end{description} | |
b2983f35 | 706 | |
a42893dd MW |
707 | \subsubsection{Fragment items} |
708 | \begin{grammar} | |
709 | <fragment-item> ::= <fragment-kind> "{" <c-fragment> "}" | |
710 | ||
711 | <fragment-kind> ::= "init" | "teardown" | |
712 | \end{grammar} | |
713 | ||
68a620ab | 714 | \subsubsection{Message items} |
1f7d590d MW |
715 | \begin{grammar} |
716 | <message-item> ::= | |
391c5a34 MW |
717 | @<declaration-specifier>^+ |
718 | <keyword-declarator>$[\mbox{@<identifier>}]$ | |
719 | @[<method-body>@] | |
1f7d590d | 720 | \end{grammar} |
8399be6f MW |
721 | Properties: |
722 | \begin{description} | |
ba375a80 | 723 | \item[@|message_class|] A symbol naming the Lisp class to use to represent |
8399be6f | 724 | the message. |
ba375a80 | 725 | \item[@|combination|] A keyword naming the aggregating method combination to |
8399be6f | 726 | use. |
ba375a80 | 727 | \item[@|most_specific|] A keyword, either @`first' or @`last', according to |
8399be6f MW |
728 | whether the most specific applicable method should be invoked first or |
729 | last. | |
730 | \end{description} | |
731 | ||
732 | Properties for the @|custom| aggregating method combination: | |
733 | \begin{description} | |
ba375a80 | 734 | \item[@|retvar|] An identifier for the return value from the effective |
8399be6f MW |
735 | method. The default is @|sod__ret|. Only permitted if the message return |
736 | type is not @|void|. | |
ba375a80 | 737 | \item[@|valvar|] An identifier holding each return value from a direct method |
8399be6f | 738 | in the effective method. The default is @|sod__val|. Only permitted if |
ba375a80 MW |
739 | the method return type (see @|methty| below) is not @|void|. |
740 | \item[@|methty|] A C type, which is the return type for direct methods of | |
054e8f8f | 741 | this message. The default is the return type of the message. |
ba375a80 | 742 | \item[@|decls|] A code fragment containing declarations to be inserted at the |
8399be6f | 743 | head of the effective method body. The default is to insert nothing. |
ba375a80 | 744 | \item[@|before|] A code fragment containing initialization to be performed at |
8399be6f MW |
745 | the beginning of the effective method body. The default is to insert |
746 | nothing. | |
ba375a80 | 747 | \item[@|empty|] A code fragment executed if there are no primary methods; |
b07535d8 MW |
748 | it should usually store a suitable (identity) value in @<retvar>. The |
749 | default is not to emit an effective method at all if there are no primary | |
750 | methods. | |
ba375a80 MW |
751 | \item[@|first|] A code fragment to set the return value after calling the |
752 | first applicable direct method. The default is to use the @|each| | |
8399be6f | 753 | fragment. |
ba375a80 MW |
754 | \item[@|each|] A code fragment to set the return value after calling a direct |
755 | method. If @|first| is also set, then it is used after the first direct | |
8399be6f MW |
756 | method instead of this. The default is to insert nothing, which is |
757 | probably not what you want. | |
ba375a80 | 758 | \item[@|after|] A code fragment inserted at the end of the effective method |
8399be6f | 759 | body. The default is to insert nothing. |
ba375a80 | 760 | \item[@|count|] An identifier naming a variable to be declared in the |
8399be6f MW |
761 | effective method body, of type @|size_t|, holding the number of applicable |
762 | methods. The default is not to provide such a variable. | |
763 | \end{description} | |
1f7d590d | 764 | |
68a620ab | 765 | \subsubsection{Method items} |
1f7d590d MW |
766 | \begin{grammar} |
767 | <method-item> ::= | |
391c5a34 MW |
768 | @<declaration-specifier>^+ |
769 | <keyword-declarator>$[\mbox{@<dotted-name>}]$ | |
ea08dc56 | 770 | <method-body> |
1f7d590d MW |
771 | |
772 | <method-body> ::= "{" <c-fragment> "}" | "extern" ";" | |
773 | \end{grammar} | |
8399be6f MW |
774 | Properties: |
775 | \begin{description} | |
ba375a80 | 776 | \item[@|method_class|] A symbol naming the Lisp class to use to represent |
8399be6f | 777 | the direct method. |
ba375a80 | 778 | \item[@|role|] A keyword naming the direct method's rôle. For the built-in |
8399be6f MW |
779 | `simple' message classes, the acceptable rôle names are @|before|, |
780 | @|after|, and @|around|. By default, a primary method is constructed. | |
781 | \end{description} | |
1f7d590d | 782 | |
1f7d590d MW |
783 | %%%----- That's all, folks -------------------------------------------------- |
784 | ||
785 | %%% Local variables: | |
786 | %%% mode: LaTeX | |
787 | %%% TeX-master: "sod.tex" | |
788 | %%% TeX-PDF-mode: t | |
789 | %%% End: |