Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-08-03 Thread Michael Van Canneyt



On Sat, 3 Aug 2019, Ondrej Pokorny wrote:


On 13.07.2019 21:26, Michael Van Canneyt wrote:
I think all sides have now been reviewed to the point of boring or 
annoying each other almost to death, and we finally need to decide on 
whether the patch is applied, and if so, which parts of it.


That would be great. I have been waiting for some kind of decision or at 
least some statement from the compiler team for more than a year. Are 
there any news regarding the decision progress?


It has not been discussed on core.

As far as I am concerned, the patch can be applied. 
But since I don't manage the compiler, I have little voice in the process.


I will raise the subject on core.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-08-03 Thread Ondrej Pokorny

On 13.07.2019 21:26, Michael Van Canneyt wrote:
I think all sides have now been reviewed to the point of boring or 
annoying each other almost to death, and we finally need to decide on 
whether the patch is applied, and if so, which parts of it.


That would be great. I have been waiting for some kind of decision or at 
least some statement from the compiler team for more than a year. Are 
there any news regarding the decision progress?


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Ben Grasset
On Tue, Jul 16, 2019 at 8:35 AM Michael Van Canneyt 
wrote:

> 2. The Low(T) does not work, as there is no way to tell Delphi that T must
> be an enum.
>

Hmm, I guess it makes sense Delphi wouldn't allow the "Low", based on other
Delphi generics behavior (more like C#, whereas FPC is more like C++.)

I only realized recently that you can't even actually use "arithmetic"
operators on Delphi generics at all, E.G, the following is valid FPC code,
but not valid Delphi code:

program Example;

{$mode Delphi}

type
  TComparer = record
  public
class function Min(const A, B: T): T; static; inline;
class function Max(const A, B: T): T; static; inline;
  end;

  class function TComparer.Min(const A, B: T): T;
  begin
if A < B then
  Result := A
else
  Result := B;
  end;

  class function TComparer.Max(const A, B: T): T;
  begin
if A > B then
  Result := A
else
  Result := B;
  end;

begin
  WriteLn(TComparer.Min(2.0, 4.0));
  WriteLn(TComparer.Max(2.0, 4.0));
end.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Sven Barth via fpc-devel
Michael Van Canneyt  schrieb am Di., 16. Juli 2019,
16:31:

>
>
> On Tue, 16 Jul 2019, Ben Grasset wrote:
>
> > On Tue, Jul 16, 2019 at 5:28 AM Sven Barth via fpc-devel <
> > fpc-devel@lists.freepascal.org> wrote:
> >
> >> The output will then be two different addresses, thus showing that the
> >> code had been generated twice.
> >>
> >> However the compiler/linker is good at leaving out unused code and in
> this
> >> case only the two Assign specializations are kept as their addresses are
> >> taken, everything else is discarded. If you'd change one of the two to
> >> another non-virtual method then Assign of the one specialization and the
> >> other method of the other specialization would be kept.
> >>
> >> If you use virtual methods inside generics then things are less likely
> to
> >> be removed.
> >>
> >
> > Ah, I understand now.
> >
> > I guess my point overall was that, in my experience at least, while
> there's
> > indeed probably room for improvement in that area via something like WPO
> /
> > COMDAT support / e.t.c. as you'd suggested, the overall effect of
> generics
> > in FPC on binary size is not *unreasonable*.
> >
> > I use Delphi only semi-regularly, but it does seem to be somewhat more of
> > an actual issue there (as frankly binary size in recent Delphis is in
> > general, with generics or not, when compared to FPC.)
>
> I suspect this is also in part due to the liberal and generous use of
> extended RTTI.
>

Correct. We'll have to see how that works out with FPC...

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Michael Van Canneyt



On Tue, 16 Jul 2019, Ben Grasset wrote:


On Tue, Jul 16, 2019 at 5:28 AM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:


The output will then be two different addresses, thus showing that the
code had been generated twice.

However the compiler/linker is good at leaving out unused code and in this
case only the two Assign specializations are kept as their addresses are
taken, everything else is discarded. If you'd change one of the two to
another non-virtual method then Assign of the one specialization and the
other method of the other specialization would be kept.

If you use virtual methods inside generics then things are less likely to
be removed.



Ah, I understand now.

I guess my point overall was that, in my experience at least, while there's
indeed probably room for improvement in that area via something like WPO /
COMDAT support / e.t.c. as you'd suggested, the overall effect of generics
in FPC on binary size is not *unreasonable*.

I use Delphi only semi-regularly, but it does seem to be somewhat more of
an actual issue there (as frankly binary size in recent Delphis is in
general, with generics or not, when compared to FPC.)


I suspect this is also in part due to the liberal and generous use of extended 
RTTI.

Michael.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Ben Grasset
On Tue, Jul 16, 2019 at 5:28 AM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:

> The output will then be two different addresses, thus showing that the
> code had been generated twice.
>
> However the compiler/linker is good at leaving out unused code and in this
> case only the two Assign specializations are kept as their addresses are
> taken, everything else is discarded. If you'd change one of the two to
> another non-virtual method then Assign of the one specialization and the
> other method of the other specialization would be kept.
>
> If you use virtual methods inside generics then things are less likely to
> be removed.
>

Ah, I understand now.

I guess my point overall was that, in my experience at least, while there's
indeed probably room for improvement in that area via something like WPO /
COMDAT support / e.t.c. as you'd suggested, the overall effect of generics
in FPC on binary size is not *unreasonable*.

I use Delphi only semi-regularly, but it does seem to be somewhat more of
an actual issue there (as frankly binary size in recent Delphis is in
general, with generics or not, when compared to FPC.)
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Ben Grasset wrote:


On Sat, Jul 13, 2019 at 2:37 PM Ondrej Pokorny  wrote:


I do exactly the same - check the low/high bounds in a type helper :)
Yes, and I am tired of typing it as well :)



You can pretty easily write a generic function that will work on pretty
much any enum for this, BTW:

program Example;

{$mode Delphi}

uses TypInfo, SysUtils;

function TryConvert(const Value: SizeInt): T; inline;
begin
 if (Value >= SizeInt(Low(T))) and (Value <= SizeInt(High(T))) then
   Result := T(Value)
 else
   raise EConvertError.Create(
 Format(
   'Invalid value for %s : %d', [
 PTypeInfo(TypeInfo(T))^.Name,
 Value
   ]
 )
   );


For the record:

The above will not work in delphi for at least 2 reasons:
1. Simple fuctions are not supported. Can be worked around by making it part
of a record.
2. The Low(T) does not work, as there is no way to tell Delphi that T must
be an enum.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Sven Barth via fpc-devel
Ben Grasset  schrieb am Mo., 15. Juli 2019, 23:48:

> On Mon, Jul 15, 2019 at 5:23 PM Sven Barth via fpc-devel <
> fpc-devel@lists.freepascal.org> wrote:
>
>> That is exactly what is happening if you have a specialization in
>> multiple units that don't know about each other.
>>
>
> At what point are they being removed so that the executable is not
> comically large, then? Is it on the FPC side, or the linker side? Or a bit
> of both perhaps?
>

They are not removed. At least not in the way you think:

Declare a type" TTest = specialize TFPGList;" in two different
units (here ugentest1 and ugentest2) and then have the following program:

=== code begin ===

program tgentest;

{$mode objfpc}

uses
  ugentest1, ugentest2;

begin
  // TFPGList<>.Assign is a non-virtual method
  Writeln(HexStr(@ugentest1.TTest.Assign));
  Writeln(HexStr(@ugentest2.TTest.Assign));
end.

=== code end ===

The output will then be two different addresses, thus showing that the code
had been generated twice.

However the compiler/linker is good at leaving out unused code and in this
case only the two Assign specializations are kept as their addresses are
taken, everything else is discarded. If you'd change one of the two to
another non-virtual method then Assign of the one specialization and the
other method of the other specialization would be kept.

If you use virtual methods inside generics then things are less likely to
be removed.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Sven Barth via fpc-devel
Ben Grasset  schrieb am Di., 16. Juli 2019, 00:13:

> On Mon, Jul 15, 2019 at 5:50 PM Michael Van Canneyt <
> mich...@freepascal.org> wrote:
>
>> As far as I know, they are not. I believe that when specializing, the
>> compiler checks if an identical specialization is in scope:
>> if so, it uses that. If not, a duplicate is made.
>>
>> As far as I know, Delphi behaves the same.
>>
>> Michael.
>>
>
> I was aware of the "identical specialization" check (or at least, I
> assumed it worked that way.)
>
> It still seems to me though that while heavy use of generics is certainly
> reflected in PPU size (for example, on x86_64 Windows, the release mode PPU
> of Generics.Collections.pas with my build of FPC is slightly over 30 MB)
> the PPU size does not really correspond to object file size or overall
> binary size (which again might be thanks to some stage of FPC itself, or
> the linker in the case of external ones, or both.)
>
> I suppose FPC does probably diverge from Delphi behavior at some point
> there too, as Delphi uses only DCUs, with no separate ".O"s.
>

The *declaration* of a generic is reflected in the size of the PPU as the
token stream is stored there. While *specializations* are reflected in the
compiled object code, aka the .o file.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Sven Barth via fpc-devel
Michael Van Canneyt  schrieb am Mo., 15. Juli 2019,
23:50:

>
>
> On Mon, 15 Jul 2019, Ben Grasset wrote:
>
> > On Mon, Jul 15, 2019 at 5:23 PM Sven Barth via fpc-devel <
> > fpc-devel@lists.freepascal.org> wrote:
> >
> >> That is exactly what is happening if you have a specialization in
> multiple
> >> units that don't know about each other.
> >>
> >
> > At what point are they being removed so that the executable is not
> > comically large, then? Is it on the FPC side, or the linker side? Or a
> bit
> > of both perhaps?
>
> As far as I know, they are not. I believe that when specializing, the
> compiler checks if an identical specialization is in scope:
> if so, it uses that. If not, a duplicate is made.
>
> As far as I know, Delphi behaves the same.
>

Delphi changed this in one of the newer versions. That's also when the
behavior of class variables in generics changed.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-16 Thread Kai Burghardt
Nihao,

On Sat, Jul 13, 2019 at 01:52:46PM +0200, Michael Van Canneyt wrote:
> On Sat, 13 Jul 2019, Jonas Maebe wrote:
> > On 13/07/2019 13:28, J. Gareth Moreton wrote:
> > [...]
> > 
> > Declare your enumation types so that the lowest and highest valid value
> > comprise the lowest and highest value representable by its storage:
> > 
> > {$mode delphi}
> > {$z1}
> > type
> >  tmyenum = (ea, eb, ec, emax = 255);
> > 
> > That behaves the same both in FPC and in Delphi.
> 
> This is a completely pointless definition, since for effective use you still
> need to add code to check that the value is a named one.

Not to mention, that this is the job of the {$PACKENUM} directive,
ensuring an enumeration type reserves a minimum amount of space.
-- 
Sincerely yours
Kai Burghardt


signature.asc
Description: PGP signature
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Ben Grasset
On Mon, Jul 15, 2019 at 5:50 PM Michael Van Canneyt 
wrote:

> As far as I know, they are not. I believe that when specializing, the
> compiler checks if an identical specialization is in scope:
> if so, it uses that. If not, a duplicate is made.
>
> As far as I know, Delphi behaves the same.
>
> Michael.
>

I was aware of the "identical specialization" check (or at least, I assumed
it worked that way.)

It still seems to me though that while heavy use of generics is certainly
reflected in PPU size (for example, on x86_64 Windows, the release mode PPU
of Generics.Collections.pas with my build of FPC is slightly over 30 MB)
the PPU size does not really correspond to object file size or overall
binary size (which again might be thanks to some stage of FPC itself, or
the linker in the case of external ones, or both.)

I suppose FPC does probably diverge from Delphi behavior at some point
there too, as Delphi uses only DCUs, with no separate ".O"s.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Michael Van Canneyt



On Mon, 15 Jul 2019, Ben Grasset wrote:


On Mon, Jul 15, 2019 at 5:23 PM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:


That is exactly what is happening if you have a specialization in multiple
units that don't know about each other.



At what point are they being removed so that the executable is not
comically large, then? Is it on the FPC side, or the linker side? Or a bit
of both perhaps?


As far as I know, they are not. I believe that when specializing, the
compiler checks if an identical specialization is in scope: 
if so, it uses that. If not, a duplicate is made.


As far as I know, Delphi behaves the same.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Ben Grasset
On Mon, Jul 15, 2019 at 5:23 PM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:

> That is exactly what is happening if you have a specialization in multiple
> units that don't know about each other.
>

At what point are they being removed so that the executable is not
comically large, then? Is it on the FPC side, or the linker side? Or a bit
of both perhaps?
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Michael Van Canneyt



On Mon, 15 Jul 2019, Sven Barth via fpc-devel wrote:


Ben Grasset  schrieb am Mo., 15. Juli 2019, 22:57:


On Sat, Jul 13, 2019 at 9:02 PM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:


Not necessarily. If you have two units that don't know about each other
that specialize the function with the same enum then you'd have two
specializations already.



Surely that only applies to what winds up in the PPUs for the units in
question, if anything, though? As opposed to the object files and the final
executable. Like, I don't see how it could possibly be the case that if two
/ three / four / e.t.c units all use Generics.Collections, and each one
contains an instance of something like:

var IntList: TList

that this means the resulting binary contains  two / three / four /
e.t.c  separate complete instantiations of TList for LongInt. You'd wind up
with executables in the literal hundreds-of-megabytes range if that were
so, even with optimizations / symbol stripping and so on activated.



That is exactly what is happening if you have a specialization in multiple
units that don't know about each other.


Indeed. And this is a very common scenario.

For this reason, I explicitly declare all specializations I need in a
separate unit. To make sure there is only 1 of them for each type.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Sven Barth via fpc-devel
Ben Grasset  schrieb am Mo., 15. Juli 2019, 22:57:

> On Sat, Jul 13, 2019 at 9:02 PM Sven Barth via fpc-devel <
> fpc-devel@lists.freepascal.org> wrote:
>
>> Not necessarily. If you have two units that don't know about each other
>> that specialize the function with the same enum then you'd have two
>> specializations already.
>>
>
> Surely that only applies to what winds up in the PPUs for the units in
> question, if anything, though? As opposed to the object files and the final
> executable. Like, I don't see how it could possibly be the case that if two
> / three / four / e.t.c units all use Generics.Collections, and each one
> contains an instance of something like:
>
> var IntList: TList
>
> that this means the resulting binary contains  two / three / four /
> e.t.c  separate complete instantiations of TList for LongInt. You'd wind up
> with executables in the literal hundreds-of-megabytes range if that were
> so, even with optimizations / symbol stripping and so on activated.
>

That is exactly what is happening if you have a specialization in multiple
units that don't know about each other.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-15 Thread Ben Grasset
On Sat, Jul 13, 2019 at 9:02 PM Sven Barth via fpc-devel <
fpc-devel@lists.freepascal.org> wrote:

> Not necessarily. If you have two units that don't know about each other
> that specialize the function with the same enum then you'd have two
> specializations already.
>

