(but there might be a
-fenable-forward/-fdisable-forward in the future
should users wish to detect code using FORWARD or enforce
stricter PIM (Springer) compliance)
If there is a compiler switch for forward, then the switch should allow choosing between forward pragma and forward language extension.
Implementing forward as a pragma is the better approach in every possible aspect one might look at it.
(1) correctness
A forward directive does not change semantics, it is merely a directive to influence or control the compilation process. As such it is by definition a pragma and not language.
(2) simplicity of implementation
When using opening and closing delimiters for pragmas, such as is the case in Modula-2, be it '(*$...*)' or '<*...*>', the directive can be more easily skipped by the compiler without the need to do any syntax analysis. A compiler that builds an AST can simply skip the pragma at the lexical level, such as it would for any other unknown pragma.
And if the forward pragma syntax follows the format we used in M2R10, the forward pragma only contains the identifier of the entity for which it is a forward reference. Thus, even a single pass compiler would have less work to do to parse it as it only consists of two tokens.
(3) non-interference
A compiler that does not require nor implement a forward reference facility will automatically ignore a forward pragma because compilers ignore unknown pragmas by default. If it is language syntax however, such a compiler will generate syntax errors for every forward reference and they would have to be removed from the source code in order to compile the sources.
(4) less clutter
Very few compilers nowadays are single-pass. Building an AST has become the standard. But when the language has built in language syntax for forward references, all source code needs to have these unnecessary forward references which clutters the code. A simple pragma that only contains the identifiers of entities for which forward references are established constitutes far less clutter.
Ideally, the language would not provide neither a pragma, nor language syntax for forward references as this would completely remove any unnecessary clutter altogether. Single pass compilers could simply read the forward references from an external forward file. Alternatively, a preprocessing utility could read such a file and then merge the forward references into the source file for which it provides the forward references. A single pass compiler would then simply call this utility to have the forward references inserted before compiling a source file. Even in this case, a forward pragma would simplify the implementation both for the utility that inserts the references and the single pass compiler that will read the generated references in the output.
The whole forward business reminds me of the folly of octal literals, or even worse the synonym symbols '!' and '&' in ISO-Modula-2. Totally useless, but somebody thinks everything needs to be backwards compatible up to the Jurassic. It is far less effort to write a console utility that converts a source file to the outdated syntax, than to maintain the backwards compatibility for every such outdated syntax within the compiler.
BTW, the same applies to PIM2 support. It is far less effort to provide a console utility to convert a PIM2 source file to make it compilable on a PIM3 compiler, than building PIM support into a compiler.
Unfortunately, ISO M2 requires FORWARD in the language. If it wasn't for that, I would plead for removing any forward reference facility from the compiler altogether and handle backwards compatibility with a console utility instead. But since PIM doesn't actually specify a forward reference facility, perhaps it is worthwhile thinking about this approach for PIM. Using language syntax forward for the PIM mode as the default does not strike me as desirable. Readability of source code is far more important than avoiding that one time inconvenience of having to run your code through a preprocessing utility.
regards
benjamin