I noticed that the following FPC code (claimed to be BP compatible) is not accepted by GPC:
function b:string; begin b[1] := ' ' end;
Similarely FPC accepts:
type a = record i, j : integer end; function b(i, j: integer) : a; begin b.i := i; b.j := j end;
I do not know if we want to implement that feature, but (assuming it is really accepted by BP) we should list it as known incompatiblity.
On 26 May 2004 at 1:17, Waldek Hebisch wrote:
I noticed that the following FPC code (claimed to be BP compatible) is not accepted by GPC:
function b:string; begin b[1] := ' ' end;
BP accepts this, and so does Delphi. I agree that GPC should too.
GPC accepts this: function b:string; begin result[1] := ' ' end;
Similarely FPC accepts:
type a = record i, j : integer end; function b(i, j: integer) : a; begin b.i := i; b.j := j end;
BP doesn't accept this. If gives this error: "Error 34: Invalid function result type."
However, Delphi accepts it. GPC doesn't. But GPC accepts this: function b(i, j: integer) : a; begin result.i := i; result.j := j end;
So, GPC is nearly there already.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
But GPC accepts this: function b(i, j: integer) : a; begin result.i := i; result.j := j end;
So, GPC is nearly there already.
Not really. The case with result-variables, whether implicit (`Result' in Delphi) or explicit (in EP etc.), is quite clear because they always have the same meaning.
The question is the interpretation of the function-identifier in absence of a result-variable. It can either be a recursive call or the assignment of the function result.
The ISO standards are clear (AFAICS) that only if the function-identifier is the direct target of an assignment-statement, it's the assignment of the function result.
BP seems to extend this to cases such as `function-identifier[index]' and (Delphi) `function-identifier.fieldname' which are somewhat harmless because they'd be invalid otherwise (expressions that are no "lvalues" can't occur at the beginning of a statement).
I don't know what the exact rules are that BP uses. Perhaps it assumes that whenever the function-identifier appears at the beginning of a statement, it's meant as the assignment of (a component of) the function result.
This rule becomes wrong in cases such as `function-identifier^', when compared to Pascal semantics, because `function-identifier^' is an lvalue and is therefore a valid beginning of an assignment-statement involving a recursive call. As you reported, Delphi doesn't do it anymore.
Anyway, before deciding what to do, we'll have to know how other compilers behave exactly. Since BP has restrictions on result types, there aren't much cases that can occur (strings and pointers may be the only questionable ones).
In Delphi, as in GPC, function result types can be almost anything, so we'll need to know in which cases it's meant to be the assignment of the function result. Perhaps if the target of an assignment-statement is a function-identifier followed by a sequence of index (`[...]') and component access (`.field') specifications (but not pointer dereferences (`^'))? It may take a series of tests to find out ...
When this is cleared, it'll be another question if we can and/or want to implement it in GPC ...
Frank
On 27 May 2004 at 1:26, Frank Heckenbach wrote:
[...]
Anyway, before deciding what to do, we'll have to know how other compilers behave exactly. Since BP has restrictions on result types, there aren't much cases that can occur (strings and pointers may be the only questionable ones).
I tested this program: type a = record i, j : integer end;
function b:string; begin b[1] := ' ' end;
function b1:string; begin result[1] := ' ' end;
function bb(i, j: integer) : a; begin bb.i := i; bb.j := j end;
function b3(i, j: integer) : a; begin result.i := i; result.j := j end; begin Writeln ('OK'); end.
This is the result of my tests: 1. Virtual Pascal compiles it. 2. FreePascal compiles it. 3. Delphi compiles it. 4. TMT Pascal accepts functions b, b1, and b3, but rejects bb with this error: " bb.i := i; ? Error: TEST.PAS (line 18, col 3): expression must be a RECORD or OBJECT"
5. We already know GPC's and BP's behaviour.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof. Abimbola A. Olowofoyeku wrote:
On 26 May 2004 at 1:17, Waldek Hebisch wrote:
I noticed that the following FPC code (claimed to be BP compatible) is not accepted by GPC:
function b:string; begin b[1] := ' ' end;
BP accepts this, and so does Delphi. I agree that GPC should too.
GPC accepts this: function b:string; begin result[1] := ' ' end;
Similarely FPC accepts:
type a = record i, j : integer end; function b(i, j: integer) : a; begin b.i := i; b.j := j end;
BP doesn't accept this. If gives this error: "Error 34: Invalid function result type."
However, Delphi accepts it. GPC doesn't. But GPC accepts this: function b(i, j: integer) : a; begin result.i := i; result.j := j end;
So, GPC is nearly there already.
The tricky point is to decide if we access result variable or if we have recursive call. Note that with `--ignore-function-results'
f;
is accepted by GPC and means recursive call. As Frank noted
f^ := x;
according to ISO means recursive call.
Later you wrote (about Frank's example):
BP prints "3 2" FreePascal prints "3 2" Virtual Pascal prints "3 2 " Delphi prints "1 3" TMT Pascal prints "1 3" GPC prints "1 3"
The score is 3/3. I'd rather go with Delphi than with BP. Borland probably saw the light somewhere along the line ...
Pascal P4 prints "3 2". I am not sure if it is a feature or a bug: the standard comitee may have changed the language. On the other hand this example looks like a trap for implementers. Scott, care to say what IP Pascal is doing with that example ?
I would say that what BP does is consistent. Looking at Frank example, my first reactin was "Of course, standard says it is recursive call". But actually, saying that function identifier in left hand side of assignment means result variable makes some sense -- it is strange to treat records fields and subscripting differently then pointer dereference. Well, if we have parentheses, then it is recursive call. Also in
f[f[i]] := f[f[i]];
we must have 3 recursive calls and only leftmost `f' can be result variable.
Delphi behaviour is actually quite nasty to implement: at the moment we see assignment GPC already built function call and we need to check if left hand side contains call to our function at proper position and replace that call by reference to result variable. BP behaviour is quite easy to implement in recursive descent parser, but in GPC probably would require similar effort as Delphi way (since we can not use lookahead to decide which action is apropriate, and we can not exclude recursive call due to `--ignore-function-results').
Waldek Hebisch wrote:
I noticed that the following FPC code (claimed to be BP compatible) is not accepted by GPC:
function b:string; begin b[1] := ' ' end;
Similarely FPC accepts:
type a = record i, j : integer end; function b(i, j: integer) : a; begin b.i := i; b.j := j end;
I do not know if we want to implement that feature, but (assuming it is really accepted by BP) we should list it as known incompatiblity.
BP really accepts the first case (not the second one because it doesn't allow record result types, but if it did, it presumably might accept the second case too). Ouch!
It seems like BP does context-dependent parsing, treating the function-identifier differently in "lvalues" and "rvalues". The problem (besides being a rather strange thing in itself) it that it seems to be done wrongly. The `^' suffix operator (pointer dereference) can make an lvalue from an rvalue.
In particular, AFAICS in the following program, the `f' in `f^ := 3' must be a recursive call (yielding b), so b^ must be set to 3, and the program must say `1 3'.
BP, however, seems to think `f' is an lvalue before it sees the `^', so it sets the current function-result (which is a), dereferenced, to 3, and says `3 2'.
So, in contrast to the examples above, this is not an extension (i.e., some behaviour for a case otherwise invalid), but at least another incompatibility (if not to say, a violation of Pascal semantics) for a correct Pascal program, so I'm not sure if the whole thing is a bug or just a buggy feature.
program Foo (Output);
type PInteger = ^Integer;
var Called: Boolean; a, b, c: PInteger;
function f: PInteger; begin if Called then f := b else begin Called := True; f := a; f^ := 3 end end;
begin Called := False; New (a); a^ := 1; New (b); b^ := 2; c := f; WriteLn (a^, ' ', b^) end.
Frank
Frank Heckenbach wrote:
... snip ...
It seems like BP does context-dependent parsing, treating the function-identifier differently in "lvalues" and "rvalues". The
As has every Pascal compiler known to me since J&W. This is part of the original language specification and of ISO7185, while use of 'result' is not.
CBFalconer wrote:
Frank Heckenbach wrote:
... snip ...
It seems like BP does context-dependent parsing, treating the function-identifier differently in "lvalues" and "rvalues". The
As has every Pascal compiler known to me since J&W. This is part of the original language specification and of ISO7185,
ISO contains a special provision for using the function-identifier as the target of an assignment-statement, not in arbitrary "lvalue" contexts.
As I said, AFAICS, the `f^' in my demo program must be a recursive call according to ISO, even though `f^' is an lvalue.
while use of 'result' is not.
I didn't talk about `Result' at all.
Frank
CBFalconer wrote:
Frank Heckenbach wrote:
... snip ...
It seems like BP does context-dependent parsing, treating the function-identifier differently in "lvalues" and "rvalues". The
As has every Pascal compiler known to me since J&W. This is part of the original language specification and of ISO7185, while use of 'result' is not.
The var on the left side of an assignment is context dependent. What else ?
Wirth described the var exception to strict syntax (and not sematic) based processing and noted that it was unavoidable, but seemed pround that he had got the number of such dependencies down to 1.
Context dependencies, as I am sure you gentleman know, are rampant in other langauges, notably C.
On 26 May 2004 at 12:36, Frank Heckenbach wrote:
[...]
In particular, AFAICS in the following program, the `f' in `f^ := 3' must be a recursive call (yielding b), so b^ must be set to 3, and the program must say `1 3'.
BP, however, seems to think `f' is an lvalue before it sees the `^', so it sets the current function-result (which is a), dereferenced, to 3, and says `3 2'.
So, in contrast to the examples above, this is not an extension (i.e., some behaviour for a case otherwise invalid), but at least another incompatibility (if not to say, a violation of Pascal semantics) for a correct Pascal program, so I'm not sure if the whole thing is a bug or just a buggy feature.
program Foo (Output);
type PInteger = ^Integer;
[...]
BP prints "3 2" FreePascal prints "3 2" Virtual Pascal prints "3 2 " Delphi prints "1 3" TMT Pascal prints "1 3" GPC prints "1 3"
The score is 3/3. I'd rather go with Delphi than with BP. Borland probably saw the light somewhere along the line ...
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/