The syntax for declaring and defining C++ functions is the same as in C++ [ANSI95] with some additions. See section 6 Function Specifications for the syntax of fun-spec-body, and for how to specify (and not just declare or define the interface of) a function. The syntax for a compound-statement is as in C++ (see Section 17.6 of [Ellis-Stroustrup90][ANSI95]), except that traits can be passed to higher-order functions (see section 6.13 Specifying Higher-Order Functions for the syntax of using-trait-list), and Larch/C++ adds specification-statements (see section 6.14 Behavior Programs, for these), and annotated-iteration-statements (see section 6.15 Annotated Iteration Statements) to C++. Since, aside from these additions, the syntax of statements and expressions is identical to that in C++, it is not given in full here.
function-definition ::= fun-interface [ fun-spec-body ] [ ctor-initializer ] fun-body
| fun-interface [ fun-spec-body ] function-try-block
fun-interface ::= [ decl-specifier-seq ] declarator
| [ decl-qualifier-seq ] ctor-declarator
| [ decl-qualifier-seq ] special-function-declarator
decl-qualifier ::= storage-class-specifier | function-specifier | friend | typedef
decl-qualifier-seq ::= decl-qualifier [ decl-qualifier ] ...
ctor-initializer ::= : mem-initializer [ , mem-initializer ] ...
mem-initializer ::= mem-initializer-id ( expression-list )
mem-initializer-id ::= complete-class-name | identifier
expression-list ::= expression [ , expression ] ...
expression ::= exactly as in C++, but add the following
postfix-expression ::= postfix-expression ( [ expression-list ] [ using-trait-list ] )
| simple-type-name ( [ expression-list ] [ using-trait-list ] )
function-try-block ::= try [ ctor-initializer ] fun-body handler-seq
handler-seq ::= handler [ handler ] ...
handler ::= catch ( exception-declaration ) compound-statement
exception-declaration ::= type-specifier-seq declarator
| type-specifier-seq [ abstract-declarator ]
| `...'
compound-statement ::= { statement-seq }
statement-seq ::= statement [ statement ] ...
statement ::= as in C++, but add ...
| specification-statement
| annotated-iteration-statement
ctor-declarator ::= complete-class-name param-qualifier
| complete-template-class-name param-qualifier
complete-template-class-name ::= [ :: ] [ nested-name-specifier ] template-class-name
special-function-declarator ::= [ :: ] nested-name-specifier dtor-name param-qualifier
| dtor-name param-qualifier | declarator-id param-qualifier
dtor-name ::= ~ original-class-name | ~ template-class-name
fun-body ::= compound-statement
The form of a fun-interface starting with an optional explicit
followed by a complete-class-name or a template-ctor-name
is for the constructor of a class (see section 7.2.1 Constructors).
(The use of explicit in constructors is a feature of the
proposed C++ standard [Stroustrup95] [ANSI95].)
(See section 7.2.2 Destructors for how to declare and specify destructors.
See section 5.4 Declarators for the syntax of destructor names,
which is unqualified-id.)
A normal fun-interface has the following form, just as in C++ (see Section r.8.2.5 of [Stroustrup90]).
[ decl-specifier-seq ] declarator([ parameter-declaration-clause ])[ cv-qualifier-seq ] [ exception-decl ]
That is, one specifies the function's return type
(in the decl-specifier-seq and parts of the declarator),
name (in the declarator),
and formal arguments (in the parameter-declaration-clause).
The use of const and volatile
in the cv-qualifier-seq
is restricted as in C++
(see Section r.8.2.5 of [Stroustrup90]).
Finally, one can declare the exceptions that may be raised
by the function in the optional exception-decl
(see section 6.11 Exceptions).
See section 5.4 Declarators for details of the syntax.
The syntax for declaring the arguments to a C++ function is also the same as in C++, with a slight addition. See section 5.4 Declarators for the syntax of declarator, which is used to declare a function interfaces by using a param-qualifier. The syntax for a param-qualifier allows one to specify what traits should also be passed to the function. See section 6.13 Specifying Higher-Order Functions for how to use this extension.
parameter-declaration-clause ::= parameter-declaration-list [ `...' ] | `...' | parameter-declaration-list,`...' parameter-declaration-list ::= parameter-declaration [,parameter-declaration ] ... parameter-declaration ::= decl-specifier-seq declarator [ parameter-initializer ] | decl-specifier-seq [ abstract-declarator ] [ parameter-initializer ] parameter-initializer ::==assignment-expression assignment-expression ::= exactly as in C++
Note that the three dots in `...' are not a meta-notation;
they form a single token in the C++ syntax
(see Section 8.2.5 in [Ellis-Stroustrup90]).
For example, one would write:
int printf(char *fmt, ...);
The sort of a global function name is ConstObj[cpp_function].
Consider the following.
Declaration Name Its Sort (when used as a global variable) ------------- ---- ----------------------------------------- int f(int i); f ConstObj[cpp_function]
That f has sort ConstObj[cpp_function] means that
it is an object whose abstract value cannot be changed.
C++ functions used as global variables are modeled as objects
because one can take their address.
A declaration such as int f(int i) makes Larch/C++ implicitly
use the trait cpp_function.
See section 11.12 Function Types for details of the trait that defines this sort.
In a class, a function is called a member function.
If the declaration of f appeared in a class,
it would have sort ConstObj[cpp_member_function]
when used as a global variable.
Such a declaration makes Larch/C++ implicitly
use the trait cpp_member_function.
See section 11.12 Function Types for details on this trait.
See section 6.13 Specifying Higher-Order Functions for how to specify functions that take and return pointers to functions.
Go to the first, previous, next, last section, table of contents.