Surely that only applies to what winds up in the PPUs for the units in
question, if anything, though? As opposed to the object files and the final
executable. Like, I don't see how it could possibly be the case that if two
/ three / four / e.t.c units all use Generics.Collections, and each one
contains an instance of something like:

var IntList: TList

that this means the resulting binary contains  two / three / four /
e.t.c  separate complete instantiations of TList for LongInt. You'd wind up
with executables in the literal hundreds-of-megabytes range if that were
so, even with optimizations / symbol stripping and so on activated.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Martok
> If you want to nitpick, the compiler will perform 1/2/4 byte writes for
> enums of those sizes, so the full reserved data is in fact
> used/initialised. Again: the only relevant part in this discussion is
> the valid values. The reserved/used/accessed/written/... storage size is
> unrelated to that to the extent explained in my previous message.
That was exactly my point!

The storage size is unrelated to the "used"/"valid" size, therefore there is
little point in being able to set it.
I can tell the compiler "this type is 4 bytes wide", but it will still only ever
consider the lowest byte if that's how many elements there are.

> This inconsistency would mean that we at least need two versions of
> defutils.getrange() in the compiler: one for (some) range checks (using
> the named range), and one for other reasoning (which must use the
> basedef range). There may be other such places that need modifications.
Interestingly, that's not the case, I checked.
There are like 2 major places that need adjustment, everything else already
correctly uses getrange for the type range and min/max for label range. It
almost looks as if most of the compiler was written assuming these two are not
the same.

The JVM class generator is the only real challenge. These days, one could
probably take a look at .Net Core to see how a managed language does this.

>> Arrays of such a type should not be allowed (as for enums with jumps right 
>> now)
>> (* although they could be without surprises, Array[tmyenum] would simply be
>> Array[Byte] *).
> 
> The whole point of a directive/modifier would be to get
> Delphi-compatible enums, not to add a third variant.
Where do you see a third variant? If you think this is anything but a
"Hejlsberg-Enum", I seriously failed to explain it.

The proposed syntax would be a shorthand for what Delphi does when you write
  {$Zn} tenum = (ea,eb,ec,ed);
With n:=sizeof(basetype).

Nothing else, nothing more.

> I meant that Delphi's range checking for enums/subranges doesn't make
> any sense due to the inconsistency between the "valid" and "declared" range.
The thing about $R and Delphi: a) it is purely ancillary and not part of the
type system. A *lot* of stuff is not rangechecked there at all. This has not a
lot to do with the nesting of type ranges.
b) only pred/succ, literal assignment without hard cast and assignment from
larger to smaller type are guaranteed to check if a subrange type is exceeded by
an action. Nothing else does - anything(!!) that fits in the same storage is a
valid value.

Both of that is documented behaviour, and has been for decades.


> E.g., take this Delphi program (tested with Kylix 3; YMMV with modern
> Delphi versions, to which I don't have access)
> [snip]
> This is both 100% inconsistent and 100% logical.
> On the other hand, you have this whole inconsistency where 255 is both a
> valid and an invalid value. So when a range check happens to be
> inserted, you get a range check error, and when it isn't, you don't.

One might argue that it is 100% consistent as well. Compile in {$R-} (remember,
in TP and Delphi it's a debugging aid, not a
thing-you-have-to-do-to-get-somehwat-safe-results like in FPC), and only the out
of bounds array accesses remain. And those are 100% equivalent to our old
friend, the unchecked jumptable access.

> As described in that post, the issue is that the default FPC units
> declare various enumeration types without any specific modifiers. Even
> if all default FPC units would be changed to Delphi-compatible enums,
> then you would still get issues when mixing and matching units declared
> with differently declared enumeration types, since there is no obvious
> way to know how a particular enumeration type has been declared.
Except, you know, looking at the source?

That's like arguing that there is no way to know if a record is packed or not.
Of course there is, it's a keyword right in the declaration.

Or, actually, more like asking what the calling convention of a function could
be. Usually you don't need to know, but when you do, it's either a keyword at
declaration site, or a {$CALLING} setting is in effect. No ambiguity at all.

That's why I say the decision must be clear at declaration point, not for every
access (as was previously suggested).


Best,
Sebastian





___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Jonas Maebe
On 14/07/2019 15:53, Martok wrote:
> Am 14.07.2019 um 14:18 schrieb Jonas Maebe:
>>> Side note: if this was done 100% consistently (and it does make sense!), the
>>> PACKENUM directive would be completely useless. There is no point in being 
>>> able
>>> to specify the storage size of an enum when it can be and is ignored at 
>>> will.
>>
>> In other cases, the requested storage size is reserved.
> 
> Oh please, don't troll.

Please refrain from throwing around insults.

> I know that you know that "is reserved" and "is used"
> are not the same thing.

If you want to nitpick, the compiler will perform 1/2/4 byte writes for
enums of those sizes, so the full reserved data is in fact
used/initialised. Again: the only relevant part in this discussion is
the valid values. The reserved/used/accessed/written/... storage size is
unrelated to that to the extent explained in my previous message.

>> The issue with a modifier or directive that would change the definition
>> of which values are valid for an enumerations with this modifier/within
>> this directive, is (besides the inconsistent low/high and range checking
>> behaviour from Delphi this would require,
> This is easy, enums already have separate min/max and a basedef. Make the
> basedef a type that can hold an orddef, modify calcsavesize and packedbitsize
> accordingly, done.
> Low/High will continue to provide the named range.

This inconsistency would mean that we at least need two versions of
defutils.getrange() in the compiler: one for (some) range checks (using
the named range), and one for other reasoning (which must use the
basedef range). There may be other such places that need modifications.

> Arrays of such a type should not be allowed (as for enums with jumps right 
> now)
> (* although they could be without surprises, Array[tmyenum] would simply be
> Array[Byte] *).

The whole point of a directive/modifier would be to get
Delphi-compatible enums, not to add a third variant.

> On Subranges, that's also simple and obvious.

I meant that Delphi's range checking for enums/subranges doesn't make
any sense due to the inconsistency between the "valid" and "declared" range.

E.g., take this Delphi program (tested with Kylix 3; YMMV with modern
Delphi versions, to which I don't have access)

{$z1}
type
  tenum = (ea, eb, ec, ed);
  tsubenum = eb..ed;
  tsubsubenum = ec..ed;
var
  enum, enum2: tenum;
  subenum: tsubenum;
  subsubenum: tsubsubenum;
  arr: array[tenum] of byte;
begin
{$r+}
  // no problem
  enum:=tenum(255);
  // no problem
  enum2:=enum;
  // segmentation fault
  arr[enum]:=2;
  // range error
  subenum:=enum;
  // no problem
  subenum:=tsubenum(255);
  // no problem
  enum:=subenum;
  // segmentation fault
  arr[subenum]:=2;
  // range error
  subsubenum:=subenum;
  // no problem
  subsubenum:=tsubsubenum(255);
  // no problem (!)
  subenum:=subsubenum;
  // no problem
  enum:=subsubenum;
  // segmentation fault
  arr[subsubenum]:=2;
end.

This is both 100% inconsistent and 100% logical.

It is logical because according to the (Delphi and FPC) type system
rules tsubsubenum <= tsubenum <= tenum, and hence every tsubsubenum by
definition is a valid subenum and a valid tenum, every tsubenum is a
valid tenum (and every valid t(sub)(sub)enum is a valid
t(sub)(sub)enum). As a result, you don't need any range checks when
converting them in that direction (an array indexation is also a type
conversion to the index type, hence the segmentation fault rather than
range error). However, the other way round does not necessarily hold,
and hence there are range checks when going in the other direction.

On the other hand, you have this whole inconsistency where 255 is both a
valid and an invalid value. So when a range check happens to be
inserted, you get a range check error, and when it isn't, you don't.

The only way to implement consistent range checking in this scenario is
by having range checks for every single enumeration type conversion,
even between the same type. Although then you get the curious situation
where 255 is at the same time both valid and triggering range check
errors all over the place as soon as you dare to use it. Plus you get a
whole bunch of unnecessary range check operations in code unless you add
a separate optimisation pass to remove them.

I completely understand the practical use case of this type of enums,
but from a type/correctness checking point of view it's utter nonsense.

>> the post I linked near the beginning of
>> the thread:
>> https://forum.lazarus.freepascal.org/index.php/topic,45507.msg322059.html#msg322059
> 
> As I wrote in the last message, those points would be fully addressed by this
> proposal. Choosing at declaration time is the only valid solution, all modes
> will behave exactly the same once the type is defined.

As described in that post, the issue is that the default FPC units
declare various enumeration types without any specific modifiers. Even
if all default FPC units would be changed to 

Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Martok
Am 14.07.2019 um 14:18 schrieb Jonas Maebe:
>> Side note: if this was done 100% consistently (and it does make sense!), the
>> PACKENUM directive would be completely useless. There is no point in being 
>> able
>> to specify the storage size of an enum when it can be and is ignored at will.
> 
> In other cases, the requested storage size is reserved.

Oh please, don't troll. I know that you know that "is reserved" and "is used"
are not the same thing.

> The most common cases to specify a storage size would be alignment, and
> the ability to add more valid values in the future without having to
> change the layout of a data structure.
... the only reasonable application of which is some kind of IO or an ABI that
shouldn't change, for which enums must not be used directly in the first place.

> It would solve nothing, and rather demonstrates the disconnect that
> apparently still exists in this discussion: the ability to bitpack enums
> (and hence reduce their storage size) is a mere side effect of the fact
> that their valid range only goes from the lowest to the highest declared
> value. You could reserve 4KB for an enum
No, you couldn't. The largest ordinal type is QWORD.


> The issue with a modifier or directive that would change the definition
> of which values are valid for an enumerations with this modifier/within
> this directive, is (besides the inconsistent low/high and range checking
> behaviour from Delphi this would require,
This is easy, enums already have separate min/max and a basedef. Make the
basedef a type that can hold an orddef, modify calcsavesize and packedbitsize
accordingly, done.
Low/High will continue to provide the named range.
Arrays of such a type should not be allowed (as for enums with jumps right now)
(* although they could be without surprises, Array[tmyenum] would simply be
Array[Byte] *).

On Subranges, that's also simple and obvious. That's the beauty of it, explicit
sizes would be explicit. They are not "inherited":

  tmyenum : Byte = (ea, eb, ec);
  tsubenum = eb..ec;
 //^ basedef=tmyenum, no explicit type, "fpc-style" enum,
 //  inherited symtable with ordinals $01 and $02
  tsubwenum: Word = eb..ec;
 //^ basedef=u16inttype, new symtable with ordinals $0001 and $0002

While the first example looks inconsistent, it is the same as what we already 
have:
{$PACKENUM 1}
  tmyenum = (ea, eb, ec);
{$PACKENUM DEFAULT}
  tsubenum = eb..ec;
tsubenum will be 4-bytes, tmyenum is 1 byte, same as with the new syntax.
tsubenum remains assignment compatible to tmyenum.

In contrast tmyenum.eb and tsubwenum.eb are not compatible, as the obviously
cannot be, since they have different _explicit_ sizes. I can't think of a
usecase for the second declaration in the first place, but getting correct
behaviour as a side effect is always a good sign.


> the post I linked near the beginning of
> the thread:
> https://forum.lazarus.freepascal.org/index.php/topic,45507.msg322059.html#msg322059

As I wrote in the last message, those points would be fully addressed by this
proposal. Choosing at declaration time is the only valid solution, all modes
will behave exactly the same once the type is defined.


Best,

Martok


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Jonas Maebe
On 14/07/2019 04:08, J. Gareth Moreton wrote:
> Just a thought that I'd chuck in on this... I did wonder how practical
> it would be to store checksums of all compiled procedures and the like
> and to look for collisions.  When studying how the compiler is built, I
> noticed a lot of the internal methods, due to conditional defines, would
> compile into identical code, so merging them would reduce the binary
> size if the linker is able to strip out procedures that are never
> called.  Granted, I haven't done research on how Free Pascal does Whole
> Program Optimisation yet, especially as it requiring a separate
> compilation pass has always put me off.  I would have thought that the
> linker should be able to handle it right there and then because it has
> all the information it needs.

Optimising linkers that do this exist. However, it's tricky to do it in
a safe way because programs may compare addresses of functions to
determine what to do. If those addresses become equal, program behaviour
can change. E.g.

procedure test1;
begin
end;

procedure test2;
begin
end;

procedure doit(proc: tprocedure);
begin
  if proc=@test1 then
writeln('test1')
  else
writeln('test2');
end;

begin
  doit(@test1);
  doit(@test2);
end.



Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Jonas Maebe
On 14/07/2019 00:12, Martok wrote:
> 
>> In Delphi's type system (and in C, C++, and C#), the valid values for an
>> enum are always all values that fit within its storage size, and that
>> storage size is fixed.
>>
>> In FPC's type system (and in Ada and Java), the valid values for an an
>> enum are only the values between the lowest and the highest declared
>> enum element (in Java it's even more strict, in that when you have
>> "enums with holes", the holes are also invalid), regardless of the
>> storage size. Moreover, this storage size can vary depending on whether
>> or not the item is in bitpacked storage.
> 
> Side note: if this was done 100% consistently (and it does make sense!), the
> PACKENUM directive would be completely useless. There is no point in being 
> able
> to specify the storage size of an enum when it can be and is ignored at will.

It is not ignored at will. It is only ignored when an enumeration is put
in a bitpacked array/record, i.e., when the programmer explicitly
instructs the compiler to ignore it. In other cases, the requested
storage size is reserved.

However, while storage size and valid values are related (you have to
have enough storage size to store the valid values), the fact that a
particular type can store a particular bitpattern does not mean that
this bitpattern is a valid value for the type. Just take an ansistring:
you can put any bitpattern in it that fits in a PtrSInt, yet most of
them are invalid and will result in undefined behaviour.

The most common cases to specify a storage size would be alignment, and
the ability to add more valid values in the future without having to
change the layout of a data structure.

> C# and C++ do the same with explicitly sized enumerations. Who would I have to
> bribe to get that in FPC?
> 
> {$mode objfpc}
> type
>   tmyenum : Byte = (ea, eb, ec);
> 
> That would solve literally all problems we ever discussed:

It would solve nothing, and rather demonstrates the disconnect that
apparently still exists in this discussion: the ability to bitpack enums
(and hence reduce their storage size) is a mere side effect of the fact
that their valid range only goes from the lowest to the highest declared
value. You could reserve 4KB for an enum with as only valid value
"enumX" and it would not change a thing as far as the valid values or
the compiler behaviour are concerned.

The issue with a modifier or directive that would change the definition
of which values are vali for an enumerations with this modifier/within
this directive, is (besides the inconsistent low/high and range checking
behaviour from Delphi this would require, especially when subranges also
enter the picture) explained in the post I linked near the beginning of
the thread:
https://forum.lazarus.freepascal.org/index.php/topic,45507.msg322059.html#msg322059


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-14 Thread Sven Barth via fpc-devel

Am 14.07.2019 um 04:08 schrieb J. Gareth Moreton:


Just a thought that I'd chuck in on this... I did wonder how practical 
it would be to store checksums of all compiled procedures and the like 
and to look for collisions.  When studying how the compiler is built, 
I noticed a lot of the internal methods, due to conditional defines, 
would compile into identical code, so merging them would reduce the 
binary size if the linker is able to strip out procedures that are 
never called.  Granted, I haven't done research on how Free Pascal 
does Whole Program Optimisation yet, especially as it requiring a 
separate compilation pass has always put me off.  I would have thought 
that the linker should be able to handle it right there and then 
because it has all the information it needs.


That would be a possible approach to use if the output format does not 
support combining equal sections. PE/COFF's COMDAT sections do have a 
flag that says that they need to have equal content (there are also 
other possibilities). Don't know right now whether ELF does.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread J. Gareth Moreton
Just a thought that I'd chuck in on this... I did wonder how practical 
it would be to store checksums of all compiled procedures and the like 
and to look for collisions.  When studying how the compiler is built, I 
noticed a lot of the internal methods, due to conditional defines, would 
compile into identical code, so merging them would reduce the binary 
size if the linker is able to strip out procedures that are never 
called.  Granted, I haven't done research on how Free Pascal does Whole 
Program Optimisation yet, especially as it requiring a separate 
compilation pass has always put me off.  I would have thought that the 
linker should be able to handle it right there and then because it has 
all the information it needs.


Gareth aka. Kit

On 14/07/2019 02:01, Sven Barth via fpc-devel wrote:
Ben Grasset mailto:operato...@gmail.com>> 
schrieb am Sa., 13. Juli 2019, 21:52:


On Sat, Jul 13, 2019 at 3:47 PM Michael Van Canneyt
mailto:mich...@freepascal.org>> wrote:

No doubt, but this will lead to a bloated binary. I want less
code (both
source and assembler), not more.


Well, it would be one instantiation per unique type it was used on.


Not necessarily. If you have two units that don't know about each 
other that specialize the function with the same enum then you'd have 
two specializations already.


This would need either a WPO pass or COMDAT support. Both are on my 
ToDo list, especially as the former is needed if the output format 
does not support the idea of COMDATs (e.g. PE/COFF and ELF do).


Regards,
Sven

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Sven Barth via fpc-devel
Ben Grasset  schrieb am Sa., 13. Juli 2019, 21:52:

> On Sat, Jul 13, 2019 at 3:47 PM Michael Van Canneyt <
> mich...@freepascal.org> wrote:
>
>> No doubt, but this will lead to a bloated binary. I want less code (both
>> source and assembler), not more.
>>
>
> Well, it would be one instantiation per unique type it was used on.
>

Not necessarily. If you have two units that don't know about each other
that specialize the function with the same enum then you'd have two
specializations already.

This would need either a WPO pass or COMDAT support. Both are on my ToDo
list, especially as the former is needed if the output format does not
support the idea of COMDATs (e.g. PE/COFF and ELF do).

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Martok

> In Delphi's type system (and in C, C++, and C#), the valid values for an
> enum are always all values that fit within its storage size, and that
> storage size is fixed.
> 
> In FPC's type system (and in Ada and Java), the valid values for an an
> enum are only the values between the lowest and the highest declared
> enum element (in Java it's even more strict, in that when you have
> "enums with holes", the holes are also invalid), regardless of the
> storage size. Moreover, this storage size can vary depending on whether
> or not the item is in bitpacked storage.

Side note: if this was done 100% consistently (and it does make sense!), the
PACKENUM directive would be completely useless. There is no point in being able
to specify the storage size of an enum when it can be and is ignored at will.


C# and C++ do the same with explicitly sized enumerations. Who would I have to
bribe to get that in FPC?

{$mode objfpc}
type
  tmyenum : Byte = (ea, eb, ec);

That would solve literally all problems we ever discussed:
 - the "scoped constant" concept is obvious when used
 - for bitpacking purposes, the bitsize is that of the explicit ordinal
 - therefore, any same-size cast (API return, file io, network io) is valid
 - {$Mode TP} and {$Mode Delphi} would treat all enum declarations as sized
enumerations of whatever $Z is set to at declaration time, fixing the "same
syntax but invisibly different result" portability issue
 - both type concepts would be consistently handled in the same type system
 - whenever that syntax is not used, all existing optimizations are valid
 - when it is used, others may be chosen
 - the case label checks would also catch any problems we don't yet see


Anything else (including the intrinsics this is about) is just a hacky
workaround to the difference Jonas summarised above, IMHO.

-- 
Regards,
Martok

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Ben Grasset
On Sat, Jul 13, 2019 at 3:59 PM Michael Van Canneyt 
wrote:

> Yes, I know. But the goal is to have 'is/as'. Then there is at best only 1
> helper
> function for all enumerateds.
>

Oh yeah, I wasn't really suggesting a generic function as a *solution* to
the problem versus "is" and "as". I was just pointing it out as a concept
that works in general and can be used right now (for things other than
enums as well).
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Ben Grasset wrote:


On Sat, Jul 13, 2019 at 3:47 PM Michael Van Canneyt 
wrote:


No doubt, but this will lead to a bloated binary. I want less code (both
source and assembler), not more.



Well, it would be one instantiation per unique type it was used on.


I know. See below.



So if you had five hand-written helper functions for different types, and
replaced all of them with the use of a single generic function, you'd still
end up with just five functions worth of assembler code (i.e. the same
amount you had to begin with.)


Yes, I know. But the goal is to have 'is/as'. Then there is at best only 1 
helper
function for all enumerateds.

I have a Delphi project that uses really lots of generics. The decrease in
compilation speed and increase in binary size is truly noticeable.


In general, I strive to minimalize the use of generics or avoid them at all. 
IMO there are little use cases that really justify the use of generics. 
But that's a highly personal opinion.



Michael.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Ben Grasset
On Sat, Jul 13, 2019 at 3:47 PM Michael Van Canneyt 
wrote:

> No doubt, but this will lead to a bloated binary. I want less code (both
> source and assembler), not more.
>

Well, it would be one instantiation per unique type it was used on.

So if you had five hand-written helper functions for different types, and
replaced all of them with the use of a single generic function, you'd still
end up with just five functions worth of assembler code (i.e. the same
amount you had to begin with.)
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Ben Grasset wrote:


On Sat, Jul 13, 2019 at 2:37 PM Ondrej Pokorny  wrote:


I do exactly the same - check the low/high bounds in a type helper :)
Yes, and I am tired of typing it as well :)



You can pretty easily write a generic function that will work on pretty
much any enum for this, BTW:


No doubt, but this will lead to a bloated binary. I want less code (both
source and assembler), not more.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Ben Grasset
On Sat, Jul 13, 2019 at 2:37 PM Ondrej Pokorny  wrote:

> I do exactly the same - check the low/high bounds in a type helper :)
> Yes, and I am tired of typing it as well :)
>

