Problem with --enable-keyword and --enable-predefined-identifier

Waldek Hebisch hebisch at math.uni.wroc.pl
Sun Jul 23 04:31:09 CEST 2006


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:
> 
>  1. 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}").
> 
>  2. 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.

-- 
                              Waldek Hebisch
hebisch at math.uni.wroc.pl 





More information about the Gpc mailing list