GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature. (If it made it possible to nest a compile-time-unknown number of `for' loops, I could see some point, but of course, it doesn't.)
So, would anybody mind dropping this misfeature, and requiring an identifier in for-loop counters?
The same (and probably a lot of other weird stuff) can be achieved with "extended" `absolute' variables, such as:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer; {$local W-} c: Integer absolute a[i]; {$endlocal}
begin i := 1; for c := 1 to 10 do begin WriteLn (i, ' ', c); if a[i] = 5 then i := 2 end end.
We support `absolute' for BP compatibility, but IMHO then we should restrict it to what BP requires, i.e. really absolute addresses, or the address of entire variables or parameters.
I suppose (hope) few users actually knew about the extended (mis)features GPC allowed, so I hope we can drop them. (If not, we probably should change semantics to evaluate the address once, and not on each usage, as is done now, so if you rely on this behaviour, you might have to change your code anyway -- if nothing else helps, you can always achieve the same effect with type-casting of pointers.) BP compatible code will not be affected.
Any objections?
Frank
On 29 Jun 2005 at 8:19, Frank Heckenbach wrote:
GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature.
Neither do I.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
"Prof A Olowofoyeku (The African Chief)" wrote:
On 29 Jun 2005 at 8:19, Frank Heckenbach wrote:
GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature.
Neither do I.
Nor I. I vaguely recall that it is forbidden in at least ISO 7185, but cannot quote chapter and verse. This is a milestone, where BP is more standards adherent :=)
I would not mind dropping the feature. The ISO Standard, IIRC, does not allow it.
It may seem to be a useful feature at first sight (in particular using a field in a record as control variable, where there is less harm), but it does not save much and, as the example shows, encourages obscurity. Even if the identity of the control variable is determined only once (just like the upper bound), it is still a bigger burden to understand such a construction.
On the other hand, even with simple control variables (that are not changed inside the for-loop), you can write obscure code:
readln ( i ) ; for i := i + 1 to sqr ( i ) do write ( i )
Exercise: Determine the output for various input values of i by reasoning (rather than trying).
Tom -- On Wed, Jun 29, 2005 at 08:19:06AM +0200, Frank Heckenbach wrote:
GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature. (If it made it possible to nest a compile-time-unknown number of `for' loops, I could see some point, but of course, it doesn't.)
So, would anybody mind dropping this misfeature, and requiring an identifier in for-loop counters?
Frank Heckenbach wrote:
So, would anybody mind dropping this misfeature, and requiring an identifier in for-loop counters?
Do agree that it is not needed.
The same (and probably a lot of other weird stuff) can be achieved We support `absolute' for BP compatibility, but IMHO then we should restrict it to what BP requires, i.e. really absolute addresses, or the address of entire variables or parameters.
I am not enthousiastic about this one because GPC
- is very restrictive in what typecasts are allowed - typecastst with $R+ cause range-check errors.
Regards,
Adriaan van Os
Adriaan van Os wrote:
The same (and probably a lot of other weird stuff) can be achieved We support `absolute' for BP compatibility, but IMHO then we should restrict it to what BP requires, i.e. really absolute addresses, or the address of entire variables or parameters.
I am not enthousiastic about this one because GPC
- is very restrictive in what typecasts are allowed
Via pointers you can cast basically everything, i.e. `PNewType (@OldVar)^'. (Sure, you must be able to take the address, i.e. lvalues, and you may get warnings about alignment, and on strict alignment machines it may actually crash, but all of this is also true for absolute variables. In fact, internally absolute variables do just cast pointers.)
- typecastst with $R+ cause range-check errors.
Which kinds of typecasts? Can you give an example?
Frank
At 13:54 +0200 29/6/05, Frank Heckenbach wrote:
Adriaan van Os wrote:
The same (and probably a lot of other weird stuff) can be achieved We support `absolute' for BP compatibility, but IMHO then we should restrict it to what BP requires, i.e. really absolute addresses, or the address of entire variables or parameters.
I am not enthousiastic about this one because GPC
- is very restrictive in what typecasts are allowed
I agree entirely with the for loop case. I would hope that the absolute case is not removed though. For example, I use this quite cleanly in my program:
function SFTPProducer( parameter: UnivPtr ): OSStatus; var transfer: TransferDataPtr absolute parameter; taskinfo: TaskInformationPtr = @transfer^.producer; extra: SFTPExtraStoragePtr absolute taskinfo^.extra_storage;
I have many similar producer and consumer threads. The threads must take a defined parameter (and GPC will not allow me to cast the procedure to a compatible one taking a different pointer). The thread data has pointers for storage, and the absolute method allows specifying a specific type for each different thread.
Yes, I agree that it could all be done with multiple variables, casting and assignments, but that clutters the code, adds warnings which have to be disabled, and adds real code that may or may not be optimized away later.
Via pointers you can cast basically everything, i.e. `PNewType (@OldVar)^'. (Sure, you must be able to take the address, i.e. lvalues, and you may get warnings about alignment, and on strict alignment machines it may actually crash, but all of this is also true for absolute variables. In fact, internally absolute variables do just cast pointers.)
You cannot case function pointers to/from pointers, so that would not work for at least that case. You cannot even cast function pointers between reasonably compatible cases (like parameters with differing pointer types).
- typecastst with $R+ cause range-check errors.
Which kinds of typecasts? Can you give an example?
It is traditional to use a UserData field of UInt32 or SInt32 or Pointer to store arbitrary user data in various interfaces on the Mac. Casting between them can generate range check errors. So for example, a library that uses SInt32 as the UserData field, where you wish to have the UserData store an arbitrary UInt32 can cause a range check error when you pass it as SInt32(mydata).
Traditional use of casting between SInt32 and UInt32 on the Mac is a binary four byte cast.
The problem of course is that as a developer you might never catch this range check until after you deploy the application (disabling range checking when deploying the application is a possibility but might lead to security issues such as buffer overflows).
Anyway, summary:
for loops as only local variables - I fully support this change.
removing absolute - I would not make this change. I can live with it if you do, but it is a useful feature which can be used reasonably cleanly. If you support univ instead, or function casting between reasonably compatible functions, or function casting to/from pointers, then all of those would provide alternate solutions. I would really love to see univ implemented for pointer parameters, I even started doing it myself, but got a bit stuck when I hit pascal_type_variant...
Casting range checks - it is not what I expect, I expect cast to be a strict change of type with no interpretation on the contents, but I can understand and accept the reasoning for it (for example EnumeratedType(myinteger) is obviously bogus if myinteger is not within range).
Enjoy, Peter.
Hi,
In my opinion, using such a (mis)feature in a useful program is as silly as the result it gives. And if this kind of schema is required (?), what about using a 'while' or 'repeat' loop instead? Then you can modify the loop index inside of the loop body the right way, safely and - most of all - with PREDICTABLE results.
I think dropping this feature would be an enhancement.
My 2 cents
Pascal Viandier
pascal@accovia.com
-----Message d'origine----- De : gpc-owner@gnu.de [mailto:gpc-owner@gnu.de] De la part de Frank Heckenbach Envoyé : June 29, 2005 02:19 À : gpc@gnu.de Objet : Dropping some misfeatures in for-loops and`absolute' variables
GPC accepts the following program, but produces quite silly results:
<snip>
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature. (If it made it possible to nest a compile-time-unknown number of `for' loops, I could see some point, but of course, it doesn't.)
So, would anybody mind dropping this misfeature, and requiring an identifier in for-loop counters?
<snip>
I suppose (hope) few users actually knew about the extended (mis)features GPC allowed, so I hope we can drop them. (If not, we probably should change semantics to evaluate the address once, and not on each usage, as is done now, so if you rely on this behaviour, you might have to change your code anyway -- if nothing else helps, you can always achieve the same effect with type-casting of pointers.) BP compatible code will not be affected.
Any objections?
Frank
Frank Heckenbach a écrit:
GPC accepts the following program, but produces quite silly results: Any objections?
Certainly not. This "feature" goes contrary to all the reasons I program in pascal.
Maurice
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Jun 29, 2005, at 2:19 AM, Frank Heckenbach wrote:
GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature. (If it made it possible to nest a compile-time-unknown number of `for' loops, I could see some point, but of course, it doesn't.)
Actually, I think it does (untested, though):
CONST max_depth = 100;
FUNCTION Multi_For(depth, limit : INTEGER) : LONGINT; VAR i : INTEGER; a : ARRAY[1..max_depth] OF INTEGER; v : LONGINT;
BEGIN { setup } i := 1; v := 0;
{ the loops } FOR a[i] := 1 TO limit DO BEGIN IF (i < depth) THEN BEGIN INC(i); a[i] := 1 END ELSE BEGIN { actual loop stuff } v := v + a[i];
{ handle reduction in depth at end of loop } IF (a[i] = limit) AND (i > 1) THEN DEC(i) END END;
Multi_For := v END;
- ----------------------------------------------------------- Frank D. Engel, Jr. fde101@fjrhome.net
$ ln -s /usr/share/kjvbible /usr/manual $ true | cat /usr/manual | grep "John 3:16" John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. $
___________________________________________________________ $0 Web Hosting with up to 200MB web space, 1000 MB Transfer 10 Personalized POP and Web E-mail Accounts, and much more. Signup at www.doteasy.com
One can handle nested for loops with REPEAT and WHILE loops, without going into FOR loop contortions:
From a Delphi program I wrote long ago. By using dynamic arrays, you can get around a fixed dimension.
unit ForLoopUnit;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation {$R *.DFM}
const Dim = 3;
type TIndex = array[1..Dim] of Integer;
var F: TextFile; Index, LowerBound, UpperBound: TIndex;
procedure Initialize;
var K: Integer;
begin for K := 1 to Dim do begin LowerBound[K] := 0; UpperBound[K] := 5; //Random(6) + 1; end; end; // Initialize
procedure P(const Index: TIndex); // for testing
var K: Integer; S: string;
begin S := 'Index = ['; for K := 1 to Dim - 1 do S := S + IntToStr(Index[K]) + ', '; S := S + IntToStr(Index[Dim]) + ']'; Writeln(F, S); end; // P
procedure MultiForLoop;
var K: Integer;
begin Index := LowerBound; K := Dim; repeat P(Index); while (K >= 1) and (Index[K] = UpperBound[K]) do Dec(K); if K = 0 then Break; // repeat loop // K >= 1, Index[K] < UpperBound[K], // and Index[J] < UpperBound[J] for all J > K Inc(Index[K]); Inc(K); while K <= Dim do begin Index[K] := LowerBound[K]; Inc(K) end; until False; end;
initialization AssignFile(F, 'For.Pas'); Rewrite(F); Initialize; MultiForLoop; CloseFile(F); end.
Harley Flanders
====================================
Frank D. Engel, Jr. wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Jun 29, 2005, at 2:19 AM, Frank Heckenbach wrote:
GPC accepts the following program, but produces quite silly results:
program Foo;
var a: array [1 .. 2] of Integer value (0, 0); i: Integer;
begin i := 1; for a[i] := 1 to 10 do begin WriteLn (i, ' ', a[i]); if a[i] = 5 then i := 2 end end.
The problem is that it evaluates the index i each time, not once before the loop. It would be possible to fix it, but do we really want that? Neither BP nor CP/EP allow it, they allow only identifiers in for-loops.
Waldek and I see no need for such a feature. (If it made it possible to nest a compile-time-unknown number of `for' loops, I could see some point, but of course, it doesn't.)
Actually, I think it does (untested, though):
CONST max_depth = 100;
FUNCTION Multi_For(depth, limit : INTEGER) : LONGINT; VAR i : INTEGER; a : ARRAY[1..max_depth] OF INTEGER; v : LONGINT;
BEGIN { setup } i := 1; v := 0;
{ the loops } FOR a[i] := 1 TO limit DO BEGIN IF (i < depth) THEN BEGIN INC(i); a[i] := 1 END ELSE BEGIN { actual loop stuff } v := v + a[i]; { handle reduction in depth at end of loop } IF (a[i] = limit) AND (i > 1) THEN DEC(i) END END; Multi_For := v
END;
Frank D. Engel, Jr. fde101@fjrhome.net
$ ln -s /usr/share/kjvbible /usr/manual $ true | cat /usr/manual | grep "John 3:16" John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. $ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (Darwin)
iD8DBQFCwrkC7aqtWrR9cZoRAmuyAJ0ZJsfJkKGZfHdWr2+9Z1wySk+eCACcCpIJ TWcqtXyw2D5jpyYhkNe36tg= =Gc9l -----END PGP SIGNATURE-----
$0 Web Hosting with up to 200MB web space, 1000 MB Transfer 10 Personalized POP and Web E-mail Accounts, and much more. Signup at www.doteasy.com
Prof. Harley Flanders wrote:
One can handle nested for loops with REPEAT and WHILE loops, without going into FOR loop contortions: [...]
Indeed, and that's what should be done (or using recursion, as one prefers).
I suppose (really hope! :-) that Frank D. Engel's example was meant as a proof of concept only, and not to be seriously used. (I think it would currently work with GPC, but relies heavily on undocumented implementation specifics.)
Frank
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Jul 2, 2005, at 9:06 AM, Frank Heckenbach wrote:
I suppose (really hope! :-) that Frank D. Engel's example was meant as a proof of concept only, and not to be seriously used. (I think
Obviously.
- ----------------------------------------------------------- Frank D. Engel, Jr. fde101@fjrhome.net
$ ln -s /usr/share/kjvbible /usr/manual $ true | cat /usr/manual | grep "John 3:16" John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. $
___________________________________________________________ $0 Web Hosting with up to 200MB web space, 1000 MB Transfer 10 Personalized POP and Web E-mail Accounts, and much more. Signup at www.doteasy.com
This GPC forum is NOT the place for religious messages.
HF
Frank D. Engel, Jr. wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Jul 2, 2005, at 9:06 AM, Frank Heckenbach wrote:
I suppose (really hope! :-) that Frank D. Engel's example was meant as a proof of concept only, and not to be seriously used. (I think
Obviously.
Frank D. Engel, Jr. fde101@fjrhome.net
$ ln -s /usr/share/kjvbible /usr/manual $ true | cat /usr/manual | grep "John 3:16" John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. $ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (Darwin)
iD8DBQFCxpqz7aqtWrR9cZoRAlFnAJ9DhbJ4AqcCrPP1OhNP155Mm0YFBwCgij3M j81TcFGpO7lXlWVVhbKO2YM= =TqLB -----END PGP SIGNATURE-----
$0 Web Hosting with up to 200MB web space, 1000 MB Transfer 10 Personalized POP and Web E-mail Accounts, and much more. Signup at www.doteasy.com