Sign in Join

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

Mailing lists / fpc-devel / 2008-03

Bug in trunk?

24 messages · 7 people ·

Reply by email Subscribe to this list Your subscription

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

Martin Schreiber
Hi,
What is wrong with this code:
"
program rangeerror;
{$ifdef FPC}{$mode objfpc}{$h+}{$endif}
{$ifdef mswindows}{$apptype console}{$endif}
uses
 {$ifdef FPC}{$ifdef linux}cthreads,{$endif}{$endif}
 sysutils;
type
 colorty = type longword;
const
 cl_mapped = colorty($90000000);
type
 ttestclass = class
  private
   fcolor: colorty;
  published
   property color: colorty read fcolor write fcolor default cl_mapped; //<<--
 end;
begin
end.
"
"
Free Pascal Compiler version 2.3.1 [2008/03/27] for i386
Copyright (c) 1993-2007 by Florian Klaempfl
Target OS: Linux for i386
Compiling rangeerror.pas
rangeerror.pas(16,70) Error: range check error while evaluating constants
rangeerror.pas(21) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
"
Delphi7 and FPC fixes_2_2 compile fine.

Martin

Reply by email

Graeme Geldenhuys
to Martin Schreiber
Martin Schreiber wrote
Hi, What is wrong with this code:

Michael Van Canneyt detected a similar issue with fpGUI code and FPC 2.3.1

- It doesn't compile with my 2.3.1 compiler. (64 bit)

Free Pascal Compiler version 2.3.1 [2007/07/04] for x86_64
Copyright (c) 1993-2007 by Florian Klaempfl
gfx_widget.pas(126,117) Error: range check error while evaluating constants
gfx_widget.pas(127,88) Error: range check error while evaluating constants
gfx_widget.pas(137,1) Fatal: There were 2 errors compiling module, stopping

The lines referred to are:

 property BackgroundColor: TfpgColor read FBackgroundColor write
SetBackgroundColor default clWindowBackground;
 property TextColor: TfpgColor read FTextColor write SetTextColor
default clText1;

and TfpgColor is defined as follows:

 TfpgColor = type longword;

With FPC 2.2.0 (64bit and 32bit) the code compiles with out issues.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
Graeme Geldenhuys wrote 6 lines
and TfpgColor is defined as follows: TfpgColor = type longword; With FPC 2.2.0 (64bit and 32bit) the code compiles with out issues.

And some predefined colors used in fpGUI are defined as follows:

  clSilver        = TfpgColor($C0C0C0);
  clTeal          = TfpgColor($008080);
  clWhite         = TfpgColor($FFFFFF);
  clYellow        = TfpgColor($FFFF00);
  clNone          = TfpgColor($1FFFFFFF);
  clDefault       = TfpgColor($20000000);

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Martin Schreiber: What is wrong with this code: " program rangeerror; {$ifdef FPC}{$mode…
Martin Schreiber wrote 22 lines
What is wrong with this code: " program rangeerror; {$ifdef FPC}{$mode objfpc}{$h+}{$endif} {$ifdef mswindows}{$apptype console}{$endif} uses {$ifdef FPC}{$ifdef linux}cthreads,{$endif}{$endif} sysutils; type colorty = type longword; const cl_mapped = colorty($90000000); type ttestclass = class private fcolor: colorty; published property color: colorty read fcolor write fcolor default cl_mapped; //<<-- end; begin end.

It compiles again. Unrelated (because I think such declarations are broken for fpu types/values): what code do you have to write so that this default value is actually used?

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 28 lines
On 28 Mar 2008, at 07:47, Martin Schreiber wrote: >What is wrong with this code: >" >program rangeerror; >{$ifdef FPC}{$mode objfpc}{$h+}{$endif} >{$ifdef mswindows}{$apptype console}{$endif} >uses >{$ifdef FPC}{$ifdef linux}cthreads,{$endif}{$endif} >sysutils; >type >colorty = type longword; >const >cl_mapped = colorty($90000000); >type >ttestclass = class > private > fcolor: colorty; > published > property color: colorty read fcolor write fcolor default cl_mapped; //<<-- >end; >begin >end. It compiles again. Unrelated (because I think such declarations are broken for fpu types/values): what code do you have to write so that this default value is actually used?

It is used in streaming in the classes unit; the streaming mechanism checks the actual value against this value: if it is the same, the value is not streamed.

Martin by himself probably doesn't have specific code.

Michael.

Reply by email

Micha Nelissen
to Michael Van Canneyt
Michael Van Canneyt wrote
It is used in streaming in the classes unit; the streaming mechanism checks the actual value against this value: if it is the same, the value is not streamed.

FYI: so before streaming, the "streamer" has to reset the values to their defaults to stream properly. Unfortenately, there is no function to do this, and it's usually done in constructor. Therefore streaming twice does not work properly.

