Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2009-11

Testing for..in feature

46 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Alexander Klenin
I have started testing the new for..in code.
The very first test I tried found a bug ;-)
---
const S = 'abc';
var ch: Char;
begin
  for ch in S do Writeln(ch);
end.
---
Alexander S. Klenin

Reply by email

Alexander Klenin
to Alexander Klenin

Another minor problem:

begin for ch in S do Writeln(ch); end. -- Results in: t.pp(2,10) Error: Identifier not found "ch" t.pp(2,15) Error: Identifier not found "S" t.pp(2,28) Error: Identifier not found "ch" t.pp(2,29) Error: Can not find an enumerator for the type "<erroneous type>" IMHO the last two errors are not needed. -- Alexander S. Klenin

Reply by email

Thaddy
to Alexander Klenin: I have started testing the new for..in code. The very first test I tried found a bug ;-)…
Alexander Klenin wrote 10 lines
I have started testing the new for..in code. The very first test I tried found a bug ;-) --- const S = 'abc';//<----??? var ch: Char; begin for ch in S do Writeln(ch); end. ---

I suppose you refer to the fact that the compiler should never allow this ;) Or do you want this to actually work?? An untyped const is fine with me and I use it for years, but should it be allowed for for..in?

Reply by email

Alexander Klenin
to Thaddy
Thaddy wrote 14 lines
Alexander Klenin wrote: > > I have started testing the new for..in code. > The very first test I tried found a bug ;-) > --- > const S = 'abc';//<----??? > var ch: Char; > begin >  for ch in S do Writeln(ch); > end. > --- > I suppose you refer to the fact that the compiler should never allow this ;)

I refer to the fact that iteration starts from position 0 instead of 1. I think this is just a minor glitch in ShortString vs AnsiString detection.

Or do you want this to actually work?? An untyped const is fine with me and I use it for years, but should it be allowed for for..in?

Do not see a reason why not.

Alexander S. Klenin

Reply by email

Paul Ishenin
to Alexander Klenin: Yet another bug: --- type T = (a1, b1=5); var ch: T; begin for ch in T do Writeln(ch);…
Alexander Klenin wrote 10 lines
Yet another bug: --- type T = (a1, b1=5); var ch: T; begin for ch in T do Writeln(ch); end.

This is caused by the problem in the for-to loop:

for ch := Low(T) to High(T) do
   WriteLn(ch)

How should I solve the problem in the for-in loop?

I tried the next way:
  ch := Low(T);
  while ch <= High(T) do
  begin
    WriteLn(ch);
    inc(ch);

But it fails the same way.

Best regards,
Paul Ishenin.

Reply by email

Florian Klaempfl
to Paul Ishenin
Show quoted text 26 lines
Alexander Klenin wrote: > Yet another bug: > > --- > type T = (a1, b1=5); > var > ch: T; > begin > for ch in T do Writeln(ch); > end. > This is caused by the problem in the for-to loop: for ch := Low(T) to High(T) do WriteLn(ch) How should I solve the problem in the for-in loop? I tried the next way: ch := Low(T); while ch <= High(T) do begin WriteLn(ch); inc(ch); But it fails the same way.

You can use the rtti generated for those enums.

Reply by email

Alexander Klenin
to Paul Ishenin: This is caused by the problem in the for-to loop: for ch := Low(T) to High(T) do…
Paul Ishenin wrote 28 lines
Alexander Klenin wrote: > > Yet another bug: > > --- > type T = (a1, b1=5); > var >  ch: T; > begin >  for ch in T do Writeln(ch); > end. > This is caused by the problem in the for-to loop: for ch := Low(T) to High(T) do  WriteLn(ch) How should I solve the problem in the for-in loop? I tried the next way:  ch := Low(T);  while ch <= High(T) do  begin   WriteLn(ch);   inc(ch); But it fails the same way.
ch := succ(ch);

OTOH, I am not sure -- obviously either Succ or Inc is buggy, but which one? Maybe runtime instead of compile-time error is actually correct?

Alexander S. Klenin

Reply by email

Marco van de Voort
to Paul Ishenin: This is caused by the problem in the for-to loop: for ch := Low(T) to High(T) do…

In our previous episode, Paul Ishenin said:

> Yet another bug: > > ---
{$apptype console}
Show quoted text 6 lines
> type T = (a1, b1=5); > var > ch: T; > begin > for ch in T do Writeln(ch); > end.