You can pretty easily write a generic function that will work on pretty
much any enum for this, BTW:

program Example;

{$mode Delphi}

uses TypInfo, SysUtils;

function TryConvert(const Value: SizeInt): T; inline;
begin
  if (Value >= SizeInt(Low(T))) and (Value <= SizeInt(High(T))) then
Result := T(Value)
  else
raise EConvertError.Create(
  Format(
'Invalid value for %s : %d', [
  PTypeInfo(TypeInfo(T))^.Name,
  Value
]
  )
);
end;

type
  Letter = (A, B, C);

begin
  WriteLn(TryConvert(0));
  WriteLn(TryConvert(1));
  WriteLn(TryConvert(2));
  // Exception!
  WriteLn(TryConvert(3));
end.

The exception printing "EConvertError: Invalid value for Letter : 3", of
course.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Ondrej Pokorny wrote:




Even to such a degree that the compiler would
simply reject your code by not allowing is/at on a variable of the type
itself. Also defendable.


No - not this one. Don't forget about e.g. generics:
function Test(MyValue: T): Boolean;
begin
  Result := MyValue is TMyEnum;
end;
would compile for all enumeration types but not for MyValue:TMyEnum. 
That doesn't make sense.


Better to have a compiler hint/warning when such a construct is found 
and optimized. This perfectly corresponds with the fact that also 
constructs like "SmallIntValue is Integer" can be optimized away but 
must be allowed.


Fair enough. 
Like I said: The point is defendable. So is your point of view.


Personally I am OK with either point of view. 
I am just interested in the ordinal, to make an easier check possible.


I think all sides have now been reviewed to the point of boring or
annoying each other almost to death, and we finally need to decide on 
whether the patch is applied, and if so, which parts of it.


Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Ondrej Pokorny

On 13.07.2019 13:47, J. Gareth Moreton wrote:
Here lies the problem - if you have a enumeration stored in a byte 
field, say, in a file, and there's a chance it's been corrupted, 
there's no reliable way to detect that, since even typecasting may not 
be reliable, and once again I'm implying that enums are unsafe to use, 
but right now, what else can one do?


Don't forget about my second suggestion: add internal range checking for 
enumeration values on specific operations: 
https://lists.freepascal.org/pipermail/fpc-devel/2019-July/041499.html


The "BUT (big BUT)" section in the 2nd half of the email. I copy it here 
with one small update:


BUT (big BUT): I suggest to do an enumeration/subrange validity check on 
the compiler side when range checking is used. This is similar to the 
current fpc_check_object intrinsic.


When range checking is used, this check should be injected (at least) 
before every case-of and the new is/as operators if they are replaced 
with true. When range checking is disabled, the check should not be 
injected at all. Examples for range checking:


1.) case MyEnumValue of // <<< here an enumeration validity check should 
be injected
2.) IsValid := SomeValue is TEnumValue; //  <<< here an enumeration 
validity check should be injected if SomeValue is an enumeration type. 
(It doesn't make sense for normal ordinal values like Integer because 
they are valid in the whole stored range.)

That would catch the
IsValid := MyEnumValue is TEnumValue;
check - it would be replaced by a TRUE constant but there would still be 
a range check injected that would raise an error in case MyEnumValueis 
not valid.


IMO such a solution is acceptable for both sides:
1.) Jonas' point: The clarity of the language will stay untouched 
because the new validity check will be only informative and used only 
for debugging without any assurance of correctness. (You see the 
difference: MyEnumValue is TEnumValue will raise an exception for an 
invalid value and not return false! False will be returned only for 
(MyInt is TEnumValue) if MyInt is ot of the range of TEnumValue.)


2.) My/J.Gareth's point: We will get an information about invalid enum 
values (range check error) instead of "undefined behavior" when 
debugging - and we
will be able to find code where invalid enum values can occur and fix 
the code where these values were assigned. Although this information may 
not be (theoretically) absolutely accurate (the same as fpc_check_object 
is not absolutely accurate), it will still be pretty accurate and it 
will be a big help during the debugging.


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Ondrej Pokorny

On 13.07.2019 14:32, Michael Van Canneyt wrote:

I yesterday checked a database project I have. I counted 25 enumerateds
which are stored in the database. Without fail, for each type there is 
somewhere code in a type helper:


if (MyDatabaseValue>=0) and (MyDatabaseValue<=Ord(High(TMyENum))) then
  MyENumValue:=TEnum(MyDatabaseValue))
else
  EConvertError.Create('Invalid value for TMyEnum : %d',[MyDatabaseValue])


I do exactly the same - check the low/high bounds in a type helper :) 
Yes, and I am tired of typing it as well :)




That the case where you would write

if MyEnumValue is TMyEnumValue then

can 'by default' be optimized away because as far as the compiler is
concerned this is a tautology, is for me a perfectly acceptable and
defendable point of view.


I agree.



Even to such a degree that the compiler would
simply reject your code by not allowing is/at on a variable of the type
itself. Also defendable.


No - not this one. Don't forget about e.g. generics:
function Test(MyValue: T): Boolean;
begin
  Result := MyValue is TMyEnum;
end;
would compile for all enumeration types but not for MyValue:TMyEnum. 
That doesn't make sense.


Better to have a compiler hint/warning when such a construct is found 
and optimized. This perfectly corresponds with the fact that also 
constructs like "SmallIntValue is Integer" can be optimized away but 
must be allowed.


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Jonas Maebe wrote:


On 13/07/2019 13:52, Michael Van Canneyt wrote:



On Sat, 13 Jul 2019, Jonas Maebe wrote:


On 13/07/2019 13:28, J. Gareth Moreton wrote:

Okay, okay.  So what do we do to stop all these bug reports and help
programmers who get caught out by case blocks raising access
violations?  Are you effectively saying "don't ever use enumerations for
external files and network signals" etc?


Declare your enumation types so that the lowest and highest valid value
comprise the lowest and highest value representable by its storage:

{$mode delphi}
{$z1}
type
 tmyenum = (ea, eb, ec, emax = 255);

That behaves the same both in FPC and in Delphi.


This is a completely pointless definition, since for effective use you
still need to add code to check that the value is a named one.


That is exactly what this thread is about: the ability to manually check
whether an enumeration value is one of the valid (named) values.


I know.

I simply do not want to change a type definition just to keep the compiler 
happy.

I want to define a type as dictated by my use case:
  tmyenum = (ea, eb, ec)

and then some easy means to check if an ordinal value fits. Hence the Is/as.

I yesterday checked a database project I have. I counted 25 enumerateds
which are stored in the database. Without fail, for each type 
there is somewhere code in a type helper:


if (MyDatabaseValue>=0) and (MyDatabaseValue<=Ord(High(TMyENum))) then
  MyENumValue:=TEnum(MyDatabaseValue))
else
  EConvertError.Create('Invalid value for TMyEnum : %d',[MyDatabaseValue])

If I can replace this with a simple

  MyEnumValue:=MyDatabaseValue as TMyEnumValue

It makes life a lot easier. So this construct has my support.

That the case where you would write

if MyEnumValue is TMyEnumValue then

can 'by default' be optimized away because as far as the compiler is
concerned this is a tautology, is for me a perfectly acceptable and
defendable point of view. Even to such a degree that the compiler would
simply reject your code by not allowing is/at on a variable of the type
itself. Also defendable.

The check on a valid value using is/as should be done before the enum variable 
is
used/assigned.

I just want to make the check easier.


Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Martin Frb

On 13/07/2019 13:47, J. Gareth Moreton wrote:
Here lies the problem - if you have a enumeration stored in a byte 
field, say, in a file, and there's a chance it's been corrupted, 
there's no reliable way to detect that, since even typecasting may not 
be reliable, and once again I'm implying that enums are unsafe to use, 
but right now, what else can one do?

Well yes. Reading from a file is like a typecast.

TEnum(SomeInt) implies that you have done the validity check *before* 
this. Because by using the type you declare that the result is valid.


Of course reading from a file/api you can not do the test before

But if you want the test afterwards, you must change the entire 
definition of the type. Changing it for just one statement (the "is") 
can not work for technical reasons (see my previous post). You do not 
know what other side-effects you may have done in the statement that 
typecasted an unchecked/invalid value. If you do not know the list of 
possible side effects, then you can not test for all of them.


I would guess this would work

{$mode delphi}
{$z1}
type
 tmyFileEnum = (ea, eb, ec, emax = 255);
 tmyenum = (ea, eb, ec);

