J. David Bryan wrote:
On 21 Jul 2006 at 3:51, Waldek Hebisch wrote:
However, "--enable-keyword" just causes GPC to recognize given keyword, but otherwise do not influence the accepted language. Since by default all keywords are allowed and dialect choice just rejects constucts outside given dialect, "--enable-keyword" in fact can not enable a new construct -- it can only turn on previously disabled keyword.
I am confused by this. In test program "fjf733e.pas", we have:
{$enable-keyword pow} {$classic-pascal}
program fjf733e (Output);
begin if 2 pow 3 = 8 then WriteLn ('OK') else WriteLn ('failed') end.
This works, but why does it work? "pow" is an operator, and "asm" is a statement keyword, but why does that matter? It appears to me that this changes the dialect from CP to CP-plus-pow-from-EP. I don't understand why:
{$enable-keyword pow}
works, but:
{$enable-keyword asm}
does not work. Shouldn't the above program give "error: `pow' is an extension of Extended Pascal"?
To be more precise: "{$enable-keyword asm}" just causes `asm' to be recognized as the keyword. Other checks are unaffected by "enable-keyword". Apparently, for `pow' no more checks is used, by for `asm' an extera check was active.
In particular, builtin routines remain effectively disabled (and "ParamCount" is a routine (function)). "Cardinal" works since it is a type.
This also is confusing. In the presence of a language restriction, some predefined identifiers may be enabled (types), but others (built-in routines) cannot. Some keywords ("pow", "attribute") may be enabled, but others ("asm") cannot.
The following patch enables "asm" keyword and builtin procedures (but see below):
Index: predef.c =================================================================== RCS file: /mn/a8/cvsroot/gpc/p/predef.c,v retrieving revision 1.16 diff -u -p -r1.16 predef.c --- predef.c 7 Apr 2006 00:00:50 -0000 1.16 +++ predef.c 22 Jul 2006 20:14:48 -0000 @@ -1242,7 +1242,9 @@ build_predef_call (int r_num, tree apar) r_name = predef_table[i].idname; if (!r_name) r_name = predef_table[i].alias_name; gcc_assert (r_name); +#if 0 chk_dialect_name (r_name, predef_table[i].dialect); +#endif
if (r_num == p_Exit && apar) { Index: statements.c =================================================================== RCS file: /mn/a8/cvsroot/gpc/p/statements.c,v retrieving revision 1.10 diff -u -p -r1.10 statements.c --- statements.c 6 Apr 2006 04:58:33 -0000 1.10 +++ statements.c 22 Jul 2006 20:12:33 -0000 @@ -74,8 +74,10 @@ pascal_expand_asm_operands (tree string, { if (co->pascal_dialect & B_D_M_PASCAL) gpc_warning ("GPC and Borland Pascal have different `asm' syntax"); +#if 0 else chk_dialect ("`asm' is", B_D_M_PASCAL); +#endif }
string = combine_strings (string, 2);
I am not sure if we should change what GPC is doing.
I believe that gpc should either allow "enable" only if a prior "disable" has been done, or allow "enable" without restriction, or document the specific cases where "enable" is allowed. The first option would be your original intent. The second would be most flexible. The third would at least eliminate the confusion where some "enables" are allowed and others are not.
Let me explain some technical problems: on low level "enable" always "works". That is when GPC reads your program and the keyword is disabled GPC will read a name as oridinary identifier. Similarely for builtin names GPC will forget about builtin meaning (so the name probably will be reported as undefined). If the keyword is enabled GPC will treat it as a keyword (to be more precise: most keywords are recognized as a keyword only when the keyword is allowed by the grammar, otherwise are still treated as identifiers). However, GPC applies a large number of validity checks to the program, and the other checks still may reject the program.
As explained below it is not clear how (if) "enable-keyword" should interact with other checks. Even if one can find a resonable specification implementing it would probably require a lot of work -- personally I think it is not worth the effort.
I am reluctant to document existing behaviour, since it mostly reflects various implementation details which otherwise should be irrelevant for the user. Worse, GPC is constantly changing and such documentation would quicky be out of date or prevent some needed change.
I am tempted to say that the exact effect of enabling a keyword which otherwise would be disabled by dialect settings is explicitly undocumented. Typically I prefer to exactly specify meaning of the souce code. However, compiler options like "enable-keyword" are a tool to tweak around some specific problems. Moreover, the potential for error is limited since the effect (failure or success of the compilation) should be immediatly visble (of course, there is a problem with future compiler versions).
...for keywords things are more tricky: a set of dialects in which a constuct is valid may be smaller then set of dialects in which keywords involved in the constuct are valid so we still need dialect checks.
Are you thinking of cases such as "packed array" is CP, but "packed 0..3" is not? Or "a and b" is CP, but "a and 1" is not?
Yes.
So, I am not sure how useful would be ability to enable all constructs involwing given keyword.
The reason I was trying to restrict the dialect and then enable certain keywords and predefined identifiers is that changing the dialect from EP to GP changes the semantics of some EP constructs. For instance, changing to GP means that strings are no longer padded for comparisons, so:
var s : packed array [1..6] of char; [...]
s := 'GPC'; if s = 'GPC' then ...
...fails. Also:
var i, j: integer; [...]
i := 1; j := 2; writeln (i, j);
prints "12". So I cannot simply write EP with a few extensions; I must also remember all of the semantic changes that go along with selecting GP.
There are two alternate ways I can accomplish this:
Choose the GP dialect and either program around the semantic changes ("if s = 'GPC ' then") or use compiler directives to restore EP semantics ("{$no-exact-compare-strings}").
Choose the EP dialect and bracket each extension with "{$gnu-pascal}" and "{$extended-pascal}".
But if I could choose EP and selectively enable the extensions, it would be simpler, and it would document at the start of the source file exactly what extensions were used.
Yes, I understand your goal. But I am affraid that keyword-level control is too crude.