CodeGear Delphi for Win32 compiler version 20.0
Copyright (c) 1983,2008 CodeGear
testx.dpr(6) Error: E2029 '(' expected but 'DO' found testx.dpr(7) Error: E2430 for-in statement cannot operate on collection type 'T'

Since I suspected that D2009 doesn't work on sparse enums, I tried, and the above is the result.

Reply by email

Vincent Snijders
to Marco van de Voort
Marco van de Voort wrote 20 lines
In our previous episode, Paul Ishenin said: >> Yet another bug: >> >> --- {$apptype console} >> type T = (a1, b1=5); >> var >> ch: T; >> begin >> for ch in T do Writeln(ch); >> end. CodeGear Delphi for Win32 compiler version 20.0 Copyright (c) 1983,2008 CodeGear testx.dpr(6) Error: E2029 '(' expected but 'DO' found testx.dpr(7) Error: E2430 for-in statement cannot operate on collection type 'T' Since I suspected that D2009 doesn't work on sparse enums, I tried, and the above is the result.

Does it work on not sparse enums?

Vincent

Reply by email

Marco van de Voort
to Vincent Snijders: Does it work on not sparse enums? Vincent

In our previous episode, Vincent Snijders said:
yy> >>> end.

Show quoted text 11 lines
> > > CodeGear Delphi for Win32 compiler version 20.0 > Copyright (c) 1983,2008 CodeGear > testx.dpr(6) Error: E2029 '(' expected but 'DO' found > testx.dpr(7) Error: E2430 for-in statement cannot operate on collection type 'T' > > Since I suspected that D2009 doesn't work on sparse enums, I tried, and the > above is the result. Does it work on not sparse enums?

Good point. Same error.

In the help only strings,arrays, sets and collections (and in D2009 a records are explicely named) are described, not enums.

Reply by email

Marco van de Voort
to Paul Ishenin: Delphi compiler does not support for-in loop for types (enums, integer, ...). This is fpc…

In our previous episode, Paul Ishenin said:

Show quoted text 7 lines
>> Since I suspected that D2009 doesn't work on sparse enums, I tried, >> and the >> above is the result. > > Does it work on not sparse enums? Delphi compiler does not support for-in loop for types (enums, integer, ...). This is fpc extension :)

Do you have unit tests for multidimensional arrays. I saw quite funky examples (involving dummy variables) in the D2009 help for that.

Reply by email

Paul Ishenin
to Marco van de Voort
Marco van de Voort wrote
Do you have unit tests for multidimensional arrays. I saw quite funky examples (involving dummy variables) in the D2009 help for that.

No. I know delphi allows to enumerate multidimensional arrays but fpc traverses only the first dimension.

Best regards,
Paul Ishenin.

Reply by email

Marco van de Voort
to Alexander Klenin: ch := succ(ch); OTOH, I am not sure -- obviously either Succ or Inc is buggy, but which…

In our previous episode, Alexander Klenin said:

Show quoted text 9 lines
> ? WriteLn(ch); > ? inc(ch); > > But it fails the same way. ch := succ(ch); OTOH, I am not sure -- obviously either Succ or Inc is buggy, but which one? Maybe runtime instead of compile-time error is actually correct?

Sparse enums are simply a kludge. They were needed because they exist in the Windows API, and afaik for that only. IOW for easy translation of Windows types.

I wouldn't assume that all rules for enums apply to sparse ones too.

Reply by email

Matt Emson
to Marco van de Voort
Marco van de Voort wrote
Sparse enums are simply a kludge. They were needed because they exist in the Windows API, and afaik for that only. IOW for easy translation of Windows types.

They were added to Delphi in version 6. I though they added them to support Qt and the CLX, which relied on Qt as its underlying base toolkit. They were common in C/C++ before that though.

The problem I always had with Pascal supporting them was that a Pascal enum was designed to represents the position in a sequence and not necessarily an underlying integral value - where as a sparse enum is simply a grouping for a bunch of numerical values at the whim of the developer.

Reply by email

Marco van de Voort
to Matt Emson

In our previous episode, Matt Emson said:

Show quoted text 5 lines
> Sparse enums are simply a kludge. They were needed because they exist in the Windows API, and afaik for that only. IOW for easy translation of Windows types. They were added to Delphi in version 6. I though they added them to support Qt and the CLX, which relied on Qt as its underlying base toolkit. They were common in C/C++ before that though.

Well, anyway, foreign interfacing related, not core language feature.