read(file, AFileEnum);
if AFileEnum is TMyEnum
then AMyEnum := TMyEnum(AFileEnum)
else DoError;
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Jonas Maebe
On 13/07/2019 13:52, Michael Van Canneyt wrote:
> 
> 
> On Sat, 13 Jul 2019, Jonas Maebe wrote:
> 
>> On 13/07/2019 13:28, J. Gareth Moreton wrote:
>>> Okay, okay.  So what do we do to stop all these bug reports and help
>>> programmers who get caught out by case blocks raising access
>>> violations?  Are you effectively saying "don't ever use enumerations for
>>> external files and network signals" etc?
>>
>> Declare your enumation types so that the lowest and highest valid value
>> comprise the lowest and highest value representable by its storage:
>>
>> {$mode delphi}
>> {$z1}
>> type
>>  tmyenum = (ea, eb, ec, emax = 255);
>>
>> That behaves the same both in FPC and in Delphi.
> 
> This is a completely pointless definition, since for effective use you
> still need to add code to check that the value is a named one.

That is exactly what this thread is about: the ability to manually check
whether an enumeration value is one of the valid (named) values.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Michael Van Canneyt



On Sat, 13 Jul 2019, Jonas Maebe wrote:


On 13/07/2019 13:28, J. Gareth Moreton wrote:

Okay, okay.  So what do we do to stop all these bug reports and help
programmers who get caught out by case blocks raising access
violations?  Are you effectively saying "don't ever use enumerations for
external files and network signals" etc?


Declare your enumation types so that the lowest and highest valid value
comprise the lowest and highest value representable by its storage:

{$mode delphi}
{$z1}
type
 tmyenum = (ea, eb, ec, emax = 255);

That behaves the same both in FPC and in Delphi.


This is a completely pointless definition, since for effective use 
you still need to add code to check that the value is a named one.


Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread J. Gareth Moreton
I see your point.  There seems to be some argument because it 
effectively bans the use of enumerations in external data (e.g. a file, 
network packet or third-party API) if there's a chance that the value is 
corrupted or has been tampered with, because sometimes allowing the 
program to crash is not acceptable.  Though misinterpreted, Michael said 
this to me when I mentioned to the effect of "in that case, you could 
only use Integers etc. for external data":


...

With this sentence you forbid storing or communicating enumerated values 
in any way: file, database, over network. It can be used only in a 
computer program and never

leave the context of the running program under any form. Because as soon as
it is somehow communicated, there is a chance it becomes invalid in return
communication.

Additionally you must then also abolish typecasting to an enumerated (or
pointers to enumerated values), since that also can be a source of invalid
values for an enumerated.

Or are you realy advocating we write code such as

Case MyInteger of
  0 : MyEnum:=ValueOrd0
  1 : MyEnum:=ValueOrd2;
else
  someError
end;
etc, whenever an integer must be changed to an enumerated ?

IMHO you would reduce the usabilty of enumerateds to almost zero by doing
so.

...

Here lies the problem - if you have a enumeration stored in a byte 
field, say, in a file, and there's a chance it's been corrupted, there's 
no reliable way to detect that, since even typecasting may not be 
reliable, and once again I'm implying that enums are unsafe to use, but 
right now, what else can one do?


Gareth aka. Kit


On 13/07/2019 12:28, Martin Frb wrote:

On 11/07/2019 15:46, J. Gareth Moreton wrote:


For my personal point of view, I would like these operators to be the 
exception to the rule of the compiler assuming an enum always 
contains a valid value,


As much as I would like to agree with you (and yes I think such a 
check, if possible, would be desirable - even if it meant to ignore 
certain language design principles), it is indeed not possible.
Maybe it would be today (as in today's fpc implementation), maybe not. 
I do not know.


But it would not be future safe.

Lets say "fpc breaks the rule for "is/as" and only for those".

  FooEnum := SomeApi();
  if not (FooEnum is TFooEnum) then FooEnum := low(TFooEnum);

Now we do *not* know what the optimizer does in the first line. And 
that is the problem.
On some platform (that we have no clue of today), the compiler may 
store the value bitpacked into a temp var/register. The storage is 
shared with other values.
If the result of "SomeApi()" is out of bounds, it might overwrite one 
of the other values stored in that var/register.
The "is" can only check the part of the storage actually meant to be 
used by the enum. The change to the other value goes unnoticed.


So in such a future case, the is may do what you expect. A later "case 
FooEnum" will be ok, as FooEnum is "forced" to be valid.
But your program still crashes, due to the other var being modified 
unexpectedly.


Yes that may sound far fetched. But maybe some embedded system, with 
scarce resources requires such behaviour?



Maybe a possible solution would be based on:

On 13/07/2019 12:48, Jonas Maebe wrote:
In Delphi's type system (and in C, C++, and C#), the valid values for 
an enum are always all values that fit within its storage size, and 
that storage size is fixed.


Create such an enum type in fpc too (as a new type / assignment 
compatible with the current enum)


  {modeswitch StorageSizeValidEnum}
  type TFullFooEnum = (a,b,c);

would treat all values of the (unpacked) storage as valid.
As a consequence:
 - it can not be packed / it would keep its full size
 - many optimizations can not be applied

But for such a type, that has explicitly been defined as having all 
the other values, you could use "is".
Of course not straight forward. Because now  255 is a valid value for 
that enum, so "is" would return true. But with:


  {modeswitch StorageSizeValidEnum on}
  type TFullFooEnum = (a,b,c);
  {modeswitch StorageSizeValidEnum off}
  type TFooEnum = (a,b,c);

this would work:
  if  FullFooEnum is TFooEnum then

Since this is only/mainly used for "external" data, the extra type def 
would not be to much overhead.


Of course, it is merely syntactical sugar, since it is identical too
  type TFullFooEnum = integer; //or whatever represents the storage size
  type TFooEnum = (a,b,c);

It only allows to have named values for that "integer"
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Jonas Maebe
On 13/07/2019 13:28, J. Gareth Moreton wrote:
> Okay, okay.  So what do we do to stop all these bug reports and help
> programmers who get caught out by case blocks raising access
> violations?  Are you effectively saying "don't ever use enumerations for
> external files and network signals" etc?

Declare your enumation types so that the lowest and highest valid value
comprise the lowest and highest value representable by its storage:

{$mode delphi}
{$z1}
type
  tmyenum = (ea, eb, ec, emax = 255);

That behaves the same both in FPC and in Delphi.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Martin Frb

On 11/07/2019 15:46, J. Gareth Moreton wrote:


For my personal point of view, I would like these operators to be the 
exception to the rule of the compiler assuming an enum always contains 
a valid value,


As much as I would like to agree with you (and yes I think such a check, 
if possible, would be desirable - even if it meant to ignore certain 
language design principles), it is indeed not possible.
Maybe it would be today (as in today's fpc implementation), maybe not. I 
do not know.


But it would not be future safe.

Lets say "fpc breaks the rule for "is/as" and only for those".

  FooEnum := SomeApi();
  if not (FooEnum is TFooEnum) then FooEnum := low(TFooEnum);

Now we do *not* know what the optimizer does in the first line. And that 
is the problem.
On some platform (that we have no clue of today), the compiler may store 
the value bitpacked into a temp var/register. The storage is shared with 
other values.
If the result of "SomeApi()" is out of bounds, it might overwrite one of 
the other values stored in that var/register.
The "is" can only check the part of the storage actually meant to be 
used by the enum. The change to the other value goes unnoticed.


So in such a future case, the is may do what you expect. A later "case 
FooEnum" will be ok, as FooEnum is "forced" to be valid.
But your program still crashes, due to the other var being modified 
unexpectedly.


Yes that may sound far fetched. But maybe some embedded system, with 
scarce resources requires such behaviour?



Maybe a possible solution would be based on:

On 13/07/2019 12:48, Jonas Maebe wrote:
In Delphi's type system (and in C, C++, and C#), the valid values for 
an enum are always all values that fit within its storage size, and 
that storage size is fixed.


Create such an enum type in fpc too (as a new type / assignment 
compatible with the current enum)


  {modeswitch StorageSizeValidEnum}
  type TFullFooEnum = (a,b,c);

would treat all values of the (unpacked) storage as valid.
As a consequence:
 - it can not be packed / it would keep its full size
 - many optimizations can not be applied

But for such a type, that has explicitly been defined as having all the 
other values, you could use "is".
Of course not straight forward. Because now  255 is a valid value for 
that enum, so "is" would return true. But with:


  {modeswitch StorageSizeValidEnum on}
  type TFullFooEnum = (a,b,c);
  {modeswitch StorageSizeValidEnum off}
  type TFooEnum = (a,b,c);

this would work:
  if  FullFooEnum is TFooEnum then

Since this is only/mainly used for "external" data, the extra type def 
would not be to much overhead.


Of course, it is merely syntactical sugar, since it is identical too
  type TFullFooEnum = integer; //or whatever represents the storage size
  type TFooEnum = (a,b,c);

It only allows to have named values for that "integer"
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread J. Gareth Moreton
Okay, okay.  So what do we do to stop all these bug reports and help 
programmers who get caught out by case blocks raising access 
violations?  Are you effectively saying "don't ever use enumerations for 
external files and network signals" etc?


Gareth aka. Kit


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-13 Thread Jonas Maebe
On 11/07/2019 15:46, J. Gareth Moreton wrote:
> Outside of typecasting, there isn't a reliable way to check if an enum
> contains a valid value

Typecasting is not a reliable way. There is no and cannot be a reliable
way, period.

> For my personal point of view, I would like these operators to be the
> exception to the rule of the compiler assuming an enum always contains a
> valid value,

This is the crux of the whole issue. Type systems do not and cannot work
this way. At its heart, this discussion is not about compiler
assumptions, optimisations, exploiting undefined behaviour etc.

It's that if a language has a type system, then by definition all
reasoning over programs written in this language must follow the rules
of this type system. A fundamental part of this is that a variable of
type X can store all values that are valid for type X. Not more, and not
less.

This is true for FPC, Delphi, C, C++, C#, Java, ADA any every other
programming language in existence that has a type system. Otherwise you
do not have a type system, but at most some ad hoc behaviours that
vaguely resemble a type system. You can never deviate from this, or you
end up with an unmaintainable and unpredictable mess (regardless of how
well you know the basic rules of the language, and not just when you are
used to type system with different rules).

In Delphi's type system (and in C, C++, and C#), the valid values for an
enum are always all values that fit within its storage size, and that
storage size is fixed.

In FPC's type system (and in Ada and Java), the valid values for an an
enum are only the values between the lowest and the highest declared
enum element (in Java it's even more strict, in that when you have
"enums with holes", the holes are also invalid), regardless of the
storage size. Moreover, this storage size can vary depending on whether
or not the item is in bitpacked storage. That definition of enums is
also what allows us to bitpack these types in the first place, since
otherwise we would not be able to store all valid values for enums in
their bitpacked versions.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread J. Gareth Moreton


On 11/07/2019 13:07, Michael Van Canneyt wrote:

There is no "disagreement". just doubt as to what the right approach is.

If the compiler assumes that an enumerated always contains a valid value,
then the logical consequence is that the above "is" always evaluates to
true. In that case it makes sense to downright forbid the construct, 
as it

only makes sense if MyEnumValue is another ordinal type.


The case of bitpacked values and variant records shows that the language
allows for cases where this assumption is maybe not correct. From this 
point

of view, the above construct is a valid check and should not be optimized
away.

It now depends on your point of view what road to take.

Michael.


Well, the patch ("AS-IS-enum-10.patch") was made on the assumption that 
"MyEnum is TMyEnum" will do a range check and return False if it's out 
of bounds.


Outside of typecasting, there isn't a reliable way to check if an enum 
contains a valid value, which leads to the problem of reading an enum 
from an external source that may be tampered or corrupted.  I had the 
impression that "as" and "is" would be a reliable sanity check to see if 
the enum is in bounds.


For my personal point of view, I would like these operators to be the 
exception to the rule of the compiler assuming an enum always contains a 
valid value, and above all, the documentation improved for "case" that 
advises the programmer to use the operators if they are using 
enumerations and there's a chance the input may be invalid.  Whatever 
decision is made though, I do think there should be a warning in the 
documentation and a suggested workaround just so we don't keep getting 
bug reports.


I'm not on the core team though, so the final decision ultimately 
doesn't rest on me, but for what it's worth, I would like "MyEnum is 
TMyEnum" to not assume the answer is True and to actually perform an 
explicit check.  However, there is an argument to be made for both 
approaches.


Gareth aka. Kit


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread Michael Van Canneyt



On Thu, 11 Jul 2019, J. Gareth Moreton wrote:


On 11/07/2019 11:52, Ondrej Pokorny wrote:
BTW, your note in the issue report is very misleading: 
https://bugs.freepascal.org/view.php?id=33603#c117162.


> The idea behind "is" and "as" is that they are the sole exception to 
the rule and will return False and raise an error respectively if the 
enum is out of bounds.


IS/AS are not an exception of the rule - after a long discussion we 
settled down that if IS/AS is applied on a value of the same 
enumeration type:


var
  MyEnumValue: TEnumValue;
begin
  if MyEnumValue is TEnumValue then
// ...
end;

the compiler will expect that the result is always true. (It doesn't 
have to check for invalid values.)


Who is "we" in this case? I was under the impression that is/as could be 
used to check if the enumeration was valid or not, as a means to check 
if the enueration contained a valid value or not so as to avoid problems 
with case blocks raising access violations. I guess we've hit 
disagreements again.


There is no "disagreement". just doubt as to what the right approach is.

If the compiler assumes that an enumerated always contains a valid value,
then the logical consequence is that the above "is" always evaluates to
true. In that case it makes sense to downright forbid the construct, as it
only makes sense if MyEnumValue is another ordinal type.


The case of bitpacked values and variant records shows that the language
allows for cases where this assumption is maybe not correct. From this point
of view, the above construct is a valid check and should not be optimized
away.

It now depends on your point of view what road to take.

Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread J. Gareth Moreton

On 11/07/2019 11:52, Ondrej Pokorny wrote:
BTW, your note in the issue report is very misleading: 
https://bugs.freepascal.org/view.php?id=33603#c117162.


> The idea behind "is" and "as" is that they are the sole exception to 
the rule and will return False and raise an error respectively if the 
enum is out of bounds.


IS/AS are not an exception of the rule - after a long discussion we 
settled down that if IS/AS is applied on a value of the same 
enumeration type:


var
  MyEnumValue: TEnumValue;
begin
  if MyEnumValue is TEnumValue then
// ...
end;

the compiler will expect that the result is always true. (It doesn't 
have to check for invalid values.)


Who is "we" in this case? I was under the impression that is/as could be 
used to check if the enumeration was valid or not, as a means to check 
if the enueration contained a valid value or not so as to avoid problems 
with case blocks raising access violations. I guess we've hit 
disagreements again.


Gareth


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread Ondrej Pokorny

On 11.07.2019 11:58, J. Gareth Moreton wrote:


Done!


Thank you for your work!

BTW, your note in the issue report is very misleading: 
https://bugs.freepascal.org/view.php?id=33603#c117162.


> The idea behind "is" and "as" is that they are the sole exception to 
the rule and will return False and raise an error respectively if the 
enum is out of bounds.


IS/AS are not an exception of the rule - after a long discussion we 
settled down that if IS/AS is applied on a value of the same enumeration 
type:


var
  MyEnumValue: TEnumValue;
begin
  if MyEnumValue is TEnumValue then
// ...
end;

the compiler will expect that the result is always true. (It doesn't 
have to check for invalid values.)


When I read the following sentence:
> If the value falls within a hole, then it will pass - currently only 
in Delphi mode though. FPC mode won't allow it.


I think you mixed up "normal enums" and "enums with holes" and so the 
note in the issue report doesn't make any sense.




The conclusion is:
1.) IS/AS works reliably only on valid values on the left side of the 
operator. (Like any other function/intrinsic/operator in FPC.)
2.) If an invalid value is to be expected, IS/AS must be executed on an 
ordinal value (Integer, SmallInt, ...) before assigning it to the 
enumeration value. It cannot be executed on the resulting enumeration 
value to check its validity.
3.) IS/AS can be used also on "enumerations with holes". In this respect 
only the low/high bounds are checked, not the holes inside the valid range.

