src/method-impl.lisp, etc.: Add a `readonly' message property.
[sod] / doc / syntax.tex
index 7eed24f..72329a4 100644 (file)
@@ -51,20 +51,20 @@ could be a token.
 
 <id-start-char> ::= <alpha-char> | "_"
 
 
 <id-start-char> ::= <alpha-char> | "_"
 
-<id-body-char> ::= <id-start-char> @! <digit-char>
+<id-body-char> ::= <id-start-char> | <digit-char>
 
 
-<alpha-char> ::= "A" | "B" | \dots\ | "Z"
-\alt "a" | "b" | \dots\ | "z"
-\alt <extended-alpha-char>
+<alpha-char> ::= "A" | "B" | $\cdots$ | "Z"
+  | "a" | "b" | $\cdots$ | "z"
+  | <extended-alpha-char>
 
 <digit-char> ::= "0" | <nonzero-digit-char>
 
 
 <digit-char> ::= "0" | <nonzero-digit-char>
 
-<nonzero-digit-char> ::= "1" | "2" $| \ldots |$ "9"
+<nonzero-digit-char> ::= "1" | "2" | $\cdots$ | "9"
 \end{grammar}
 
 The precise definition of @<alpha-char> is left to the function
 \end{grammar}
 
 The precise definition of @<alpha-char> is left to the function
-\textsf{alpha-char-p} in the hosting Lisp system.  For portability,
-programmers are encouraged to limit themselves to the standard ASCII letters.
+@|alpha-char-p| in the hosting Lisp system.  For portability, programmers are
+encouraged to limit themselves to the standard ASCII letters.
 
 There are no reserved words at the lexical level, but the higher-level syntax
 recognizes certain identifiers as \emph{keywords} in some contexts.  There is
 
 There are no reserved words at the lexical level, but the higher-level syntax
 recognizes certain identifiers as \emph{keywords} in some contexts.  There is
@@ -80,11 +80,11 @@ level.
 
 <char-literal> ::= "'" <char-literal-char> "'"
 
 
 <char-literal> ::= "'" <char-literal-char> "'"
 
-<string-literal-char> ::= any character other than "\\" or "\""
-\alt "\\" <char>
+<string-literal-char> :: "\\" <char>
+  | any character other than "\\" or "\""
 
 
-<char-literal-char> ::= any character other than "\\" or "'"
-\alt "\\" <char>
+<char-literal-char> :: "\\" <char>
+  | any character other than "\\" or "'"
 
 <char> ::= any single character
 \end{grammar}
 
 <char> ::= any single character
 \end{grammar}
@@ -101,25 +101,25 @@ discouraged.
 
 \begin{grammar}
 <integer-literal> ::= <decimal-integer>
 
 \begin{grammar}
 <integer-literal> ::= <decimal-integer>
-\alt <binary-integer>
-\alt <octal-integer>
-\alt <hex-integer>
+  | <binary-integer>
+  | <octal-integer>
+  | <hex-integer>
 
 <decimal-integer> ::= "0" | <nonzero-digit-char> @<digit-char>^*
 
 
 <decimal-integer> ::= "0" | <nonzero-digit-char> @<digit-char>^*
 
-<binary-integer> ::= "0" @("b"|"B"@) @<binary-digit-char>^+
+<binary-integer> ::= "0" @("b" | "B"@) @<binary-digit-char>^+
 
 <binary-digit-char> ::= "0" | "1"
 
 
 <binary-digit-char> ::= "0" | "1"
 
-<octal-integer> ::= "0" @["o"|"O"@] @<octal-digit-char>^+
+<octal-integer> ::= "0" @["o" | "O"@] @<octal-digit-char>^+
 
 
-<octal-digit-char> ::= "0" | "1" $| \ldots |$ "7"
+<octal-digit-char> ::= "0" | "1" | $\cdots$ | "7"
 
 
-<hex-integer> ::= "0" @("x"|"X"@) @<hex-digit-char>^+
+<hex-integer> ::= "0" @("x" | "X"@) @<hex-digit-char>^+
 
 <hex-digit-char> ::= <digit-char>
 
 <hex-digit-char> ::= <digit-char>
-\alt "A" | "B" | "C" | "D" | "E" | "F"
-\alt "a" | "b" | "c" | "d" | "e" | "f"
+  | "A" | "B" | "C" | "D" | "E" | "F"
+  | "a" | "b" | "c" | "d" | "e" | "f"
 \end{grammar}
 
 Sod understands only integers, not floating-point numbers; its integer syntax
 \end{grammar}
 
 Sod understands only integers, not floating-point numbers; its integer syntax
@@ -130,15 +130,16 @@ binary.  However, length and signedness indicators are not permitted.
 \subsection{Punctuation} \label{sec:syntax.lex.punct}
 
 \begin{grammar}
 \subsection{Punctuation} \label{sec:syntax.lex.punct}
 
 \begin{grammar}
-<punctuation> ::= any nonalphanumeric character other than "_", "\"" or "'"
+<punctuation> ::= "<<" | ">>" | "||" | "&&"
+  | "<=" | ">=" | "==" | "!=" | "\dots"
+\alt any nonalphanumeric character other than "_", "\"", or "'"
 \end{grammar}
 
 
 \subsection{Comments} \label{sec:syntax.lex.comment}
 
 \begin{grammar}
 \end{grammar}
 
 
 \subsection{Comments} \label{sec:syntax.lex.comment}
 
 \begin{grammar}
-<comment> ::= <block-comment>
-\alt <line-comment>
+<comment> ::= <block-comment> | <line-comment>
 
 <block-comment> ::=
   "/*"
 
 <block-comment> ::=
   "/*"
@@ -323,7 +324,7 @@ defined in the built-in module.
 <abstract-declarator> ::= <declarator>$[\epsilon, \mbox{@<argument-list>}]$
 
 <argument-declarator> ::=
 <abstract-declarator> ::= <declarator>$[\epsilon, \mbox{@<argument-list>}]$
 
 <argument-declarator> ::=
-  <declarator>$[\mbox{@<identifier> @! $\epsilon$}, \mbox{@<argument-list>}]$
+  <declarator>$[\mbox{@<identifier> | $\epsilon$}, \mbox{@<argument-list>}]$
 
 <simple-declarator> ::=
   <declarator>$[\mbox{@<identifier>}, \mbox{@<argument-list>}]$
 
 <simple-declarator> ::=
   <declarator>$[\mbox{@<identifier>}, \mbox{@<argument-list>}]$
@@ -351,7 +352,7 @@ keyword arguments.
   @[<list>$[\mbox{@<argument>}]$@]
   "?" @[<list>$[\mbox{@<keyword-argument>}]$@]
 
   @[<list>$[\mbox{@<argument>}]$@]
   "?" @[<list>$[\mbox{@<keyword-argument>}]$@]
 
-<method-argument-list> ::= <argument-list> @! <keyword-argument-list>
+<method-argument-list> ::= <argument-list> | <keyword-argument-list>
 
 <dotted-name> ::= <identifier> "." <identifier>
 
 
 <dotted-name> ::= <identifier> "." <identifier>
 
@@ -367,18 +368,53 @@ keyword arguments.
 
 <property> ::= <identifier> "=" <expression>
 
 
 <property> ::= <identifier> "=" <expression>
 
-<expression> ::= <term> | <expression> "+" <term> | <expression> "--" <term>
+<expression> ::= <logical-or>
 
 
-<term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor>
+<logical-or> ::= <logical-and>
+  | <logical-or> "||" <logical-and>
 
 
-<factor> ::= <primary> | "+" <factor> | "--" <factor>
+<logical-and> ::= <bitwise-or>
+  | <logical-and> "&&" <bitwise-or>
+
+<bitwise-or> ::= <bitwise-xor>
+  | <bitwise-or> "|" <bitwise-xor>
+
+<bitwise-xor> ::= <bitwise-and>
+  | <bitwise-xor> "^" <bitwise-and>
+
+<bitwise-and> ::= <equality>
+  | <bitwise-and> "&" <equality>
+
+<equality> ::= <ordering>
+  | <equality> "==" <ordering>
+  | <equality> "!=" <ordering>
+
+<ordering> ::= <shift>
+  | <ordering> "<" <shift>
+  | <ordering> "<=" <shift>
+  | <ordering> ">=" <shift>
+  | <ordering> ">" <shift>
+
+<shift> ::= <additive>
+  | <shift> "<<" <additive>
+  | <shift> ">>" <additive>
+
+<additive> ::= <term>
+  | <additive> "+" <term>
+  | <additive> "--" <term>
+
+<term> ::= <factor>
+  | <term> "*" <factor>
+  | <term> "/" <factor>
+
+<factor> ::= <primary>
+  | "!" <factor> | "~" factor
+  | "+" <factor> | "--" <factor>
 
 <primary> ::=
      <integer-literal> | <string-literal> | <char-literal> | <identifier>
 
 <primary> ::=
      <integer-literal> | <string-literal> | <char-literal> | <identifier>
-\alt "<" <plain-type> ">"
-\alt "{" <c-fragment> "}"
-\alt "?" <s-expression>
-\alt "(" <expression> ")"
+\alt "<" <plain-type> ">" | "{" <c-fragment> "}" | "?" <s-expression>
+  | "(" <expression> ")"
 \end{grammar}
 
 \emph{Property sets} are a means for associating miscellaneous information
 \end{grammar}
 
 \emph{Property sets} are a means for associating miscellaneous information
@@ -431,8 +467,8 @@ operators.
 Finally, an S-expression preceded by @|?| causes the expression to be read in
 the current package (which is always @|sod-user| at the start of a module)
 and immediately evaluated (using @|eval|); the resulting value is converted
 Finally, an S-expression preceded by @|?| causes the expression to be read in
 the current package (which is always @|sod-user| at the start of a module)
 and immediately evaluated (using @|eval|); the resulting value is converted
-into a property value using the \descref{decode-property}[generic
-function]{gf}.
+into a property value using the \descref{gf}{decode-property}[generic
+function].
 
 
 \subsection{Property output types and coercions}
 
 
 \subsection{Property output types and coercions}
@@ -440,8 +476,8 @@ function]{gf}.
 
 When a property value is inspected by the Sod translator, or an extension, it
 is \emph{coerced} so as to conform to a requested output type.  This coercion
 
 When a property value is inspected by the Sod translator, or an extension, it
 is \emph{coerced} so as to conform to a requested output type.  This coercion
-process is performed by the \descref{coerce-property-value}[generic
-function]{gf}, and additional output types and coercions can be defined by
+process is performed by the \descref{gf}{coerce-property-value}[generic
+function], and additional output types and coercions can be defined by
 extensions.  The built-in output types coercions, from the value types listed
 above, are as follows.
 
 extensions.  The built-in output types coercions, from the value types listed
 above, are as follows.
 
@@ -462,10 +498,10 @@ above, are as follows.
 
 \item The @|boolean| output type denotes a boolean value, which may be either
   true or false.  A value of type @|id| is considered true if it is @|true|,
 
 \item The @|boolean| output type denotes a boolean value, which may be either
   true or false.  A value of type @|id| is considered true if it is @|true|,
-  @|t|, @|yes|, @|on|, or @|verily|; or false if it is @|false|, @|nil|,
-  @|no|, @|off|, or @|nowise|; it is erroneous to provide any other
-  identifier where a boolean value is wanted.  A value of type @|int| is
-  considered true if it is nonzero, or false if it is zero.
+  @|t|, @|yes|, @|on|, @|yup|, or @|verily|; or false if it is @|false|,
+  @|nil|, @|no|, @|off|, @|nope|, or @|nowise|; it is erroneous to provide
+  any other identifier where a boolean value is wanted.  A value of type
+  @|int| is considered true if it is nonzero, or false if it is zero.
 
 \item The @|symbol| output type denotes a Lisp symbol.
 
 
 \item The @|symbol| output type denotes a Lisp symbol.
 
@@ -476,7 +512,7 @@ above, are as follows.
   upper; if the name contains letters of both cases, then it is not changed.
   For example, @|foo45| becomes @|FOO45|, or \emph{vice-versa}; but @|Splat|
   remains as it is.  Second, the name is subjected to \emph{separator
   upper; if the name contains letters of both cases, then it is not changed.
   For example, @|foo45| becomes @|FOO45|, or \emph{vice-versa}; but @|Splat|
   remains as it is.  Second, the name is subjected to \emph{separator
-    switching}: all underscores in the name are replaced with hyphens (and
+  switching}: all underscores in the name are replaced with hyphens (and
   \emph{vice-versa}, though hyphens aren't permitted in identifiers in the
   first place).  Finally, the resulting name is interned in the current
   package, which will usually be @|sod-user| unless changed explicitly by the
   \emph{vice-versa}, though hyphens aren't permitted in identifiers in the
   first place).  Finally, the resulting name is interned in the current
   package, which will usually be @|sod-user| unless changed explicitly by the
@@ -550,9 +586,9 @@ A search is made for a module source file as follows.
 \begin{itemize}
 \item The module name @<string> is converted into a filename by appending
   @`.sod', if it has no extension already.\footnote{%
 \begin{itemize}
 \item The module name @<string> is converted into a filename by appending
   @`.sod', if it has no extension already.\footnote{%
-    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
-    :type "SOD" :case :common))}, so exactly what this means varies
-    according to the host system.} %
+    Technically, what happens is @|(merge-pathnames name (make-pathname :type
+    "SOD" :case :common))|, so exactly what this means varies according to
+    the host system.} %
 \item The file is looked for relative to the directory containing the
   importing module.
 \item If that fails, then the file is looked for in each directory on the
 \item The file is looked for relative to the directory containing the
   importing module.
 \item If that fails, then the file is looked for in each directory on the
@@ -562,7 +598,7 @@ A search is made for a module source file as follows.
 \end{itemize}
 At this point, if the file has previously been imported, nothing further
 happens.\footnote{%
 \end{itemize}
 At this point, if the file has previously been imported, nothing further
 happens.\footnote{%
-  This check is done using \textsf{truename}, so it should see through simple
+  This check is done using @|truename|, so it should see through simple
   tricks like symbolic links.  However, it may be confused by fancy things
   like bind mounts and so on.} %
 
   tricks like symbolic links.  However, it may be confused by fancy things
   like bind mounts and so on.} %
 
@@ -579,23 +615,22 @@ A search is made for a Lisp source file as follows.
 \begin{itemize}
 \item The name @<string> is converted into a filename by appending @`.lisp',
   if it has no extension already.\footnote{%
 \begin{itemize}
 \item The name @<string> is converted into a filename by appending @`.lisp',
   if it has no extension already.\footnote{%
-    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
-    :type "LISP" :case :common))}, so exactly what this means varies
-    according to the host system.} %
+    Technically, what happens is @|(merge-pathnames name (make-pathname :type
+    "LISP" :case :common))|, so exactly what this means varies according to
+    the host system.} %
 \item A search is then made in the same manner as for module imports
   (\xref{sec:syntax-module}).
 \end{itemize}
 \item A search is then made in the same manner as for module imports
   (\xref{sec:syntax-module}).
 \end{itemize}
-If the file is found, it is loaded using the host Lisp's \textsf{load}
-function.
+If the file is found, it is loaded using the host Lisp's @|load| function.
 
 Note that Sod doesn't attempt to compile Lisp files, or even to look for
 existing compiled files.  The right way to package a substantial extension to
 the Sod translator is to provide the extension as a standard ASDF system (or
 similar) and leave a dropping @|foo-extension.lisp| in the module path saying
 something like
 
 Note that Sod doesn't attempt to compile Lisp files, or even to look for
 existing compiled files.  The right way to package a substantial extension to
 the Sod translator is to provide the extension as a standard ASDF system (or
 similar) and leave a dropping @|foo-extension.lisp| in the module path saying
 something like
-\begin{quote}
-  \textsf{(asdf:load-system :foo-extension)}
-\end{quote}
+\begin{prog}
+  (asdf:load-system :foo-extension)
+\end{prog}
 which will arrange for the extension to be compiled if necessary.
 
 (This approach means that the language doesn't need to depend on any
 which will arrange for the extension to be compiled if necessary.
 
 (This approach means that the language doesn't need to depend on any
@@ -635,14 +670,18 @@ declarations instead.
 
 \begin{grammar}
 <code-definition> ::=
 
 \begin{grammar}
 <code-definition> ::=
-  "code" <identifier> ":" <item-name> @[<constraints>@]
+  "code" <reason> ":" <item-name> @[<constraints>@]
   "{" <c-fragment> "}"
   "{" <c-fragment> "}"
+\alt
+  "code" <reason> ":" <constraints> ";"
+
+<reason> ::= <identifier>
 
 <constraints> ::= "[" <list>$[\mbox{@<constraint>}]$ "]"
 
 <constraint> ::= @<item-name>^+
 
 
 <constraints> ::= "[" <list>$[\mbox{@<constraint>}]$ "]"
 
 <constraint> ::= @<item-name>^+
 
-<item-name> ::= <identifier> @! "(" @<identifier>^+ ")"
+<item-name> ::= <identifier> | "(" @<identifier>^+ ")"
 \end{grammar}
 
 The @<c-fragment> will be output unchanged to one of the output files.
 \end{grammar}
 
 The @<c-fragment> will be output unchanged to one of the output files.
@@ -727,8 +766,9 @@ The @<list>$[\mbox{@<identifier>}]$ names the direct superclasses for the new
 class.  It is an error if any of these @<identifier>s does not name a defined
 class.  The superclass list is required, and must not be empty; listing
 @|SodObject| as your class's superclass is a good choice if nothing else
 class.  It is an error if any of these @<identifier>s does not name a defined
 class.  The superclass list is required, and must not be empty; listing
 @|SodObject| as your class's superclass is a good choice if nothing else
-seems suitable.  It's not possible to define a \emph{root class} in the Sod
-language: you must use Lisp to do this, and it's quite involved.
+seems suitable.  A class with no direct superclasses is called a \emph{root
+class}.  It is not possible to define a root class in the Sod language: you
+must use Lisp to do this, and it's quite involved.
 
 The @<properties> provide additional information.  The standard class
 properties are as follows.
 
 The @<properties> provide additional information.  The standard class
 properties are as follows.
@@ -863,6 +903,9 @@ Properties:
 \begin{description}
 \item[@|message_class|] A symbol naming the Lisp class to use to represent
   the message.
 \begin{description}
 \item[@|message_class|] A symbol naming the Lisp class to use to represent
   the message.
+\item[@|readonly|] A boolean indicating whether the message guarantees not to
+  modify its receiver.  If this is true, the receiver will be declared
+  @"const".
 \item[@|combination|] A keyword naming the aggregating method combination to
   use.
 \item[@|most_specific|] A keyword, either @`first' or @`last', according to
 \item[@|combination|] A keyword naming the aggregating method combination to
   use.
 \item[@|most_specific|] A keyword, either @`first' or @`last', according to