Show quoted text 5 lines
The problem I always had with Pascal supporting them was that a Pascal enum was designed to represents the position in a sequence and not necessarily an underlying integral value - where as a sparse enum is simply a grouping for a bunch of numerical values at the whim of the developer.

I never had a problem with that. I use them in headers, and not otherwise, so I never have a problem :-)

Reply by email

Paul Ishenin
to Paul Ishenin: No. I know delphi allows to enumerate multidimensional arrays but fpc traverses only the…
Paul Ishenin wrote 6 lines
Marco van de Voort wrote: > Do you have unit tests for multidimensional arrays. I saw quite funky > examples (involving dummy variables) in the D2009 help for that. > No. I know delphi allows to enumerate multidimensional arrays but fpc traverses only the first dimension.

To be more precise:

{$apptype console}
type
  TSingleDimArray = array[0..1] of integer;
  TMultyDimArray = array[0..1] of TSingleDimArray;
var
  MultyDimArray: TMultyDimArray;
  a: TSingleDimArray;
  i: integer;
begin
  MultyDimArray[0,0]:=1;
  MultyDimArray[0,1]:=2;
  MultyDimArray[1,0]:=3;
  MultyDimArray[1,1]:=4;
  for a in MultyDimArray do
    for i in a do
      WriteLn(i);
  for i in MultyDimArray do
    Writeln(i);
end.

The example compiles and works fine in Delphi. In fpc the second for-in loop gives an error. I will try to solve this later.

Best regards,
Paul Ishenin.

Reply by email

Vinzent Höfler
to Matt Emson: They were added to Delphi in version 6. I though they added them to support Qt and the…

Matt Emson :

Show quoted text 5 lines
The problem I always had with Pascal supporting them was that a Pascal enum was designed to represents the position in a sequence and not necessarily an underlying integral value - where as a sparse enum is simply a grouping for a bunch of numerical values at the whim of the developer.

Or to map logical values to physical ones (on some hardware).

Loops and arrays would be a plus, but I'd consider a compile-time error sufficient here. ;) I'd still expect "Succ" and "Pred" to work properly on those types.

Vinzent.

DSL-Preisknaller: DSL Komplettpakete von GMX schon für 16,99 Euro mtl.!* Hier klicken: http://portal.gmx.net/de/go/dsl02

Reply by email

Paul Ishenin
to Florian Klaempfl: You can use the rtti generated for those enums.
Florian Klaempfl wrote
You can use the rtti generated for those enums.

Actually I can't :)

uses
   typinfo;
type T = (a1, b1=5);
var
   ch: T;
   Info: PTypeInfo;
begin
   Info := TypeInfo(T);
compiler: project1.lpr(10,11) Error: No type info available for this type

So what is the best solution for now:

1) check if enum has jumps and give an error
2) skip any compiler code modifications since the next code still works and outputs 5 numbers:
type T = (a1, b1=5);
var

   ch: T;

begin

   for ch in T do
     WriteLn(Ord(ch)); // <- note Ord() here

end
3) fix write/writeln to write something for the non-existent enum members (in the example they are 2, 3, 4) instead of giving runtime error
4) write 2 magic functions: one to get the next enum value, one to get the previos enum value and implement a special handling in the for-in loop for such arrays

Best regards,
Paul Ishenin.

Reply by email

Alexander Klenin
to Paul Ishenin
Paul Ishenin wrote
So what is the best solution for now: 1) check if enum has jumps and give an error

This is what Succ/Pred do currently. I think that if we decide _not_ to choose option (1), current Succ/Prev behaviour should be considered an error.

Show quoted text 9 lines
2) skip any compiler code modifications since the next code still works and outputs 5 numbers: type T = (a1, b1=5); var  ch: T; begin  for ch in T do    WriteLn(Ord(ch)); // <- note Ord() here end

What are these numbers? (Sorry, I am at work, can not test from here). I would be surprised if they are "0 5".

3) fix write/writeln to write something for the non-existent enum members (in the example they are 2, 3, 4) instead of giving runtime error

No, I think runtime error is correct here.

4) write 2 magic functions: one to get the next enum value, one to get the previos enum value and implement a special handling in the for-in loop for such arrays

I always thought Succ/Pred are exactly such magic functions ;-)

Alexander S. Klenin

Reply by email

Paul Ishenin
to Alexander Klenin
Alexander Klenin wrote 12 lines
> 2) skip any compiler code modifications since the next code still works and > outputs 5 numbers: > type T = (a1, b1=5); > var > ch: T; > begin > for ch in T do > WriteLn(Ord(ch)); // <- note Ord() here > end What are these numbers? (Sorry, I am at work, can not test from here). I would be surprised if they are "0 5".