4.) IS/AS can be also used on ordinal types:
 - 4a.) (MyInt64Value is Integer) is a reasonable check if MyInt64Value 
is in Integer range.
 - 4b.) (MyIntegerValue is Int64) is not reasonable (Integer falls 
always into Int64 range) and will always return True and can/will be 
optimized by the compiler to return a True constant.


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread J. Gareth Moreton

Done!


On 11/07/2019 07:51, Michael Van Canneyt wrote:



On Thu, 11 Jul 2019, J. Gareth Moreton wrote:

Should I modify the patch to allow enumerations with holes with "is" 
and "as"?  Note that these operators will return True/not raise an 
error if a value falls within a hole but is otherwise between the 
lowest and highest elements.


IMO, yes.

Michael.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread Michael Van Canneyt



On Thu, 11 Jul 2019, J. Gareth Moreton wrote:

Should I modify the patch to allow enumerations with holes with "is" and 
"as"?  Note that these operators will return True/not raise an error if a 
value falls within a hole but is otherwise between the lowest and highest 
elements.


IMO, yes.

Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-11 Thread J. Gareth Moreton
Should I modify the patch to allow enumerations with holes with "is" and 
"as"?  Note that these operators will return True/not raise an error if 
a value falls within a hole but is otherwise between the lowest and 
highest elements.


Gareth aka. Kit

On 09/07/2019 20:19, J. Gareth Moreton wrote:


Hopefully we'll get there in the end!  I've updated what I can in the 
patch file directly, so hopefully all is well now.


Some of the variable names, like "ProcName", were already named as such.

Gareth aka. Kit

On 09/07/2019 10:12, Sven Barth via fpc-devel wrote:
J. Gareth Moreton > schrieb am Di., 9. Juli 2019, 08:20:


Apologies - I see now... I used them with "with" without even
thinking
about it!  I've made the changes as requested. Admittedly it's quite
hard for me to remove spaces from either side of operators because
that's something I learnt from my early days in Turbo Pascal and
to not
have spaces (and all types and variables being lowercase) feels very
C-like.  But hey, rules are rules... or guidelines!


I know the feeling. But when in Rome...

Is the new AS-IS-enum-08 patch any better?


Better (though are still some " = " around :P ), but it seems you 
missed tasnode.pass_1?
Also the typenames (TOrdDef, TEnumDef) should be lowercase as well as 
the local variables.


Regards,
Sven


___
fpc-devel maillist  -fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


 
	Virus-free. www.avast.com 
 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-09 Thread J. Gareth Moreton
Hopefully we'll get there in the end!  I've updated what I can in the 
patch file directly, so hopefully all is well now.


Some of the variable names, like "ProcName", were already named as such.

Gareth aka. Kit

On 09/07/2019 10:12, Sven Barth via fpc-devel wrote:
J. Gareth Moreton > schrieb am Di., 9. Juli 2019, 08:20:


Apologies - I see now... I used them with "with" without even
thinking
about it!  I've made the changes as requested. Admittedly it's quite
hard for me to remove spaces from either side of operators because
that's something I learnt from my early days in Turbo Pascal and
to not
have spaces (and all types and variables being lowercase) feels very
C-like.  But hey, rules are rules... or guidelines!


I know the feeling. But when in Rome...

Is the new AS-IS-enum-08 patch any better?


Better (though are still some " = " around :P ), but it seems you 
missed tasnode.pass_1?
Also the typenames (TOrdDef, TEnumDef) should be lowercase as well as 
the local variables.


Regards,
Sven


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-09 Thread Sven Barth via fpc-devel
J. Gareth Moreton  schrieb am Di., 9. Juli 2019,
08:20:

> Apologies - I see now... I used them with "with" without even thinking
> about it!  I've made the changes as requested. Admittedly it's quite
> hard for me to remove spaces from either side of operators because
> that's something I learnt from my early days in Turbo Pascal and to not
> have spaces (and all types and variables being lowercase) feels very
> C-like.  But hey, rules are rules... or guidelines!
>

I know the feeling. But when in Rome...

Is the new AS-IS-enum-08 patch any better?
>

Better (though are still some " = " around :P ), but it seems you missed
tasnode.pass_1?
Also the typenames (TOrdDef, TEnumDef) should be lowercase as well as the
local variables.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-09 Thread J. Gareth Moreton
Apologies - I see now... I used them with "with" without even thinking 
about it!  I've made the changes as requested. Admittedly it's quite 
hard for me to remove spaces from either side of operators because 
that's something I learnt from my early days in Turbo Pascal and to not 
have spaces (and all types and variables being lowercase) feels very 
C-like.  But hey, rules are rules... or guidelines!


Is the new AS-IS-enum-08 patch any better?

Gareth aka. Kit


On 09/07/2019 07:03, J. Gareth Moreton wrote:
I don't recall using "as" or "is" directly, but if I've done so, I 
humbly apologise and will fix that right away.


Gareth aka. Kit


On 09/07/2019 06:41, Sven Barth via fpc-devel wrote:

Am 08.07.2019 um 02:52 schrieb J. Gareth Moreton:
On an extra note, the assembly language produced is not yet optimal, 
so it may end up that an x86-specific implementation will be 
beneficial.  TIsNode contains a virtual method named 
"DoVariableEnumCheck" that would allow such an extension, coupled 
with returning "nil" that would defer code generation to 
"pass_generate_code" (allowing this, but not overriding 
"pass_generate_code", will trigger an internal error, because the 
'is' node normally never allows it to be called).  Nevertheless, 
even if that is a no-go, it's making me a little excited to see if I 
can find new peephole optimisations to implement.  But until my old 
x86_64 overhaul is accepted, rejected or reworked (at least to make 
it successfully merge), I can't really make any new additions yet.
Some non-technical remarks regarding code formatting (I know the 
compiler does currently not use a consistent style, but there is one 
that is considered the de facto one (I should find the time to write 
that down in the Wiki some time -.-) and new code should be added 
following this):
- no spaces between operators and symbols, both in assignments and 
expressions as well as parameter declarations
- local variables are written in lower case with the declarations as 
"name1,name2,name3 : type"

- types are written in lower case
- method names are lower case with '_' as separator between words (so 
your DoVariableEnumCheck would become do_variable_enum_check)


And one very important technical remark:
*No* "as" (or "is") inside the compiler. Use hard casts as you 
already checked for the def type


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-09 Thread J. Gareth Moreton
I don't recall using "as" or "is" directly, but if I've done so, I 
humbly apologise and will fix that right away.


Gareth aka. Kit


On 09/07/2019 06:41, Sven Barth via fpc-devel wrote:

Am 08.07.2019 um 02:52 schrieb J. Gareth Moreton:
On an extra note, the assembly language produced is not yet optimal, 
so it may end up that an x86-specific implementation will be 
beneficial.  TIsNode contains a virtual method named 
"DoVariableEnumCheck" that would allow such an extension, coupled 
with returning "nil" that would defer code generation to 
"pass_generate_code" (allowing this, but not overriding 
"pass_generate_code", will trigger an internal error, because the 
'is' node normally never allows it to be called).  Nevertheless, even 
if that is a no-go, it's making me a little excited to see if I can 
find new peephole optimisations to implement.  But until my old 
x86_64 overhaul is accepted, rejected or reworked (at least to make 
it successfully merge), I can't really make any new additions yet.
Some non-technical remarks regarding code formatting (I know the 
compiler does currently not use a consistent style, but there is one 
that is considered the de facto one (I should find the time to write 
that down in the Wiki some time -.-) and new code should be added 
following this):
- no spaces between operators and symbols, both in assignments and 
expressions as well as parameter declarations
- local variables are written in lower case with the declarations as 
"name1,name2,name3 : type"

- types are written in lower case
- method names are lower case with '_' as separator between words (so 
your DoVariableEnumCheck would become do_variable_enum_check)


And one very important technical remark:
*No* "as" (or "is") inside the compiler. Use hard casts as you already 
checked for the def type


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Sven Barth via fpc-devel
Sven Barth  schrieb am Di., 9. Juli 2019,
07:41:

> Am 08.07.2019 um 02:52 schrieb J. Gareth Moreton:
> > On an extra note, the assembly language produced is not yet optimal,
> > so it may end up that an x86-specific implementation will be
> > beneficial.  TIsNode contains a virtual method named
> > "DoVariableEnumCheck" that would allow such an extension, coupled with
> > returning "nil" that would defer code generation to
> > "pass_generate_code" (allowing this, but not overriding
> > "pass_generate_code", will trigger an internal error, because the 'is'
> > node normally never allows it to be called).  Nevertheless, even if
> > that is a no-go, it's making me a little excited to see if I can find
> > new peephole optimisations to implement.  But until my old x86_64
> > overhaul is accepted, rejected or reworked (at least to make it
> > successfully merge), I can't really make any new additions yet.
> Some non-technical remarks regarding code formatting (I know the
> compiler does currently not use a consistent style, but there is one
> that is considered the de facto one (I should find the time to write
> that down in the Wiki some time -.-) and new code should be added
> following this):
> - no spaces between operators and symbols, both in assignments and
> expressions as well as parameter declarations
> - local variables are written in lower case with the declarations as
> "name1,name2,name3 : type"
> - types are written in lower case
> - method names are lower case with '_' as separator between words (so
> your DoVariableEnumCheck would become do_variable_enum_check)
>
> And one very important technical remark:
> *No* "as" (or "is") inside the compiler. Use hard casts as you already
> checked for the def type
>

And I'm rather conflicted regarding the usage of "with". But Florian and/or
Jonas should comment whether we want new ones in the compiler or not.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Sven Barth via fpc-devel

Am 08.07.2019 um 02:52 schrieb J. Gareth Moreton:
On an extra note, the assembly language produced is not yet optimal, 
so it may end up that an x86-specific implementation will be 
beneficial.  TIsNode contains a virtual method named 
"DoVariableEnumCheck" that would allow such an extension, coupled with 
returning "nil" that would defer code generation to 
"pass_generate_code" (allowing this, but not overriding 
"pass_generate_code", will trigger an internal error, because the 'is' 
node normally never allows it to be called).  Nevertheless, even if 
that is a no-go, it's making me a little excited to see if I can find 
new peephole optimisations to implement.  But until my old x86_64 
overhaul is accepted, rejected or reworked (at least to make it 
successfully merge), I can't really make any new additions yet.
Some non-technical remarks regarding code formatting (I know the 
compiler does currently not use a consistent style, but there is one 
that is considered the de facto one (I should find the time to write 
that down in the Wiki some time -.-) and new code should be added 
following this):
- no spaces between operators and symbols, both in assignments and 
expressions as well as parameter declarations
- local variables are written in lower case with the declarations as 
"name1,name2,name3 : type"

- types are written in lower case
- method names are lower case with '_' as separator between words (so 
your DoVariableEnumCheck would become do_variable_enum_check)


And one very important technical remark:
*No* "as" (or "is") inside the compiler. Use hard casts as you already 
checked for the def type


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread J. Gareth Moreton
I need to know exactly what's been decided upon.  No arguments, no 
debates, no objections.  What has been accepted as "this is what will be 
implemented after all parties have been heard"? Because I can't put 
myself into a meltdown while my neck is being wrung for not doing what 
people wanted.


Gareth aka. Kit


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread J. Gareth Moreton
Apologies.  I've been getting lost and confused in all the details and 
am not even sure what people want any more.  What is the consensus from 
the administrators?


Gareth aka. Kit


On 08/07/2019 21:00, Ondrej Pokorny wrote:

On 08.07.2019 17:19, J. Gareth Moreton wrote:

I disabled it after Pierre pointed out
that you couldn't use Pred or Succ with
them, so wanted to be consistent,
especially as programming them to return
the expected value of False of a value
falls within a hole is not simple. Still,
it's easy enough to re-enable.

Gareth aka. Kit


There has been a much bigger discussion about it than the one post 
from Pierre.


Ondrej


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Ondrej Pokorny

On 08.07.2019 17:19, J. Gareth Moreton wrote:

I disabled it after Pierre pointed out
that you couldn't use Pred or Succ with
them, so wanted to be consistent,
especially as programming them to return
the expected value of False of a value
falls within a hole is not simple. Still,
it's easy enough to re-enable.

Gareth aka. Kit


There has been a much bigger discussion about it than the one post from 
Pierre.


Ondrej


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread J. Gareth Moreton
I disabled it after Pierre pointed out 
that you couldn't use Pred or Succ with 
them, so wanted to be consistent, 
especially as programming them to return 
the expected value of False of a value 
falls within a hole is not simple. Still, 
it's easy enough to re-enable.

Gareth aka. Kit

On Mon 08/07/19 12:51 , Ondrej Pokorny 
laza...@kluug.net sent:
> On 08.07.2019 02:37, J. Gareth Moreton 
wrote:
> 
> Uploaded the latest patch (AS-IS-enum-
07.patch) over here [1] and also a
> test project that evaluates the "is" 
operator between different ordinal
> types.  
> 
> I though I convinced you not to disable 
the feature on enums with holes
> even in OBJFPC mode... 
> 
> Ondrej
> 
> 
__
_
> fpc-devel maillist - fpc-
de...@lists.freepascal.org
> https://lists.freepascal.org/cgi-
bin/mailman/listinfo/fpc-devel [2]
> 
> 
> 
> Links:
> --
> [1] 
https://bugs.freepascal.org/view.php?
id=33603
> [2]
> http://secureweb.fast.net.uk/parse.php?
redirect=https://lists.freepascal.or
> g/cgi-bin/mailman/listinfo/fpc-devel
> 

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Ondrej Pokorny

On 08.07.2019 02:37, J. Gareth Moreton wrote:


Uploaded the latest patch (AS-IS-enum-07.patch) over here 
 and also a test 
project that evaluates the "is" operator between different ordinal types.


I though I convinced you not to disable the feature on enums with holes 
even in OBJFPC mode...


Ondrej


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Ondrej Pokorny

On 08.07.2019 12:39, Giuliano Colla wrote:

Il 07/07/2019 07:33, J. Gareth Moreton ha scritto:

In the meantime, I'm working on making
"as" and "is" work with ordinal types as
well as enumerations, although currently
some headaches occur if the right-hand
side is larger than the CPU word size
(e.g. Int64 on i386). I'll upload the
patch to the issue once it's working
properly.


Sorry for jumping in without having followed the full discussion, but 
I wonder if "as" and "is" are the best constructs to implement range 
checking. Wouldn't "in" be much more appropriate?


Sort of:

if value in enumvar then DoThat else IgnoreIt;


