Skip to content

Relaxed declarations

This is an announcement of an upcoming feature.

C declaration syntax, when you get used to it, is quite comfortable, but in is not without issues. One of its problems is inconsistency: the basic schema of declaration-specifiers stating the base type, followed by a comma-separated list of declarators, with variable name wrapped in a mixture of type operators, is convenient, and used for declaring structure and union members as well as variables. However, a different schema is used for function parameters, where each parameter is specified completely separately from the previous one:

/* base type followed by list of declarators for int-derived types: */
int i, *ip, **ipp, (*pfi)();

/* have to repeat 'int' base type for each parameter: */
extern void foo(int i, int *ip, int **ipp, int (*pfi)()); 

/* but can't repeat it for each variable: */
int i, int *ip, int **ipp, int (*pfi)()); /* error! */

/* this doesn't work either: */
extern void foo(int i, *ip, **ipp, (*pfi)()); 

This inconsistency is not annoying, but complicates parsing; it also inhibits some kinds of parsing for WCPL-specific syntactic constructs, so we have decided to relax the function parameter syntax to bring it in line with variable declarations syntax, and vice versa.

The relaxed syntax uses the same approach for both lists of declarations. The relaxed form of declaration list starts with declaration-specifiers stating the base type, followed by a comma-separated list of declarators (as in C syntax for variables and members), but, after each comma, a new base type may be introduced, serving one or more subsequent declarations having just declarators and no base type of their own:

/* WCPL: base type can be switched mid-list: */
int i, *ip, double d, **dpp, (*pfd)(), char c, *cp;

/* WCPL: no need to repeat shared base type for sibling parameters: */
extern void foo(int i, *ip, double d, **dpp, (*pfd)(), char c, *cp); 

Also WCPL structure and union declarations are allowed to omit the semicolon after the last member declaration. As declarations are relaxed too, the following syntax becomes legal:

/* WCPL: struct/union syntax can omit semicolons: */
struct { int i, *ip, char c, *cp, double d } foo;

As you can see, the relaxed format is backward-compatible with C, but does not enforce C-specific dichotomy between variable/member declarations and parameter lists. Naturally, any new feature can be abused; the fact that in typedefs and forward declarations of functions parameter names are optional, allows for these cryptic forms:

/* WCPL: minimalistic declaration with anonymous parameters: */
extern void foo(int, *, **, (*)()); 

/* same declaration in its traditional form: */
extern void foo(int i, int *ip, int **ipp, int (*pfi)()); 

Taken to the extreme, this may lead to something even more cryptic:

/* WCPL: truly bizarre declaration with anonymous parameters: */
extern void foo(int,,,); 

/* same declaration in its traditional form: */
extern void foo(int, int, int, int); 

All curiosities aside, relaxing declarations in this way will allow us to parse the upcoming syntax for multiple return values while still using single-token lookahead. More on this later…