0, 1, 2, 3, 4, 5

Show quoted text 5 lines
> 4) write 2 magic functions: one to get the next enum value, one to get the > previos enum value and implement a special handling in the for-in loop for > such arrays I always thought Succ/Pred are exactly such magic functions ;-)

yes, forgot about them.

Best regards,
Paul Ishenin.

Reply by email

Alexander Klenin
to Paul Ishenin
Paul Ishenin wrote 17 lines
Alexander Klenin wrote: >> 2) skip any compiler code modifications since the next code still works >> and >> outputs 5 numbers: >> type T = (a1, b1=5); >> var >>  ch: T; >> begin >>  for ch in T do >>   WriteLn(Ord(ch)); // <- note Ord() here >> end > > What are these numbers? (Sorry, I am at work, can not test from here). > I would be surprised if they are "0 5". 0, 1, 2, 3, 4, 5

Oh. I think it is better to generate error than to output such nonsense.

Show quoted text 9 lines
>> 4) write 2 magic functions: one to get the next enum value, one to get >> the >> previos enum value and implement a special handling in the for-in loop >> for >> such arrays > > I always thought Succ/Pred are exactly such magic functions ;-) yes, forgot about them.

So, I vote for converting "for i in Enum do" into

while ... do
  ...
  i := Succ(i);
end;

This will automatically fail for non-consecutive enums, which is fine for now. If later it will be decided to extend Succ/Pred functions to handle non-consecutive enums,
for..in loops will also start working for them.

Alexander S. Klenin

Reply by email

Paul Ishenin
to Alexander Klenin
Alexander Klenin wrote 6 lines
So, I vote for converting "for i in Enum do" into while ... do ... i := Succ(i); end;

No need to complicate the code generation for all enums. This can be done only for the enums with jumps.

Best regards,
Paul Ishenin.

Reply by email

Paul Ishenin
to Alexander Klenin: This is what Succ/Pred do currently. I think that if we decide _not_ to choose option…
Alexander Klenin wrote 5 lines
> 4) write 2 magic functions: one to get the next enum value, one to get the > previos enum value and implement a special handling in the for-in loop for > such arrays I always thought Succ/Pred are exactly such magic functions ;-)

Btw, I tested succ, pred with delphi and with fpc in mode delphi.

type
   T = (a1, b1 = 5);
var
   ch: T;
begin
   ch := a1;
   WriteLn(Ord(Succ(ch)));
end.

How do you think what is the output :) Answer: '1'

So succ/pred works another way we need.

Best regards,
Paul Ishenin.

Reply by email

Florian Klaempfl
to Paul Ishenin: Actually I can't :) uses typinfo; type T = (a1, b1=5); var ch: T; Info: PTypeInfo; begin…
Show quoted text 16 lines
Florian Klaempfl wrote: > You can use the rtti generated for those enums. Actually I can't :) uses typinfo; type T = (a1, b1=5); var ch: T; Info: PTypeInfo; begin Info := TypeInfo(T); compiler: project1.lpr(10,11) Error: No type info available for this type

This rtti isn't published for program use but e.g. writeln(<enum>) uses it.

Reply by email

Michael Van Canneyt
to Paul Ishenin: Actually I can't :) uses typinfo; type T = (a1, b1=5); var ch: T; Info: PTypeInfo; begin…
Paul Ishenin wrote 19 lines
Florian Klaempfl wrote: > You can use the rtti generated for those enums. Actually I can't :) uses typinfo; type T = (a1, b1=5); var ch: T; Info: PTypeInfo; begin Info := TypeInfo(T); compiler: project1.lpr(10,11) Error: No type info available for this type So what is the best solution for now: 1) check if enum has jumps and give an error

This is the best solution. There are many other things that don't work with enums that have jumps; This is just an additional one.

Enums with jumps are just a kludge to mimic C enums, which are in reality just a bunch of constants .

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote 5 lines
> 1) check if enum has jumps and give an error This is the best solution. There are many other things that don't work with enums that have jumps; This is just an additional one.

This is the easiest solution.

Enums with jumps are just a kludge to mimic C enums, which are in reality just a bunch of constants .

Maybe we can improve that enums a bit? I see that compiler gives no way to traverse such enums. If you have no info about such type you can't work with it properly: succ, pred, inc, dec don't work as expected, typeinfo is not present. I think that maybe at least for-in loop can work for them :)