Micha

Reply by email

Martin Schreiber
to Jonas Maebe: It compiles again. Unrelated (because I think such declarations are broken for fpu…
Jonas Maebe wrote
On 28 Mar 2008, at 07:47, Martin Schreiber wrote: > What is wrong with this code:

[...]

It compiles again.

Thanks!

Unrelated (because I think such declarations are broken for fpu types/values): what code do you have to write so that this default value is actually used?

fcolor is initialized to the default value in constructor. TWriter does not stream property values which are equal to the default value.

Martin

Reply by email

Graeme Geldenhuys
to Jonas Maebe: It compiles again. Unrelated (because I think such declarations are broken for fpu…
Jonas Maebe wrote
It compiles again. Unrelated (because I think such declarations are broken for fpu types/values): what code do you have to write so that this default value is actually used?

fpGUI's UI Designer generates GUI code directly in the .pas unit, not via BinaryObjectToText() etc.. It checks the default value of a property before it decides to generate code or not. Here is an example of a Boolean property.

function TPropertyBoolean.GetPropertySource(wg: TfpgWidget; const
ident: string): string;
var
  i: integer;
  s: string;
  PropInfo: PPropInfo;
begin
  PropInfo := GetPropInfo(wg.ClassType, Name);
  i := GetOrdProp(wg, Name);
  if PropInfo^.Default  i then
  begin
    if i = 1 then
      s := 'True'
    else
      s := 'False';
    Result := ident + Name + ' := ' + s + ';' + LineEnding;
  end
  else
    Result := '';
end;

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Martin Schreiber: [...] Thanks! fcolor is initialized to the default value in constructor. TWriter does not…
Martin Schreiber wrote 6 lines
> Unrelated (because I think such declarations are > broken for fpu types/values): what code do you have to write so that > this default value is actually used? > fcolor is initialized to the default value in constructor. TWriter does

Well, you can set the default values automatically without having to do it manually in the constructor. :-) I have been toying with this idea in fpGUI. All that the developer needs to do is set the default value in the class declaration.

I created a descendant TComponent class and in the AfterConstructor
method I call the SetDefaults();
procedure TfpgWindowBase.AfterConstruction;
begin
  inherited AfterConstruction;
  { Here is a neater way by using RTTI to set default property
    values all automatically. No need to duplicate the efforts
    and manually set the property default values in the
    constructor. This code is now the same for each
    TfpgWindowBase descendant (which includes GUI widgets) }
  SetDefaults(self);
end;
// This function uses RTTI to automatically set the default values
// of properties. That means we don't have to do it in the
// constructor anymore! :-)
procedure SetDefaults(Obj: TObject);
var
  PropInfos: PPropList;
  Count, Loop: Integer;
begin
  PropInfos := nil;
  { Find out how many properties we'll be considering }
  Count := GetPropList(Obj.ClassInfo, tkPropsWithDefault, nil);
  { Allocate memory to hold their RTTI data }
  GetMem(PropInfos, Count * SizeOf(PPropInfo));
  try
    { Get hold of the property list in our new buffer }
    GetPropList(Obj.ClassInfo, tkPropsWithDefault, PropInfos);
    { Loop through all the selected properties }
    for Loop := 0 to Count - 1 do
      with PropInfos^[Loop]^ do
        { If there is supposed to be a default value... }
        if Default  NoDefault then
          { ...then jolly well set it }
          SetOrdProp(Obj, PropInfos^[Loop], Default)
  finally
    FreeMem(PropInfos, Count * SizeOf(PPropInfo));
  end;
end;

RTTI can be very handy sometimes! ;-)

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Michael Van Canneyt
to Micha Nelissen: FYI: so before streaming, the "streamer" has to reset the values to their defaults to…
Micha Nelissen wrote 9 lines
Michael Van Canneyt wrote: > It is used in streaming in the classes unit; the streaming mechanism checks > the actual > value against this value: if it is the same, the value is not streamed. FYI: so before streaming, the "streamer" has to reset the values to their defaults to stream properly. Unfortenately, there is no function to do this, and it's usually done in constructor. Therefore streaming twice does not work properly.

This is not correct.

The default value is the value at create time and remains fixed during the lifetime of the component. It has no influence on the number of times you stream a component.

Michael.

Reply by email

Mattias Gärtner
to Michael Van Canneyt

Zitat von Michael Van Canneyt :

Show quoted text 22 lines
On Fri, 28 Mar 2008, Micha Nelissen wrote: > Michael Van Canneyt wrote: > > It is used in streaming in the classes unit; the streaming mechanism checks > > the actual > > value against this value: if it is the same, the value is not streamed. > > FYI: so before streaming, the "streamer" has to reset the values to their > defaults to stream properly. Unfortenately, there is no function to do this, > and it's usually done in constructor. Therefore streaming twice does not work > properly. This is not correct. The default value is the value at create time and remains fixed during the lifetime of the component. It has no influence on the number of times you stream a component.

Theoretically yes.
Practically it works this way:
TWriter writes a value if it differs from the 'default'. The 'default' is
1. if there is a stored function, and it returns false, then the current value is a default.
2. if there is an ancestor, then the current value of the ancestor
3. the 'default' constant of the property.

So, it is not always possible to find out if _a_ value is default. You can only find out if the _current_ value is default.

And even worse:
This is only true for normal properties. The DefineProperties can do nearly anything.

Conclusion:
In general you can not 'reset' an arbitrary component. Graeme's SetDefaults could be extended to apply all ancestor streams. Then it would probably set the defaults for 99% of all properties correct, assuming that the properties define good stored functions, good constructor values and good default constants.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gärtner
Mattias Gärtner wrote 35 lines
Zitat von Michael Van Canneyt : > > > On Fri, 28 Mar 2008, Micha Nelissen wrote: > > > Michael Van Canneyt wrote: > > > It is used in streaming in the classes unit; the streaming mechanism > checks > > > the actual > > > value against this value: if it is the same, the value is not streamed. > > > > FYI: so before streaming, the "streamer" has to reset the values to their > > defaults to stream properly. Unfortenately, there is no function to do > this, > > and it's usually done in constructor. Therefore streaming twice does not > work > > properly. > > This is not correct. > > The default value is the value at create time and remains fixed during the > lifetime of the component. It has no influence on the number of times you > stream a component. Theoretically yes. Practically it works this way: TWriter writes a value if it differs from the 'default'. The 'default' is 1. if there is a stored function, and it returns false, then the current value is a default. 2. if there is an ancestor, then the current value of the ancestor 3. the 'default' constant of the property. So, it is not always possible to find out if _a_ value is default. You can only find out if the _current_ value is default.

Yes, but now you are juggling with terms, and mixing concepts:

- The "default" keyword means the value when the class was created. Nothing more, nothing less.
As such the current implementation does what it needs to do.
- Stored is a mechanism, separate from default, to determine whether a property should be stored at all, regardless of the value, be it default or not.
- The ancestor never acts as 'default'. Visual inheritance is a diff mechanism, nothing else: only the differences between ancestor and child should be streamed.

The streaming mechanism uses these 3 concepts to minimalize the size of the stream that it creates. It couldn't care less about resetting the component or whatever.

If a 'reset to defaults' mechanism is required, then a different set of concepts must be developed and used.

Michael.

Reply by email

Micha Nelissen
to Michael Van Canneyt: This is not correct. The default value is the value at create time and remains fixed…
Michael Van Canneyt wrote 10 lines
> FYI: so before streaming, the "streamer" has to reset the values to their > defaults to stream properly. Unfortenately, there is no function to do this, > and it's usually done in constructor. Therefore streaming twice does not work > properly. This is not correct. The default value is the value at create time and remains fixed during the lifetime of the component. It has no influence on the number of times you stream a component.

Example: suppose a component has been written out that uses the default for a certain property X. Now if you do:

class.X := <some-non-default-value>;
stream.readstream(class);
(class.X = <default-value>) is false, while it should be true.

Micha

Reply by email

Michael Van Canneyt
to Micha Nelissen: Example: suppose a component has been written out that uses the default for a certain…
Micha Nelissen wrote 20 lines
Michael Van Canneyt wrote: > > FYI: so before streaming, the "streamer" has to reset the values to their > > defaults to stream properly. Unfortenately, there is no function to do > > this, > > and it's usually done in constructor. Therefore streaming twice does not > > work > > properly. > > This is not correct. > > The default value is the value at create time and remains fixed during the > lifetime of the component. It has no influence on the number of times you > stream a component. Example: suppose a component has been written out that uses the default for a certain property X. Now if you do: class.X := <some-non-default-value>; stream.readstream(class); (class.X = <default-value>) is false, while it should be true.

Why should it be true ?
The specs only say something about writing, not about reading.

It is a misconception to think that you can read a stream and thus restore a component to it's "original designed state".

The behaviour of reading a component from stream is only well-defined after it was just created.

If you want a general streaming mechanism (javabeans like), then you simply should not use "stored" or "default", then you'll have something that comes close.

Michael.

Reply by email

Michael Van Canneyt
to Micha Nelissen: Oh come on! It's not *that* far from a general streaming mechanism; so I consider this a…
Micha Nelissen wrote 7 lines
Michael Van Canneyt wrote: > If you want a general streaming mechanism (javabeans like), then you > simply should not use "stored" or "default", then you'll have something > that comes close. Oh come on! It's not *that* far from a general streaming mechanism; so I consider this a design flaw.

IMHO, it's very far, see Mattias' remarks :(

Michael.

Reply by email

Micha Nelissen
to Michael Van Canneyt
Michael Van Canneyt wrote
> Oh come on! It's not *that* far from a general streaming mechanism; so I > consider this a design flaw. IMHO, it's very far, see Mattias' remarks :(

Hmm well the other "fun" thing was that in Delphi you could not have no default for floats or integers IIRC. Maybe this was fixed though?

Micha

Reply by email

Michael Van Canneyt
to Micha Nelissen
Micha Nelissen wrote 8 lines
Michael Van Canneyt wrote: > > Oh come on! It's not *that* far from a general streaming mechanism; so I > > consider this a design flaw. > > IMHO, it's very far, see Mattias' remarks :( Hmm well the other "fun" thing was that in Delphi you could not have no default for floats or integers IIRC. Maybe this was fixed though?

Floats not, integers yes, I think ?

Michael.

Reply by email

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 14 lines
On Fri, 28 Mar 2008, Micha Nelissen wrote: > Michael Van Canneyt wrote: >>> Oh come on! It's not *that* far from a general streaming >>> mechanism; so I >>> consider this a design flaw. >> >> IMHO, it's very far, see Mattias' remarks :( > > Hmm well the other "fun" thing was that in Delphi you could not > have no > default for floats or integers IIRC. Maybe this was fixed though? Floats not, integers yes, I think ?

FPC cannot deal properly with floats either as far as I can see from the compiler source code. But since there is apparently no way to easily create a simple test program, I can't verify this.

Jonas

Reply by email

Martin Schreiber
to Jonas Maebe
Jonas Maebe wrote 7 lines
> > Floats not, integers yes, I think ? FPC cannot deal properly with floats either as far as I can see from the compiler source code. But since there is apparently no way to easily create a simple test program, I can't verify this.

AFAIK there is a inherent default of 0.0, "default" property keyword can not be used with floats.

Martin

Reply by email

Jonas Maebe
to Martin Schreiber
Martin Schreiber wrote 11 lines
On Friday 28 March 2008 16.36:35 Jonas Maebe wrote: >> >> Floats not, integers yes, I think ? > > FPC cannot deal properly with floats either as far as I can see from > the compiler source code. But since there is apparently no way to > easily create a simple test program, I can't verify this. > AFAIK there is a inherent default of 0.0, "default" property keyword can not be used with floats.

In can be in FPC.

Jonas

Reply by email

Martin Schreiber
to Jonas Maebe
Jonas Maebe wrote 14 lines
On 28 Mar 2008, at 16:41, Martin Schreiber wrote: > On Friday 28 March 2008 16.36:35 Jonas Maebe wrote: >>> Floats not, integers yes, I think ? >> >> FPC cannot deal properly with floats either as far as I can see from >> the compiler source code. But since there is apparently no way to >> easily create a simple test program, I can't verify this. > > AFAIK there is a inherent default of 0.0, "default" property keyword > can not > be used with floats. In can be in FPC.

Uuh, no rounding problems across platforms and by
ObjectTextToBinary<->ObjectBinaryToText? ;-)

Martin

Reply by email

Jonas Maebe
to Martin Schreiber
Martin Schreiber wrote 18 lines
On Friday 28 March 2008 16.42:52 Jonas Maebe wrote: > On 28 Mar 2008, at 16:41, Martin Schreiber wrote: >> On Friday 28 March 2008 16.36:35 Jonas Maebe wrote: >>>> Floats not, integers yes, I think ? >>> >>> FPC cannot deal properly with floats either as far as I can see >>> from >>> the compiler source code. But since there is apparently no way to >>> easily create a simple test program, I can't verify this. >> >> AFAIK there is a inherent default of 0.0, "default" property keyword >> can not >> be used with floats. > > In can be in FPC. > Uuh, no rounding problems across platforms

No, because it forces everything into a single (although wrongly, as far as I can see).

and by ObjectTextToBinary<->ObjectBinaryToText? ;-)

As I said, I don't think it works at all currently, but I have no test program to verify that assumption.

Jonas

Reply by email

Anton Kavalenka
to Michael Van Canneyt: Why should it be true ? The specs only say something about writing, not about reading. It…
Show quoted text 19 lines
Why should it be true ? The specs only say something about writing, not about reading. It is a misconception to think that you can read a stream and thus restore a component to it's "original designed state". The behaviour of reading a component from stream is only well-defined after it was just created. If you want a general streaming mechanism (javabeans like), then you simply should not use "stored" or "default", then you'll have something that comes close. Michael. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

This was about modifiers
http://bugs.freepascal.org/view.php?id=10080

Current impementation of propert writer is Delphi incompatible (eg does not take in account modifiers as the Delphi does).

Anton

Reply by email