The IN operator
1.) expects a value on the right side, not a type.
2.) can be overloaded: 
https://www.freepascal.org/docs-html/ref/refse104.html#x213-23500015.6 . 
IS/AS cannot.


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-08 Thread Giuliano Colla

Il 07/07/2019 07:33, J. Gareth Moreton ha scritto:

In the meantime, I'm working on making
"as" and "is" work with ordinal types as
well as enumerations, although currently
some headaches occur if the right-hand
side is larger than the CPU word size
(e.g. Int64 on i386). I'll upload the
patch to the issue once it's working
properly.


Sorry for jumping in without having followed the full discussion, but I 
wonder if "as" and "is" are the best constructs to implement range 
checking. Wouldn't "in" be much more appropriate?


Sort of:

if value in enumvar then DoThat else IgnoreIt;

Giuliano

--
Do not do to others as you would have them do to you.They might have different 
tastes.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread J. Gareth Moreton
On an extra note, the assembly language produced is not yet optimal, so 
it may end up that an x86-specific implementation will be beneficial.  
TIsNode contains a virtual method named "DoVariableEnumCheck" that would 
allow such an extension, coupled with returning "nil" that would defer 
code generation to "pass_generate_code" (allowing this, but not 
overriding "pass_generate_code", will trigger an internal error, because 
the 'is' node normally never allows it to be called).  Nevertheless, 
even if that is a no-go, it's making me a little excited to see if I can 
find new peephole optimisations to implement.  But until my old x86_64 
overhaul is accepted, rejected or reworked (at least to make it 
successfully merge), I can't really make any new additions yet.


Gareth aka. Kit

P.S. One optimisation I would like to suggest across all platforms, if 
at all possible, is to defer register allocations until after the first 
peephole optimisation stage, because I see sequences like this on i386 
when working with Int64's (this particular sequence sign-extends from 
LongInt to Int64):


mov %reg1,%reg2
sar $31,%reg2

This fills %reg2 with all 0s or all 1s depending on if the sign bit is 
set in %reg1.  However, if the registers are still virtual, it may be 
possible to evaluate nearby code and request a preference for %eax for 
%reg1 and %edx for %reg2 (certain operations like "mul", "div" or 
function parameters require the use of %eax and %edx specifically) - 
that way, the sequence can be collapsed into a single call (and a single 
byte in size) to "cdq".



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread J. Gareth Moreton
Uploaded the latest patch (AS-IS-enum-07.patch) over here 
 and also a test project 
that evaluates the "is" operator between different ordinal types.


Following the advice of Jonas and Florian, I've removed my x86-specific 
code for now.


Gareth aka. Kit



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread J. Gareth Moreton
Oh right!  In that case, I can upload the code now... well, after I 
finish testing everything!  (I'll keep my platform-specific code in a 
personal branch though in case it doesn't work).


I have seen once source of inefficiency in the compiled assembly 
language and that's something akin to this (the code is to assign the 
result of a condition to a Boolean variable - for example, "Result := 
Value is TEnum;")


  cmpl   $##, %reg
  jnbe   @Lbl
  xorb   %al, %al
  jmp    @Done
@lbl:
  movb   $1, %al
@Done:

(Presumably the xorb %al,%al line was originally movb $0,%al before the 
post-peephole stage converted it) It might be this way because there was 
something else in between that was optimised out, but this could be 
optimised to:


  CMP    $##, %reg
  SETNBE %al

Note that there is one shortcoming that I've discovered while writing a 
test, and that you can't yet use as/is in a generic function - that is, 
if you have something akin to this:


generic function(Value: T1): Boolean;
begin
  Result := T1 is T2;
end;

It will fail, saying that a class type is expected where T2 is 
specified. I'll open a separate issue for this once the first patches 
are accepted and cleaned up.


Gareth aka. Kit

On 07/07/2019 20:07, Jonas Maebe wrote:

On 07/07/2019 07:33, J. Gareth Moreton wrote:

Maybe I'm missing something painfully
obvious here. Can I request an example
where such an invalid value/undefined
behaviour crops up in bitpacked records so
I can see what's going on? Logic dictates
that the number of bits required to store
an enum in that arrangement is equal to
the index of the highest element,

That is correct, but the discussion revolves about storing elements that
are larger than that the highest or smaller than the lowest element. In
that case, bits gets lost when storing them in bitpacked versions.


On 07/07/2019 19:36, J. Gareth Moreton wrote:

Additionally, I'm putting in an implementation specific to x86 because I
can take advantage of its ALU design to do the range check in as few as
2 instructions (a comparison and either a conditional jump or a SETcc
instruction).  If the range exceeds the CPU size though, then it falls
back to the node-level, platform-agnostic method.

That is not necessary. The compiler can do that trick itself (in a
CPU-independent way). Before yesterday, it could only do it with
unsigned ranges, but since yesterday it can also do it for signed ranges.

It can't yet inline the fpc_is/as_enum because it calls an
implementation-only procedure of the system unit, but I'm working on
solving that as well.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread Jonas Maebe
On 07/07/2019 07:33, J. Gareth Moreton wrote:
> Maybe I'm missing something painfully 
> obvious here. Can I request an example 
> where such an invalid value/undefined 
> behaviour crops up in bitpacked records so 
> I can see what's going on? Logic dictates 
> that the number of bits required to store 
> an enum in that arrangement is equal to 
> the index of the highest element,

That is correct, but the discussion revolves about storing elements that
are larger than that the highest or smaller than the lowest element. In
that case, bits gets lost when storing them in bitpacked versions.


On 07/07/2019 19:36, J. Gareth Moreton wrote:
> Additionally, I'm putting in an implementation specific to x86 because I
> can take advantage of its ALU design to do the range check in as few as
> 2 instructions (a comparison and either a conditional jump or a SETcc
> instruction).  If the range exceeds the CPU size though, then it falls
> back to the node-level, platform-agnostic method.

That is not necessary. The compiler can do that trick itself (in a
CPU-independent way). Before yesterday, it could only do it with
unsigned ranges, but since yesterday it can also do it for signed ranges.

It can't yet inline the fpc_is/as_enum because it calls an
implementation-only procedure of the system unit, but I'm working on
solving that as well.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread J. Gareth Moreton
Most of it is node-level.  Ondrej's method was to use an inlined 
compilerproc to do the range check, but the parameters are of type 
SizeInt, which causes problems if the range to check against is of size 
Int64 or, worse, QWord.  It may be that after some refactoring, the 
nodes for such an inlined procedure can be inserted directly rather than 
just inserting a procedure call.


Additionally, I'm putting in an implementation specific to x86 because I 
can take advantage of its ALU design to do the range check in as few as 
2 instructions (a comparison and either a conditional jump or a SETcc 
instruction).  If the range exceeds the CPU size though, then it falls 
back to the node-level, platform-agnostic method.


It's probably better to simply show the code for scrutiny once I get it 
ready, rather than try to explain myself.  Nevertheless, there may be 
some peephole optimisations that are to be added, but I haven't worked 
on that in a while due to my overhaul that needs updating so it at least 
merges with the latest trunk and doesn't undo a load of more recent changes.


Gareth aka. Kit

On 07/07/2019 09:24, Florian Klämpfl wrote:

Am 07.07.2019 um 07:33 schrieb J. Gareth Moreton:

Maybe I'm missing something painfully
obvious here. Can I request an example
where such an invalid value/undefined
behaviour crops up in bitpacked records so
I can see what's going on? Logic dictates
that the number of bits required to store
an enum in that arrangement is equal to
the index of the highest element, although
that's without looking at the source code
and doesn't account for elements that have
assigned negative values.

In the meantime, I'm working on making
"as" and "is" work with ordinal types as
well as enumerations, although currently
some headaches occur if the right-hand
side is larger than the CPU word size
(e.g. Int64 on i386). I'll upload the
patch to the issue once it's working
properly.

I strongly recommend to add these changes at node level, then you do not have 
to fiddle with the alu sizes of different
CPUs.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread Florian Klämpfl
Am 07.07.2019 um 07:33 schrieb J. Gareth Moreton:
> Maybe I'm missing something painfully 
> obvious here. Can I request an example 
> where such an invalid value/undefined 
> behaviour crops up in bitpacked records so 
> I can see what's going on? Logic dictates 
> that the number of bits required to store 
> an enum in that arrangement is equal to 
> the index of the highest element, although 
> that's without looking at the source code 
> and doesn't account for elements that have 
> assigned negative values.
> 
> In the meantime, I'm working on making 
> "as" and "is" work with ordinal types as 
> well as enumerations, although currently 
> some headaches occur if the right-hand 
> side is larger than the CPU word size 
> (e.g. Int64 on i386). I'll upload the 
> patch to the issue once it's working 
> properly.

I strongly recommend to add these changes at node level, then you do not have 
to fiddle with the alu sizes of different
CPUs.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-07 Thread J. Gareth Moreton
Maybe I'm missing something painfully 
obvious here. Can I request an example 
where such an invalid value/undefined 
behaviour crops up in bitpacked records so 
I can see what's going on? Logic dictates 
that the number of bits required to store 
an enum in that arrangement is equal to 
the index of the highest element, although 
that's without looking at the source code 
and doesn't account for elements that have 
assigned negative values.

In the meantime, I'm working on making 
"as" and "is" work with ordinal types as 
well as enumerations, although currently 
some headaches occur if the right-hand 
side is larger than the CPU word size 
(e.g. Int64 on i386). I'll upload the 
patch to the issue once it's working 
properly.

Gareth aka. Kit

On Sat 06/07/19 14:19 , "Jonas Maebe" 
jo...@freepascal.org sent:
> On 06/07/2019 14:56, Martok wrote:
> 
> > Am 06.07.2019 um 09:01 schrieb Ondrej 
Pokorny:
> 
> >> Ord(aEnum) for invalid enumeration 
values is
> undefined ;)
> > 
> 
> > If there was any logic here, it should 
be, but
> it's not ;-)
> > 
> 
> > The documentation page specifically 
mentions Ord
> as the older syntax to hard
> > casts. Whatever it contains, any enum 
is always
> smaller or equal to the largest
> > possible bitsize, which is Longint.
> 
> 
> 
> It is in fact undefined. The undefined 
behaviour comes from the fact
> 
> that an invalid value was stored in the 
variable and then read again,
> 
> not from how the read value is used. An 
example of where you may get
> 
> different data than wat you put in, even 
in the absence of any
> 
> optimisations, is again bitpacked 
records/arrays.
> 
> 
> 
> 
> 
> Jonas
> 
> 
__
_
> 
> fpc-devel maillist  -  fpc-
de...@lists.freepascal.org
> https://lists.freepascal.org/cgi-
bin/mailman/listinfo/fpc-devel
> 
> 
> 
> 
> 

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Jonas Maebe
On 06/07/2019 14:56, Martok wrote:
> Am 06.07.2019 um 09:01 schrieb Ondrej Pokorny:
>> Ord(aEnum) for invalid enumeration values is undefined ;)
> 
> If there was any logic here, it should be, but it's not ;-)
> 
> The documentation page specifically mentions Ord as the older syntax to hard
> casts. Whatever it contains, any enum is always smaller or equal to the 
> largest
> possible bitsize, which is Longint.

It is in fact undefined. The undefined behaviour comes from the fact
that an invalid value was stored in the variable and then read again,
not from how the read value is used. An example of where you may get
different data than wat you put in, even in the absence of any
optimisations, is again bitpacked records/arrays.


Jonas
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Martok
Am 06.07.2019 um 09:01 schrieb Ondrej Pokorny:
> Ord(aEnum) for invalid enumeration values is undefined ;)

If there was any logic here, it should be, but it's not ;-)

The documentation page specifically mentions Ord as the older syntax to hard
casts. Whatever it contains, any enum is always smaller or equal to the largest
possible bitsize, which is Longint.


Alternatively, which should be completely equivalent but is not because Ord is
Delphi-compatible and subranges are not:

generic function TStreamHelper.ReadEnum(out aEnum: T): Boolean;
var
  tmp: Ord(Low(T))..Ord(High(T)) absolute aEnum;
begin
   if Read(aEnum, SizeOf(aEnum)) <> SizeOf(aEnum) then
 Exit(False)
   else begin
 Result := (tmp >= Ord(Low(T))) and (tmp <= Ord(High(T)));
   end;
end;

This *could* be optimized out by FPC, but not by a Borland compiler.


-- 
Regards,
Martok

Ceterum censeo b32079 esse sanandam.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Michael Van Canneyt



On Sat, 6 Jul 2019, Ondrej Pokorny wrote:


On 05.07.2019 22:44, J. Gareth Moreton wrote:


In the meantime, I've extended your AS/IS patch over here 
 to create efficient code 
for x86 platforms, although currently it only does a range check and won't 
correctly handle enumerations with holes.  If non-contiguous enumerations 
are going to be allowed, we'll need to design an algorithm that can cover 
these holes with the smallest number of Boolean conditions.


IMO handling holes in enumerations is just a pure waste of time and energy. 
Delphi documents them as valid and the FPC compiler handles them as valid as 
well. IMO it is just an unnecessary extra added limitation to disable IS/AS 
on them. Furthermore they are used mainly for very specific needs, so are 
very marginal. The effort to make this work just doesn't pay off.


After considering what Ondrej pointed out about the behaviour of FPC and
delphi, I agree that checking lower and upper bounds should be sufficient.

Michael.___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Ondrej Pokorny

On 05.07.2019 22:44, J. Gareth Moreton wrote:


In the meantime, I've extended your AS/IS patch over here 
 to create efficient 
code for x86 platforms, although currently it only does a range check 
and won't correctly handle enumerations with holes.  If non-contiguous 
enumerations are going to be allowed, we'll need to design an 
algorithm that can cover these holes with the smallest number of 
Boolean conditions.


IMO handling holes in enumerations is just a pure waste of time and 
energy. Delphi documents them as valid and the FPC compiler handles them 
as valid as well. IMO it is just an unnecessary extra added limitation 
to disable IS/AS on them. Furthermore they are used mainly for very 
specific needs, so are very marginal. The effort to make this work just 
doesn't pay off.


Btw. you get a "project1.lpr(7,10) Warning: Case statement does not 
handle all possible cases" in the program below anyway:


program Project1;
type
  THoleEnum = (two=2, four=4);
var
  E: THoleEnum;
begin
  case E of
    two: ;
    four: ;
  end;
end.

What will you do now, disable case-of for enumerations with holes 
because the compiler cannot handle the holes correctly in the strict FPC 
POV way?


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Ondrej Pokorny

On 06.07.2019 02:10, Martok wrote:

In that case, unlike what was previously said in this thread, this should simply
work:

generic function TStreamHelper.ReadEnum(out aEnum: T): Boolean;
begin
   if Read(aEnum, SizeOf(aEnum)) <> SizeOf(aEnum) then
 Exit(False)
   else begin
 Result := (Ord(aEnum) >= Ord(Low(T))) and (Ord(aEnum) <= Ord(High(T)));
   end;
end;


Ord(aEnum) for invalid enumeration values is undefined ;)

Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-06 Thread Tony via fpc-devel
On Fri, 5 Jul 2019 00:40:15 +0100
"J. Gareth Moreton"  wrote:

> You could consider this an ultimatum, but I know it will be pointless
> to do that because you'll just ignore me.  So I'm pleading, Jonas...
> there needs to be a way to check if an enumeration contains an
> invalid value to avoid diving into the realm of undefined behaviour.
> Just because you wouldn't use it doesn't mean we won't.

I am only a hobbyist, so take this for what it's worth.  I am very
puzzled by Gareth's insistence on this issue.  It seems to me that, if
there is a chance that a value read from some external source might
have a value outside the range of an enum, then enum is not the right
data type for that operation.  Use an appropriate integer type
instead.

Tony



___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
Am 06.07.2019 um 01:21 schrieb J. Gareth Moreton:
> According to this , 
> a
> Longint.
Ah, right.
I checked the source again: that is true only if the argument is an enum. If it
is any other ordinal type or Pointer, the result is of the same word size (but
possibly different signedness) as the source.

In that case, unlike what was previously said in this thread, this should simply
work:

generic function TStreamHelper.ReadEnum(out aEnum: T): Boolean;
begin
  if Read(aEnum, SizeOf(aEnum)) <> SizeOf(aEnum) then
Exit(False)
  else begin
Result := (Ord(aEnum) >= Ord(Low(T))) and (Ord(aEnum) <= Ord(High(T)));
  end;
end;

So this is a comparison of Longints (add a cast to Longword to fix the overflow
bug), nothing that should be optimized out. This should also work for subranges
in their host types. Unless the optimizer removes the typeconvnodes...


Of course, this needs to be done everywhere a subrange is passed anywhere that
is not FPC, so it can't really fix anything.


-- 
Regards,
Martok


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton


On 05/07/2019 23:50, Sven Barth via fpc-devel wrote:

Am 05.07.2019 um 22:34 schrieb J. Gareth Moreton:


It feels like a very convoluted way to implement a safe means of 
reading an enumeration from a file, but given that that reading 
incorrect data files is one of the main causes of enums taking on 
invalid values, I have to say that this is the best solution should 
we not be allowed the "is" operator or an intrinsic.  If that is the 
case, then I propose this gets added to TStream!


At least it hides the gruesome details, cause you only need to call 
ReadEnum<> (or ReadRange<>)... And maybe the code the compiler 
generates can even be optimized further. :)


Regards,
Sven


On x86, when it's a standard enum with a 0 lower bound (most enums are 
like this) the check can be made as simple as this:


CMP Value, HighValue{ HighValue is calculated at compile-time, while 
Value is the memory or register that the enum is stored in }

JBE @InRange

I'm not sure how well the compiler can generate that from "If (Value >= 
Ord(Low(TEnum))) and (Value <= Ord(High(TEnum))) then" because it abuses 
the signed/unsigned convention to check both sides of the domain (i.e. 
if the value is negative, it is instead treated as a very large positive 
number that fails the conditions on the jump).


Gareth aka. Kit


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton
According to this 
, a Longint.


Gareth aka. Kit

On 06/07/2019 00:04, Martok wrote:

I think there is a shorter version, but what is the exact return type of Ord()
again?

By the way, what you're reinventing here is type marshalling, for one single
type class, and in a very roundabout way.
If that is really what the discussion settled on, it would probably make sense
to not tack this onto a particular stream implementation but instead provide a
general marshaller for it.




---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
I think there is a shorter version, but what is the exact return type of Ord()
again?

By the way, what you're reinventing here is type marshalling, for one single
type class, and in a very roundabout way.
If that is really what the discussion settled on, it would probably make sense
to not tack this onto a particular stream implementation but instead provide a
general marshaller for it.

-- 
Regards,
Martok


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Sven Barth via fpc-devel

Am 05.07.2019 um 22:34 schrieb J. Gareth Moreton:


It feels like a very convoluted way to implement a safe means of 
reading an enumeration from a file, but given that that reading 
incorrect data files is one of the main causes of enums taking on 
invalid values, I have to say that this is the best solution should we 
not be allowed the "is" operator or an intrinsic.  If that is the 
case, then I propose this gets added to TStream!


At least it hides the gruesome details, cause you only need to call 
ReadEnum<> (or ReadRange<>)... And maybe the code the compiler generates 
can even be optimized further. :)


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton
In the meantime, I've extended your AS/IS patch over here 
 to create efficient code 
for x86 platforms, although currently it only does a range check and 
won't correctly handle enumerations with holes.  If non-contiguous 
enumerations are going to be allowed, we'll need to design an algorithm 
that can cover these holes with the smallest number of Boolean conditions.


Gareth aka. Kit

On 05/07/2019 21:13, Ondrej Pokorny wrote:

On 05.07.2019 16:51, Pierre Muller wrote:
This means that using pred() or succ() intrinsics on enumerated types 
with

holes will generate a Compile Time Error.

   To be consistent, I would propose that we also generate
a Compile Time Error if 'is' or 'as' keyword is used on such a type,
unless there is a code that really check that the value is not in
one of the holes ...


I have to strongly disagree here. We need the IS/AS operators to 
prevent undefined behavior. And if undefined behavior is only outside 
the low/high bounds of the enumeration values and not within the holes 
- then the IS/AS that checks only the bounds is very consequent 
indeed. It's also consequent with the case-of statement for an enum 
with holes. (See the thread I linked before.)


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel





---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton
It feels like a very convoluted way to implement a safe means of reading 
an enumeration from a file, but given that that reading incorrect data 
files is one of the main causes of enums taking on invalid values, I 
have to say that this is the best solution should we not be allowed the 
"is" operator or an intrinsic.  If that is the case, then I propose this 
gets added to TStream!


Gareth aka. Kit

On 05/07/2019 21:27, Sven Barth via fpc-devel wrote:

Am 05.07.2019 um 22:25 schrieb Sven Barth:

Am 05.07.2019 um 08:08 schrieb Sven Barth:
Jonas Maebe mailto:jo...@freepascal.org>> 
schrieb am Do., 4. Juli 2019, 21:21:


On 03/07/2019 09:26, Ondrej Pokorny wrote:
> On 02.07.2019 23:34, Jonas Maebe wrote:
>> Invalid data means undefined behaviour, always. "is" is not a
special
>> case that is immune to this.
>
> Don't you really see the need to handle invalid data with a
/defined/
> behavior?

My point is that is impossible to do so, so trying to do it in a way
that works in some/most cases, is much more dangerous than
categorically
refusing to try to do it, as it creates a false sense of security.


Then how would you read data from e.g. a stream into an enum or 
subrange if the stream may contain invalid data?

I now did a proof of concept for that task myself:

=== code begin ===


[snip]

if not s.specialize ReadEnum(e) then
    raise EStreamError.Create('Failed to read enum value');
  Writeln('Read value: ', e);
  if not s.specialize ReadEnum(e) then
    raise EstreamError.CReate('Failed to read enum value');

[snip]


=== code end ===


Oh and once I've integrated Ryan's implicit specialization support the 
code can become this (or at least I hope so ^^'):


=== code begin ===
  if not s.ReadEnum(e) then
    raise EStreamError.Create('Failed to read enum value');
  Writeln('Read value: ', e);
  if not s.ReadEnum(e) then
    raise EstreamError.CReate('Failed to read enum value');

=== code end ===

Regards,
Sven

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Sven Barth via fpc-devel

Am 05.07.2019 um 22:25 schrieb Sven Barth:

Am 05.07.2019 um 08:08 schrieb Sven Barth:
Jonas Maebe mailto:jo...@freepascal.org>> 
schrieb am Do., 4. Juli 2019, 21:21:


On 03/07/2019 09:26, Ondrej Pokorny wrote:
> On 02.07.2019 23:34, Jonas Maebe wrote:
>> Invalid data means undefined behaviour, always. "is" is not a
special
>> case that is immune to this.
>
> Don't you really see the need to handle invalid data with a
/defined/
> behavior?

My point is that is impossible to do so, so trying to do it in a way
that works in some/most cases, is much more dangerous than
categorically
refusing to try to do it, as it creates a false sense of security.


Then how would you read data from e.g. a stream into an enum or 
subrange if the stream may contain invalid data?

I now did a proof of concept for that task myself:

=== code begin ===


[snip]

if not s.specialize ReadEnum(e) then
    raise EStreamError.Create('Failed to read enum value');
  Writeln('Read value: ', e);
  if not s.specialize ReadEnum(e) then
    raise EstreamError.CReate('Failed to read enum value');

[snip]


=== code end ===


Oh and once I've integrated Ryan's implicit specialization support the 
code can become this (or at least I hope so ^^'):


=== code begin ===
  if not s.ReadEnum(e) then
    raise EStreamError.Create('Failed to read enum value');
  Writeln('Read value: ', e);
  if not s.ReadEnum(e) then
    raise EstreamError.CReate('Failed to read enum value');

=== code end ===

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Sven Barth via fpc-devel

Am 05.07.2019 um 08:08 schrieb Sven Barth:
Jonas Maebe mailto:jo...@freepascal.org>> 
schrieb am Do., 4. Juli 2019, 21:21:


On 03/07/2019 09:26, Ondrej Pokorny wrote:
> On 02.07.2019 23:34, Jonas Maebe wrote:
>> Invalid data means undefined behaviour, always. "is" is not a
special
>> case that is immune to this.
>
> Don't you really see the need to handle invalid data with a
/defined/
> behavior?

My point is that is impossible to do so, so trying to do it in a way
that works in some/most cases, is much more dangerous than
categorically
refusing to try to do it, as it creates a false sense of security.


Then how would you read data from e.g. a stream into an enum or 
subrange if the stream may contain invalid data?

I now did a proof of concept for that task myself:

=== code begin ===

program tptrhlp;

{$mode objfpc}
{$modeswitch typehelpers}

uses
  Classes, SysUtils;

type
  TStreamHelper = type helper for TStream
  public
    generic function ReadEnum(out aEnum: T): Boolean;
  end;

generic function TStreamHelper.ReadEnum(out aEnum: T): Boolean;
var
  buf: array[0..SizeOf(T) - 1] of Byte absolute aEnum;
  tmp: LongInt;
begin
  if Read(buf[0], SizeOf(buf)) <> SizeOf(buf) then
    Exit(False)
  else begin
    case SizeOf(T) of
  1:
    tmp := PByte(@buf[0])^;
  2:
    tmp := PWord(@buf[0])^;
  3:
    tmp := LongWord(PWord(@buf[0])^) or (LongInt(PByte(@buf[2])^) 
shl 16);

  4:
    tmp := PLongWord(@buf[0])^;
    end;
    Result := (tmp >= Ord(Low(T))) and (tmp <= Ord(High(T)));
  end;
end;

type
  {$PACKENUM 1}
  TMyEnum = (
    meOne,
    meTwo,
    meThree
  );
var
  s: TMemoryStream;
  e: TMyEnum;
  b: Byte;
begin
  s := TMemoryStream.Create;
  try
    try
  Writeln(SizeOf(TMyEnum));
  b := 1;
  s.Write(b, SizeOf(b));
  b := 3;
  s.Write(b, SizeOf(b));
  s.Position := 0;
  if not s.specialize ReadEnum(e) then
    raise EStreamError.Create('Failed to read enum value');
  Writeln('Read value: ', e);
  if not s.specialize ReadEnum(e) then
    raise EstreamError.CReate('Failed to read enum value');
    except
  on e: Exception do
    Writeln(e.ClassName, ': ', e.Message);
    end;
  finally
    s.Free;
  end;
end.

=== code end ===

Note 1: Needs today's trunk cause I fixed generic methods in helpers in 
mode ObjFPC
Note 2: Similar code can also be done for ranges (though there the sizes 
5 to 8 need to be handled as well)

Note 3: I didn't test whether this works correctly on Big Endian systems
Note 4: The compiler will optimize away the unneeded case branches :)

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Ondrej Pokorny

On 05.07.2019 16:51, Pierre Muller wrote:

This means that using pred() or succ() intrinsics on enumerated types with
holes will generate a Compile Time Error.

   To be consistent, I would propose that we also generate
a Compile Time Error if 'is' or 'as' keyword is used on such a type,
unless there is a code that really check that the value is not in
one of the holes ...


I have to strongly disagree here. We need the IS/AS operators to prevent 
undefined behavior. And if undefined behavior is only outside the 
low/high bounds of the enumeration values and not within the holes - 
then the IS/AS that checks only the bounds is very consequent indeed. 
It's also consequent with the case-of statement for an enum with holes. 
(See the thread I linked before.)


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton

Hey there - sorry if I'm not explaining myself too well.

My question would be this... if Value is a variable of type TEnum that 
is invalid (either because it is out of range or contains a 'hole' 
value, but more specifically the former), should "Value is TEnum" return 
True, False or an exception?  If it's an exception, then "Value is 
TEnum" will only ever return True or raise an exception if Value is of 
type TEnum.  If it returns False instead, then it's a nice and efficient 
check to see if Value is valid or not, which is the main point of 
contention around this topic... how can we reliably detect an invalid 
value and not let the program slip into an undefined state?


For Prec and Succ to return an exception if the next value is a hole, 
that will certainly be easier to program, since then the code can be 
equivalent to this:




function Succ(EnumVal: TEnum): TEnum; inline;
begin
  Result := TEnum(Ord(EnumVal) + 1);
  if (m_delphi in current_settings.modeswitches) and
    not (Result is TEnum) then
      raise RunTimeError201;
end;



Of course the code would be generated directly and not have the check 
for Delphi mode (it'll just remove the condition and exception raise 
completely) but you get the idea.


Gareth aka. Kit


On 05/07/2019 18:28, Sven Barth via fpc-devel wrote:
Pierre Muller mailto:pie...@freepascal.org>> 
schrieb am Fr., 5. Juli 2019, 17:51:




Le 05/07/2019 à 17:42, J. Gareth Moreton a écrit :
>
> On 05/07/2019 15:51, Pierre Muller wrote:
>> Just one point from current compiler implementation:
>>
>> in trunk/fpcsrc/compiler/ninl.pas (around line 3180)
>>
>>                in_pred_x,
>>                in_succ_x:
>>                  begin
>>  set_varstate(left,vs_read,[vsf_must_be_valid]);
>>                     resultdef:=left.resultdef;
>>                     if is_ordinal(resultdef) or
is_typeparam(resultdef) then
>>                       begin
>>                         if (resultdef.typ=enumdef) and
>> (tenumdef(resultdef).has_jumps) and
>>                            not(m_delphi in
current_settings.modeswitches) and
>>                            not(nf_internal in flags) then
>>  CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
>>                       end
>>
>>
>> This means that using pred() or succ() intrinsics on enumerated
types with
>> holes will generate a Compile Time Error.
>>
>>    To be consistent, I would propose that we also generate
>> a Compile Time Error if 'is' or 'as' keyword is used on such a
type,
>> unless there is a code that really check that the value is not in
>> one of the holes ...
>>
>> Pierre
>
> That seems fair.  The main problem is what happens if, when
allowed,
> Prec or Succ are used on such a type on an element that is
adjacent to
> one of these holes.  Should it skip to the first element at the
other
> end of the hole or raise an exception? Granted, what happens if
you use
> Prec or Succ on the first or last element respectively?
>
> I can theoretically design an algorithm to cover these gaps with
Boolean
> conditions for the sake of "is", but it's a little bit complex.
>
> Sorry to bring you in on this particular point, Pierre, but if
you call
> "Value is TEnum" and Value is of type TEnum but contains an invalid
> value (due to being read from an external stream, for example),
should
> it return True or False?

  My answer would be:

in FPC modes, simply generate a CompileTimeError as above,

in Delphi mode, as Delphi states stat the holes are also valid
values of the range,
then indeed, pred() and succ() can do the simple thing they do
when there are no holes,
and 'is' or 'as' should then also do the same, i.e. only check
that the value is inside
the range defined by the lowest and highest values!

  But on course this means that in Delphi mode,
even after validating with 'is' you could still have a valid enum
value that has no
name, i.e. that is in one of those black holes ...

  I don't need to tell you that I do have a preference for the
ordinary Free Pascal way!


I think Gareth meant his question for enums without holes ;)