You and Florian as well as my left and right cerebral hemispheres give me completely different directions. Therefore I stay with the same question. I will wait for more opinions.

Best regards,
Paul Ishenin.

Reply by email

Paul Ishenin
to Florian Klaempfl: This rtti isn't published for program use but e.g. writeln(<enum>) uses it.
Florian Klaempfl wrote
This rtti isn't published for program use but e.g. writeln(<enum>) uses it.

Yes, I was surprised when I tried to look why writeln gives a runtime error for unexistent element of enum.

Also I looked at compile - it just checks if enum has jumps and refuses typeinfo() call for it. Why does compiler hides this info?

Best regards,
Paul Ishenin.

Reply by email

Florian Klaempfl
to Paul Ishenin
Show quoted text 10 lines
Florian Klaempfl wrote: > This rtti isn't published for program use but e.g. writeln(<enum>) > uses it. Yes, I was surprised when I tried to look why writeln gives a runtime error for unexistent element of enum. Also I looked at compile - it just checks if enum has jumps and refuses typeinfo() call for it. Why does compiler hides this info?

Everything exposed must be maintained ;) I guess the reason is that it was an experimental implementation first and it was not enabled, later, nobody documented it and enabled it.

Reply by email

Michael Van Canneyt
to Paul Ishenin: Yes, I was surprised when I tried to look why writeln gives a runtime error for…
Paul Ishenin wrote 9 lines
Florian Klaempfl wrote: > This rtti isn't published for program use but e.g. writeln(<enum>) uses it. Yes, I was surprised when I tried to look why writeln gives a runtime error for unexistent element of enum. Also I looked at compile - it just checks if enum has jumps and refuses typeinfo() call for it. Why does compiler hides this info?

Because - for one thing - the RTTI functions of the typinfo unit will fail on it.

They expect 0 to be the first value, and count(elements)-1 to be the last, and everything else between should be valid values.

tmyenum = (a,b,c=-1,D);

does not cope with this. If you want to support succ(), pred() and whatnot, you'll have to rewrite a large part of the RTL and RTTI stuff, which I think is such a can of works and so risky, that it isn't worth the effort. You'll also have to write all possible values, and so on. A can of worms you don't want to open.

Such enums should be used only to import some braindead C headers. Like I said, it's just a set of constants, wrapped in a type.

Maybe we should not name them enumerated.

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote
Because - for one thing - the RTTI functions of the typinfo unit will fail on it.

This is unfair. Why compiler functions (like write) have advantage over user functions.

What if user needs this info very much? Maybe allow typeinfo for them and document it limitation is better? Or add another special function: TypeInfo(TypeIdentifier, IKnowAboutLimitations: Boolean = False) ?

Best regards,
Paul Ishenin.

Reply by email

Michael Van Canneyt
to Paul Ishenin
Paul Ishenin wrote 11 lines
Michael Van Canneyt wrote: > Because - for one thing - the RTTI functions of the typinfo unit will fail > on it. This is unfair. Why compiler functions (like write) have advantage over user functions. What if user needs this info very much? Maybe allow typeinfo for them and document it limitation is better? Or add another special function: TypeInfo(TypeIdentifier, IKnowAboutLimitations: Boolean = False) ?

Fair has nothing to do with it. Enums with jumps are an ugly hack, and go against all that enumerateds stand for. They only ensure some kind of type safety.

Using this ugly hack has consequences and should not be encouraged. Consequences:
- No for to
- No Succ/pred
- No low() high()
- No RTTI

and now, because you implemented it:
- No For in.

Like I said, we should not have named it enums. They are not enums. They're a hack to support some C construct in a type-safe way. No more, no less.

At the best you can name them 'auto-generated constants with possibility to specify an exception'.

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote
Fair has nothing to do with it. Enums with jumps are an ugly hack, and go against all that enumerateds stand for. They only ensure some kind of type safety.

Enums with jumps are hacks - agree.
Fair has nothing to do with it - disagree.

and now, because you implemented it: - No For in.

Under you presure I saw no possibility to implement for-in loop for that enums :) So I completely disabled for-in loop for them.

Best regards,
Paul Ishenin.

Reply by email