Regards,
Sven


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Sven Barth via fpc-devel
Pierre Muller  schrieb am Fr., 5. Juli 2019, 17:51:

>
>
> Le 05/07/2019 à 17:42, J. Gareth Moreton a écrit :
> >
> > On 05/07/2019 15:51, Pierre Muller wrote:
> >> Just one point from current compiler implementation:
> >>
> >> in trunk/fpcsrc/compiler/ninl.pas (around line 3180)
> >>
> >>in_pred_x,
> >>in_succ_x:
> >>  begin
> >> set_varstate(left,vs_read,[vsf_must_be_valid]);
> >> resultdef:=left.resultdef;
> >> if is_ordinal(resultdef) or is_typeparam(resultdef)
> then
> >>   begin
> >> if (resultdef.typ=enumdef) and
> >>(tenumdef(resultdef).has_jumps) and
> >>not(m_delphi in
> current_settings.modeswitches) and
> >>not(nf_internal in flags) then
> >>
>  CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
> >>   end
> >>
> >>
> >> This means that using pred() or succ() intrinsics on enumerated types
> with
> >> holes will generate a Compile Time Error.
> >>
> >>To be consistent, I would propose that we also generate
> >> a Compile Time Error if 'is' or 'as' keyword is used on such a type,
> >> unless there is a code that really check that the value is not in
> >> one of the holes ...
> >>
> >> Pierre
> >
> > That seems fair.  The main problem is what happens if, when allowed,
> > Prec or Succ are used on such a type on an element that is adjacent to
> > one of these holes.  Should it skip to the first element at the other
> > end of the hole or raise an exception? Granted, what happens if you use
> > Prec or Succ on the first or last element respectively?
> >
> > I can theoretically design an algorithm to cover these gaps with Boolean
> > conditions for the sake of "is", but it's a little bit complex.
> >
> > Sorry to bring you in on this particular point, Pierre, but if you call
> > "Value is TEnum" and Value is of type TEnum but contains an invalid
> > value (due to being read from an external stream, for example), should
> > it return True or False?
>
>   My answer would be:
>
> in FPC modes, simply generate a CompileTimeError as above,
>
> in Delphi mode, as Delphi states stat the holes are also valid values of
> the range,
> then indeed, pred() and succ() can do the simple thing they do when there
> are no holes,
> and 'is' or 'as' should then also do the same, i.e. only check that the
> value is inside
> the range defined by the lowest and highest values!
>
>   But on course this means that in Delphi mode,
> even after validating with 'is' you could still have a valid enum value
> that has no
> name, i.e. that is in one of those black holes ...
>
>   I don't need to tell you that I do have a preference for the ordinary
> Free Pascal way!
>

I think Gareth meant his question for enums without holes ;)

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Pierre Muller


Le 05/07/2019 à 17:42, J. Gareth Moreton a écrit :
> 
> On 05/07/2019 15:51, Pierre Muller wrote:
>> Just one point from current compiler implementation:
>>
>> in trunk/fpcsrc/compiler/ninl.pas (around line 3180)
>>
>>in_pred_x,
>>in_succ_x:
>>  begin
>> set_varstate(left,vs_read,[vsf_must_be_valid]);
>> resultdef:=left.resultdef;
>> if is_ordinal(resultdef) or is_typeparam(resultdef) then
>>   begin
>> if (resultdef.typ=enumdef) and
>>(tenumdef(resultdef).has_jumps) and
>>not(m_delphi in current_settings.modeswitches) and
>>not(nf_internal in flags) then
>>   
>> CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
>>   end
>>
>>
>> This means that using pred() or succ() intrinsics on enumerated types with
>> holes will generate a Compile Time Error.
>>
>>To be consistent, I would propose that we also generate
>> a Compile Time Error if 'is' or 'as' keyword is used on such a type,
>> unless there is a code that really check that the value is not in
>> one of the holes ...
>>
>> Pierre
> 
> That seems fair.  The main problem is what happens if, when allowed, 
> Prec or Succ are used on such a type on an element that is adjacent to 
> one of these holes.  Should it skip to the first element at the other 
> end of the hole or raise an exception? Granted, what happens if you use 
> Prec or Succ on the first or last element respectively?
> 
> I can theoretically design an algorithm to cover these gaps with Boolean 
> conditions for the sake of "is", but it's a little bit complex.
> 
> Sorry to bring you in on this particular point, Pierre, but if you call 
> "Value is TEnum" and Value is of type TEnum but contains an invalid 
> value (due to being read from an external stream, for example), should 
> it return True or False?

  My answer would be:

in FPC modes, simply generate a CompileTimeError as above,

in Delphi mode, as Delphi states stat the holes are also valid values of the 
range,
then indeed, pred() and succ() can do the simple thing they do when there are 
no holes,
and 'is' or 'as' should then also do the same, i.e. only check that the value 
is inside
the range defined by the lowest and highest values!

  But on course this means that in Delphi mode,
even after validating with 'is' you could still have a valid enum value that 
has no
name, i.e. that is in one of those black holes ...

  I don't need to tell you that I do have a preference for the ordinary Free 
Pascal way!

Pierre
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton


On 05/07/2019 15:51, Pierre Muller wrote:

Just one point from current compiler implementation:

in trunk/fpcsrc/compiler/ninl.pas (around line 3180)

   in_pred_x,
   in_succ_x:
 begin
set_varstate(left,vs_read,[vsf_must_be_valid]);
resultdef:=left.resultdef;
if is_ordinal(resultdef) or is_typeparam(resultdef) then
  begin
if (resultdef.typ=enumdef) and
   (tenumdef(resultdef).has_jumps) and
   not(m_delphi in current_settings.modeswitches) and
   not(nf_internal in flags) then
  
CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
  end


This means that using pred() or succ() intrinsics on enumerated types with
holes will generate a Compile Time Error.

   To be consistent, I would propose that we also generate
a Compile Time Error if 'is' or 'as' keyword is used on such a type,
unless there is a code that really check that the value is not in
one of the holes ...

Pierre


That seems fair.  The main problem is what happens if, when allowed, 
Prec or Succ are used on such a type on an element that is adjacent to 
one of these holes.  Should it skip to the first element at the other 
end of the hole or raise an exception? Granted, what happens if you use 
Prec or Succ on the first or last element respectively?


I can theoretically design an algorithm to cover these gaps with Boolean 
conditions for the sake of "is", but it's a little bit complex.


Sorry to bring you in on this particular point, Pierre, but if you call 
"Value is TEnum" and Value is of type TEnum but contains an invalid 
value (due to being read from an external stream, for example), should 
it return True or False?


Gareth aka. Kit


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Sven Barth via fpc-devel
Martok  schrieb am Fr., 5. Juli 2019, 14:54:

> Am 05.07.2019 um 14:24 schrieb Sven Barth via fpc-devel:
> > Huh? The comment regarding dynamic packages is nonsense. The compiler
> and RTL
> > check that the checksums of the involved interface sections match and
> thus there
> > is no problem there.
>
> Does that cascade? If so, that's better than Delphi, nice :)
>

As loading dynamic packages is an expensive operation anyway I do indeed
intend to check the checksum of all involved packages and units for
consistency. I've been bitten often enough in Delphi by this. I don't want
the same problems in FPC...

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Ondrej Pokorny

On 05.07.2019 16:51, Pierre Muller wrote:

Just one point from current compiler implementation:

in trunk/fpcsrc/compiler/ninl.pas (around line 3180)

   in_pred_x,
   in_succ_x:
 begin
set_varstate(left,vs_read,[vsf_must_be_valid]);
resultdef:=left.resultdef;
if is_ordinal(resultdef) or is_typeparam(resultdef) then
  begin
if (resultdef.typ=enumdef) and
   (tenumdef(resultdef).has_jumps) and
   not(m_delphi in current_settings.modeswitches) and
   not(nf_internal in flags) then
  
CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
  end


This means that using pred() or succ() intrinsics on enumerated types with
holes will generate a Compile Time Error.


Only for non-Delphi modes, see: not(m_delphi in 
current_settings.modeswitches)




   To be consistent, I would propose that we also generate
a Compile Time Error if 'is' or 'as' keyword is used on such a type,
unless there is a code that really check that the value is not in
one of the holes ...


See this thread: 
https://lists.freepascal.org/pipermail/fpc-devel/2019-May/040865.html


Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Pierre Muller
Just one point from current compiler implementation:

in trunk/fpcsrc/compiler/ninl.pas (around line 3180)

  in_pred_x,
  in_succ_x:
begin
   set_varstate(left,vs_read,[vsf_must_be_valid]);
   resultdef:=left.resultdef;
   if is_ordinal(resultdef) or is_typeparam(resultdef) then
 begin
   if (resultdef.typ=enumdef) and
  (tenumdef(resultdef).has_jumps) and
  not(m_delphi in current_settings.modeswitches) and
  not(nf_internal in flags) then
 
CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
 end


This means that using pred() or succ() intrinsics on enumerated types with
holes will generate a Compile Time Error.

  To be consistent, I would propose that we also generate
a Compile Time Error if 'is' or 'as' keyword is used on such a type,
unless there is a code that really check that the value is not in
one of the holes ...

Pierre

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Ondrej Pokorny

On 05.07.2019 14:58, Martok wrote:

Am 05.07.2019 um 12:20 schrieb Ondrej Pokorny:

Anything that even looks like a subrange cannot be used for these interfaces.

You may use enumerations for these interfaces - you may just not fill
them directly but through an integer variable in between when reading
from outside.

Then you're not using them *in* the interface ;-)


For records you could use such a workaround:

program Project1;
{$mode objfpc}
{$modeswitch advancedrecords}
type
  TMyEnum = (one, two, three);
  TMyRecord = record
  public
    function IsValid: Boolean;
  public
    case Boolean of
  False: ( // real values
    Enum: TMyEnum;
  );
  True: ( // used for interface
    EnumIntf: Integer;
    {$IF SizeOf(Integer)<>SizeOf(TMyEnum)}
  {$ERROR Size mismatch}
    {$ENDIF}
  );
  end;
{ TMyRecord }
function TMyRecord.IsValid: Boolean;
begin
  Result := EnumIntf is TMyEnum;
end;

var
  R: TMyRecord;
begin
  // fill R with data ...
  Randomize;
  FillChar(R, SizeOf(R), Random(High(Byte)));
  // check validity
  if R.IsValid then
    Writeln('R is valid')
  else
    Writeln('R is not valid');
  Writeln(R.EnumIntf);
  ReadLn;
end.

Best
Ondrej

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Ondrej Pokorny

On 05.07.2019 14:58, Martok wrote:

Am 05.07.2019 um 12:20 schrieb Ondrej Pokorny:

Anything that even looks like a subrange cannot be used for these interfaces.

You may use enumerations for these interfaces - you may just not fill
them directly but through an integer variable in between when reading
from outside.

Then you're not using them *in* the interface ;-)

Agreed. Ondrej
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread J. Gareth Moreton

On 05/07/2019 13:29, Sven Barth via fpc-devel wrote:
J. Gareth Moreton > schrieb am Fr., 5. Juli 2019, 14:02:


I'm glad we agree on the "is" operator.  Personally I would like to
extend it so it accepts "if (I is TMyEnum) then" when I is also of
type
TMyEnum, since it may be the case that you're reading I directly
from a
stream, either individually or as part of a record, in which case
converting I from an Integer to TMyEnum is a little inconvenient. 
When
you get down to the compiled assembly language it shouldn't really
matter anyway.


It might not matter from the assembly point of view, but it matters 
from the language point of view. When we say that enum values only 
contain valid values then "myenum is TMyEnum" *must* always evaluate 
to true, because otherwise there's an exception of the rule that enums 
only contain valid values.


Regards,
Sven

In this situation, the exception is kind of needed, and was suggested 
for this purpose in the first place.  If you read an enum from a stream 
or any kind of external source, then there is a chance it will take on 
an invalid value and needs to be trapped. I don't think anyone wants to 
be forced to ditch enumerations for integers and C-style constants so as 
to not fall foul of this quirk.  "is" is to catch an enumeration taking 
on an invalid value, thus allowing customised error handling to be 
executed, so other expressions can be optimised on the assumption that 
the enum is definitely valid by that point.


Gareth aka. Kit



---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
> But I will not argue the point, it is largely a matter of personal 
> interpretation
> of the intended use of an enumerated.

Well, yes. Since any argument from authority is discarded, what remains is
personal interpretation.


> But I will definitely adapt the FPC documentation to be more clear about the 
> actual
> behaviour of the compiler.
And this is why we can't have nice things.

Please don't get me wrong (really!), this is nothing against your work
specifically, but that the documentation has to follow the implementation and
the implementation follows no particular philosophy at all is what got this
interpretation of the language into this mess in the first place.


FPC is in dire need of a language specification effort. But I don't think anyone
who would be willing to drive it cares enough at that point.


-- 
Regards,
Martok


___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
Am 05.07.2019 um 11:28 schrieb Michael Van Canneyt:
> But IMO such a strict stance is untenable: you cannot ensure correct values 
> in all cases even within the confines of the language (as demonstrated 
> before).

Correct. Even if certain (exactly two) people here believe differently.


> So, in my book, an intrinsic to check for a correct value in the places where 
> an 
> invalid value can enter the system is a welcome language feature.

In my book it's absolutely insane that this is needed *just because* FPC wants
to be different, but yes, it is required.


-- 
Regards,
Martok

Ceterum censeo b32079 esse sanandam.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
Am 05.07.2019 um 12:20 schrieb Ondrej Pokorny:
>> Anything that even looks like a subrange cannot be used for these interfaces.
> 
> You may use enumerations for these interfaces - you may just not fill 
> them directly but through an integer variable in between when reading 
> from outside.

Then you're not using them *in* the interface ;-)

-- 
Regards,
Martok

Ceterum censeo b32079 esse sanandam.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] [Suggestion] Enumeration range-check intrinsic

2019-07-05 Thread Martok
Am 05.07.2019 um 14:24 schrieb Sven Barth via fpc-devel:
> Huh? The comment regarding dynamic packages is nonsense. The compiler and RTL
> check that the checksums of the involved interface sections match and thus 
> there
> is no problem there. 

Does that cascade? If so, that's better than Delphi, nice :)


-- 
Regards,
Martok

Ceterum censeo b32079 esse sanandam.

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


  1   2   >