Michael Van Canneyt
to Paul Ishenin: Enums with jumps are hacks - agree. Fair has nothing to do with it - disagree. Under you…
Paul Ishenin wrote 10 lines
Michael Van Canneyt wrote: > Fair has nothing to do with it. Enums with jumps are an ugly hack, > and go against all that enumerateds stand for. They only ensure > some kind of type safety. Enums with jumps are hacks - agree. Fair has nothing to do with it - disagree. > and now, because you implemented it: > - No For in. Under you presure I saw no possibility to implement for-in loop for that enums :) So I completely disabled for-in loop for them.

I think it is a wise decision. It's an ugly construct, and is not worth the trouble (and I am convinced there would be more trouble than we can currently see :( )

Michael.

Reply by email

Vinzent Höfler
to Michael Van Canneyt: Fair has nothing to do with it. Enums with jumps are an ugly hack, and go against all…

Von: Michael Van Canneyt :

Like I said, we should not have named it enums. They are not enums. They're a hack to support some C construct in a type-safe way. No more, no less.

IBTD.

-- 8< --
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Conversion;

procedure Enumeration_Magic is

   --  Enumeration type.
   type Op_Codes is (Jmp, Inc, Dec);
   --  Representation with holes and same size as Standard.Integer.
   for Op_Codes use (Jmp => 1, Inc => 2, Dec => 5);
   for Op_Codes'Size use Integer'Size;
   --  Unsafe cast function to get access to the actual values.
   function To_Int is new Ada.Unchecked_Conversion (Source => Op_Codes,
                                                    Target => Integer);
   Low  : constant Op_Codes := Op_Codes'First;
   High : constant Op_Codes := Op_Codes'Last;
begin
   --  First/Last.
   Ada.Text_IO.Put_Line ("Low => "    & Low'Img &
                         ", High => " & High'Img);
   --  Loop through the range.
   for X in Op_Codes'Range loop
      Ada.Text_IO.Put_Line (X'Img & " => " & To_Int (X)'Img);
   end loop;
end Enumeration_Magic;
-- 8< --

Output:

-- 8< --
Low => JMP, High => DEC
JMP => 1
INC => 2
DEC => 5
-- 8< --

They might be an ugly hack, but I really doubt the part about being a C construct. And then, even in Ada, the definitions have to be in (ascending) order. Which means, the compiler only has to support "holes", not an arbitrary set of values.

Maybe this would be an option for FPC, too?

Vinzent.

Jetzt kostenlos herunterladen: Internet Explorer 8 und Mozilla Firefox 3.5 - sicherer, schneller und einfacher! http://portal.gmx.net/de/go/atbrowser

Reply by email

Alexander Klenin
to Vinzent Höfler
"Vinzent Höfler" wrote 7 lines
Von: Michael Van Canneyt : > Like I said, we should not have named it enums. They are not enums. > They're a hack to support some C construct in a type-safe way. > No more, no less. IBTD.

[skip Ada sample]

They might be an ugly hack, but I really doubt the part about being a C construct. And then, even in Ada, the definitions have to be in (ascending) order. Which means, the compiler only has to support "holes", not an arbitrary set of values. Maybe this would be an option for FPC, too?

I agree that there is, in principle, nothing wrong with sparse enums. However, Ada is well-known for sacrificing performance for correctness and generality, and I am not sure if FPC should follow that. The best Succ(X) algorithm I can think of that works correctly on sparse enums is O(log enum_size).

Which means, the compiler only has to support "holes", not an arbitrary set of values.
Yes, current enum implementation in FPC is slightly broken in this aspect:
---
type
  T = (a = 0, b = 0);
begin
  Writeln(b);
end.
---
Prints 'a'.
Alexander S. Klenin

Reply by email

Bram Kuijvenhoven
to Alexander Klenin: On Fri, Nov 6, 2009 at 05:51, "Vinzent Höfler" [skip Ada sample] I agree that there is,…
Alexander Klenin wrote
The best Succ(X) algorithm I can think of that works correctly on sparse enums is O(log enum_size).

As Florian does, I assume you discard the solution to use a lookup table from 'sparse values' to 'dense values'. Obviously that may quickly consume large amounts of memory, especially if the enum contains powers of two.

In theory, for .. in .. for sparse enums can be implemented in O(n) though. But then you should avoid using Succ.

Or, the memory location for a sparse enum variable could always contain a linear, 'dense' index into the table which holds the actual, 'sparse' values. Obviously this has a performance impact over not supporting Succ for sparse enums, but it doesn't change the runtime complexity of any code.

The question remains whether you're willing to put that much effort into it and whether you can live with the impact of doing table lookups each time the enum value needs to be casted to an integer (such as when calling C code).

Regards,

Bram

Reply by email