Sign in Join

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

Mailing lists / lazarus / 2015-11

Extending TRect breaks Lazarus

53 messages · 19 people · –

Reply by email Subscribe to this list Your subscription

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

Marco van de Voort

FYI:

I yesterday tried to implement some of the TRect helper methods in 3.1.1 and property and Lazarus(/win32) refused to start due to WMSIZE loops.

I haven't investigated deeper yet, but I suspect the heavy use of WITH in interfaces etc is the cause. (if you assign width and height of a component in a component method in a WITH with a TRECT as argument, then now width and height of the trect are assigned instead of the component's ?

Probably method calling (setwidth/setheight?) is dangerous too.

Request for TRect and patch that I used : http://bugs.freepascal.org/view.php?id=21041

Reply by email

Dmitry Boyarintsev
to Marco van de Voort
Marco van de Voort wrote 6 lines
I haven't investigated deeper yet, but I suspect the heavy use of WITH in interfaces etc is the cause. (if you assign width and height of a component in a component method in a WITH with a TRECT as argument, then now width and height of the trect are assigned instead of the component's ?

This is odd. How adding the method to TRect didn't break much for Delphi? (or maybe it did, we just don't know it).
I'd think that Delphi /3d party components code also uses a lot of WITHs with TRects

thanks,
Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151106/a196158a/attachment.html>

Reply by email

Ondrej Pokorny
to Dmitry Boyarintsev
Dmitry Boyarintsev wrote
This is odd. How adding the method to TRect didn't break much for Delphi?

It did break a lot of code for Delphi.

I'd think that Delphi /3d party components code also uses a lot of WITHs with TRects.

Yes, it did break a lot of code in 3rd party components as well.

---

Nevertheless I am of the opinion that WITH is evil and should be removed from the IDE/LCL code (unless only identifiers from within the with scope are used; but even then they could be removed...). The Width/Height (+ other useful functions) are a good TRect enhancement.

Ondrej

Reply by email

Marco van de Voort
to Dmitry Boyarintsev: This is odd. How adding the method to TRect didn't break much for Delphi? (or maybe it…
Dmitry Boyarintsev wrote 9 lines
> I haven't investigated deeper yet, but I suspect the heavy use of WITH in > interfaces etc is the cause. (if you assign width and height of a > component in a component method in a WITH with a TRECT as argument, then > now > width and height of the trect are assigned instead of the component's ? > This is odd. How adding the method to TRect didn't break much for Delphi? (or maybe it did, we just don't know it).

Maybe they were more careful with WITH or had problems and simply fixed them, always used self. to qualify such cases. I don't routine look at Delphi source, so I don't know which one.

I'd think that Delphi /3d party components code also uses a lot of WITHs with TRects

Well, not anymore I guess :-) Or there is a flaw in my thinking, but if so, then I don't see it. I'm currently building fpc with raise tobject.create in the relevant methods to see if I can quickly identify some locations.

Yup:

a#0 0x77055b68 in RaiseException () from C:\WINDOWS\SysWOW64\KernelBase.dll #1 0x00416039 in fpc_raiseexception (OBJ=0xe11f3c8, ANADDR=0x0, # AFRAME=0xe11f730) at seh32.inc:93
#2 0x00417cb6 in RECT__SETWIDTH (AVALUE=236058416, this=...) at # c:/repo/fpc/rtl/win/wininc/func.inc:2414
#3 0x00531d0a in TWIN32WIDGETSET__GETWINDOWSIZE (HANDLE=986038, # WIDTH=986038, HEIGHT=5,
this=<error reading variable>) at
C:/repo/lazarus/lcl/interfaces/win32/win32winapi.inc:2395 #4 0x004f0c0e in GETWINDOWSIZE (HANDLE=986038, WIDTH=986038, HEIGHT=5) at # C:/repo/lazarus/lcl/include/winapi.inc:564
#5 0x0052ad58 in TWINDOWPROCHELPER__DOMSGSIZE (this=<error reading # variable>)
at C:/repo/lazarus/lcl/interfaces/win32/win32callback.inc:1903 #6 0x0052be5b in TWINDOWPROCHELPER__DOWINDOWPROC (this=<error reading variable>)
at C:/repo/lazarus/lcl/interfaces/win32/win32callback.inc:2358 #7 0x0052c767 in WINDOWPROC (WINDOW=986038, MSG=5, WPARAM=0, LPARAM=0)

Maybe for the 3rd party support it is smart to tag them with experimental or so till this code is really release (as 3.2), so that people at least get an hint that something is/could be wrong.

Reply by email

Michael Van Canneyt
to Martin Schreiber: Or implement a safe "with" in Free Pascal without waiting until it is enforced by Delphi…
Martin Schreiber wrote 8 lines
On Friday 06 November 2015 17:20:24 Ondrej Pokorny wrote: > > Nevertheless I am of the opinion that WITH is evil and should be removed > from the IDE/LCL code (unless only identifiers from within the with > scope are used; but even then they could be removed...). Or implement a safe "with" in Free Pascal without waiting until it is enforced by Delphi compatibility...

Ehm. How can "with" ever be safe ?

Don't get me wrong:

I use it abundantly. If I have QMYQueryObjectWithAVeryLongName then being able to write

With QMYQueryObjectWithAVeryLongName do
   try
     // Really nice code
   finally
     Close;
   end;

is really good (tm).

NOT being able to use with would seriously impede on the readability of my code.

Add this to the observation that the lazarus team demands 'clear' variable names, and does not like/accept i,m,f,p,q or whatever as variable names, and using "with" becomes very attractive indeed...

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt
Michael Van Canneyt wrote
> by Delphi compatibility... Ehm. How can "with" ever be safe ?

Btw the case that I fixed was like this

procedure TSomeForm.Getwind...

procedure setwidthheight(const r : TRect); inline;
begin
 with R do
   begin
    width:=right-left;
    height:=bottom-top;
  end;
end;
begin
 ...
  setwidtheight(r);
end

In such case fixing with SELF doesn't work, because self isn't allowed in the nested function. I had to strip the WITH.

Luckily it wasn't as bad as expected, and only this one in the win32 widget set.

Don't get me wrong: I use it abundantly. If I have QMYQueryObjectWithAVeryLongName then being able to write

Me too, but I like to qualify fieldnames with self when the they are short, common words.

Show quoted text 22 lines
With QMYQueryObjectWithAVeryLongName do try // Really nice code finally Close; end; is really good (tm). NOT being able to use with would seriously impede on the readability of my code. Add this to the observation that the lazarus team demands 'clear' variable names, and does not like/accept i,m,f,p,q or whatever as variable names, and using "with" becomes very attractive indeed... Michael. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Flávio Etrusco
to Michael Van Canneyt: Ehm. How can "with" ever be safe ? Don't get me wrong: I use it abundantly. If I have…
Michael Van Canneyt wrote 42 lines
On Fri, 6 Nov 2015, Martin Schreiber wrote: > On Friday 06 November 2015 17:20:24 Ondrej Pokorny wrote: >> >> >> Nevertheless I am of the opinion that WITH is evil and should be removed >> from the IDE/LCL code (unless only identifiers from within the with >> scope are used; but even then they could be removed...). > > > Or implement a safe "with" in Free Pascal without waiting until it is > enforced > by Delphi compatibility... Ehm. How can "with" ever be safe ? Don't get me wrong: I use it abundantly. If I have QMYQueryObjectWithAVeryLongName then being able to write With QMYQueryObjectWithAVeryLongName do try // Really nice code finally Close; end; is really good (tm). NOT being able to use with would seriously impede on the readability of my code. Add this to the observation that the lazarus team demands 'clear' variable names, and does not like/accept i,m,f,p,q or whatever as variable names, and using "with" becomes very attractive indeed... Michael.

I hate "with" with passion because maintaining code written using it (by other people ;-) ) is very often a living hell. I, for one, always use local variables in that case, but I'd really really love to be able to declare an alias for "with" expression, no matter how many people say it's unpascalish...

WRT a "safe with", well, the compiler could continue the identifier search as if it didn't find in the With expression and then generate an error or warning...

-Fl?vio

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: Ehm. How can "with" ever be safe ? Don't get me wrong: I use it abundantly. If I have…
Michael Van Canneyt wrote
I use it abundantly. If I have QMYQueryObjectWithAVeryLongName then being able to write

Can't you simply use an "absolute" variable, or alias variable with a shorter name - instead of WITH all together.

I hate WITH, but do use it on occasion - primarily in fpGUI's Form Designer (auto generated code). But if I do have to use WITH, I always only use one variable with it.

For me at least, WITH falls into the same category as GOTO. It has its pitfalls, can easily be abused, but useful on occasions. ;-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Martin Schreiber
to Michael Van Canneyt: Ehm. How can "with" ever be safe ? Don't get me wrong: I use it abundantly. If I have…
Michael Van Canneyt wrote 11 lines
On Fri, 6 Nov 2015, Martin Schreiber wrote: > On Friday 06 November 2015 17:20:24 Ondrej Pokorny wrote: >> Nevertheless I am of the opinion that WITH is evil and should be removed >> from the IDE/LCL code (unless only identifiers from within the with >> scope are used; but even then they could be removed...). > > Or implement a safe "with" in Free Pascal without waiting until it is > enforced by Delphi compatibility... Ehm. How can "with" ever be safe ?

You are joking, no? It has been discussed on fpc-pascal/fpc-devel several times. An IIRC Italian community member then usually shows a syntax description of a safe "with" statement from a maybe more than 20 year old pascal dialect.
But probably such language additions are not sexy enough.

Martin

Reply by email

Michael Van Canneyt
to Martin Schreiber
Martin Schreiber wrote 14 lines
On Friday 06 November 2015 17:42:39 Michael Van Canneyt wrote: > On Fri, 6 Nov 2015, Martin Schreiber wrote: >> On Friday 06 November 2015 17:20:24 Ondrej Pokorny wrote: >>> Nevertheless I am of the opinion that WITH is evil and should be removed >>> from the IDE/LCL code (unless only identifiers from within the with >>> scope are used; but even then they could be removed...). >> >> Or implement a safe "with" in Free Pascal without waiting until it is >> enforced by Delphi compatibility... > > Ehm. How can "with" ever be safe ? > You are joking, no? It has been discussed on fpc-pascal/fpc-devel several times.

Erm... I am not joking.

Do you really think I recall every discussion or braindead proposal from these mailing lists over the last 20 years ?

I appreciate your high esteem of my memory, but alas, age takes it's toll... ;-)

But presumably you mean some construct as

With QMyVeryLongQueyObjectName as Q do
   try
     // Do things with Q
   finally
     Q.Close;
   end;

?

That is a modification of the current "with".
I assumed you meant to make an unchanged "with" safe.

That said, a construct such as "With QMyVeryLongQueyObjectName as Q do" has my support...

Michael.

Reply by email

Ondrej Pokorny
to Michael Van Canneyt: Ehm. How can "with" ever be safe ? Don't get me wrong: I use it abundantly. If I have…
Michael Van Canneyt wrote
Ehm. How can "with" ever be safe ?

You can make sure that if some property is ADDED into the with scope, it doesn't break anything by explicitely using Self (or the unit name or whatever):

procedure TForm1.DoMySize;
begin
   //...
   with MyRect do
     Self.Width := Right - Left;
end;

But you cannot do anything if a property is REMOVED (e.g. Right in this case)...

So yes, let's not use with :)

+ I don't use with in my code any more. I confess that in the beginning I did use it, but decided to ignore the with is
no problem with long variable are CodeTools :)

Ondrej

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: Erm... I am not joking. Do you really think I recall every discussion or braindead…
Michael Van Canneyt wrote 6 lines
With QMyVeryLongQueyObjectName as Q do try // Do things with Q finally Q.Close; end;
var
  Q: TQuery absolute QMyVeryLongQueyObjectName;
begin
  with Q do
    try
      // Do things with Q
    finally
      Q.Close;
    end;

problem solved! ;-)

And because Q is such a short name, I wouldn't even both with the WITH statement above. It would make for easier debugging too. eg: debug tooltips evaluation etc.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Martin Schreiber
to Graeme Geldenhuys: var Q: TQuery absolute QMyVeryLongQueyObjectName; begin with Q do try // Do things with Q…
Graeme Geldenhuys wrote 21 lines
On 2015-11-06 17:19, Michael Van Canneyt wrote: > With QMyVeryLongQueyObjectName as Q do > try > // Do things with Q > finally > Q.Close; > end; var Q: TQuery absolute QMyVeryLongQueyObjectName; begin with Q do try // Do things with Q finally Q.Close; end; problem solved! ;-)

Not a good idea IMHO, that hinders readability because one doesn't see the real container at the "with" block start. Another important use of "with" is to make complex address calculations only once at the "with" block start without the need to define a pointer variable in "var" and to dereference in every statement.

Martin

Reply by email

Michael Van Canneyt
to Martin Schreiber
Martin Schreiber wrote 27 lines
On Friday 06 November 2015 18:33:54 Graeme Geldenhuys wrote: > On 2015-11-06 17:19, Michael Van Canneyt wrote: >> With QMyVeryLongQueyObjectName as Q do >> try >> // Do things with Q >> finally >> Q.Close; >> end; > > var > Q: TQuery absolute QMyVeryLongQueyObjectName; > begin > with Q do > try > // Do things with Q > finally > Q.Close; > end; > > > problem solved! ;-) > Not a good idea IMHO, that hinders readability because one doesn't see the real container at the "with" block start. Another important use of "with" is to make complex address calculations only once at the "with" block start without the need to define a pointer variable in "var" and to dereference in every statement.

Indeed, and besides this:

a) it does not compile for properties. See below.
b) I did mention the requirement about non-trivial readable variable names...

Michael.

program Project1;
{$mode objfpc}
Type
   TMyType = class(TObject)
   private
     FM: TMyType;
     function GetM: TMyType;
     procedure SetM(AValue: TMyType);
   Public
     Procedure DoIt;
     Property MyVeryLongObjectPropertyName : TMyType Read GetM Write SetM;
   end;
function TMyType.GetM: TMyType;
begin
   Result:=Nil;
end;
procedure TMyType.SetM(AValue: TMyType);
begin
   //
end;
procedure TMyType.DoIt;
Var
   Q : TMyType absolute MyVeryLongObjectPropertyName; // Error !!!
begin
end;
begin
end.

Reply by email

Mattias Gaertner
to Marco van de Voort: FYI: I yesterday tried to implement some of the TRect helper methods in 3.1.1 and…
Show quoted text 7 lines
[...] I yesterday tried to implement some of the TRect helper methods in 3.1.1 [...] I haven't investigated deeper yet, but I suspect the heavy use of WITH in interfaces etc is the cause. (if you assign width and height of a component in a component method in a WITH with a TRECT as argument, then now width and height of the trect are assigned instead of the component's ?

Thanks for the hint.

Does Delphi alter some other records too, e.g. TPoint and TSize?

Hint:
Cody has a tool 'Explode a "With" block':
http://wiki.lazarus.freepascal.org/Cody#Explode_a_.22With.22_block

Mattias

Reply by email

Dmitry Boyarintsev
to Mattias Gaertner
Mattias Gaertner wrote
Does Delphi alter some other records too, e.g. TPoint and TSize? It does

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Types.TPoint http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Types.TSize

so it's just a matter of time when FPC RTL replicates them.

thanks,
Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151106/3acf3638/attachment.html>

Reply by email

Luca Olivetti
to Martin Schreiber: You are joking, no? It has been discussed on fpc-pascal/fpc-devel several times. An IIRC…

El 06/11/15 a les 18:10, Martin Schreiber ha escrit:

You are joking, no? It has been discussed on fpc-pascal/fpc-devel several times. An IIRC Italian community member then usually shows a syntax description of a safe "with" statement from a maybe more than 20 year old pascal dialect.

I don't know if that's me, but, yes, I used a variant of pascal (by texas instruments) that allowed to declare aliases with "with", e.g

  with a=somerecord, b=someotherrecord do
  begin
    a.x:=b.x;
  end;

I even found the (scanned) reference manual to confirm the syntax but now I cannot find it.
It is definitely more than 20 years old (and more than 30 ;-):

http://www.computinghistory.org.uk/det/11554/TI-990-System/

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es/ Tel. +34 93 5883004 (Ext.3010) Fax +34 93 5883007

Reply by email

Florian Klaempfl
to Luca Olivetti
Luca Olivetti wrote 15 lines
El 06/11/15 a les 18:10, Martin Schreiber ha escrit: > You are joking, no? It has been discussed on fpc-pascal/fpc-devel several > times. An IIRC Italian community member then usually shows a syntax > description of a safe "with" statement from a maybe more than 20 year old > pascal dialect. I don't know if that's me, but, yes, I used a variant of pascal (by texas instruments) that allowed to declare aliases with "with", e.g with a=somerecord, b=someotherrecord do begin a.x:=b.x; end;

While I think this is something were a patch would be accepted, my main issue is that the with handling code in the compiler is somehow messy. Not necessarily due to bad coding but simply the way how "with" works. It is similiar to the proc. var code which is also one of the places only very brave people look at ;)

Reply by email

Mark Morgan Lloyd
to Luca Olivetti: El 06/11/15 a les 18:10, Martin Schreiber ha escrit: I don't know if that's me, but, yes,…
Luca Olivetti wrote 14 lines
El 06/11/15 a les 18:10, Martin Schreiber ha escrit: > You are joking, no? It has been discussed on fpc-pascal/fpc-devel several > times. An IIRC Italian community member then usually shows a syntax > description of a safe "with" statement from a maybe more than 20 year old > pascal dialect. I don't know if that's me, but, yes, I used a variant of pascal (by texas instruments) that allowed to declare aliases with "with", e.g with a=somerecord, b=someotherrecord do begin a.x:=b.x; end;

Just because something is 20+ years old doesn't necessarily make it bad. That syntax looks OK to me (i.e. make a and b look like consts) but I also find myself wondering what the type rules are, i.e.

with pod: TTabSheet= Pages.Objects[deleteAt] do

vs

with pod= TTabSheet(Pages.Objects[deleteAt]) do
Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Marco van de Voort
to Mattias Gaertner: On Fri, 6 Nov 2015 16:45:07 +0100 Thanks for the hint. Does Delphi alter some other…
Mattias Gaertner wrote 9 lines
> width and height of the trect are assigned instead of the component's ? Thanks for the hint. Does Delphi alter some other records too, e.g. TPoint and TSize? Hint: Cody has a tool 'Explode a "With" block': http://wiki.lazarus.freepascal.org/Cody#Explode_a_.22With.22_block

Would have been nice to run that on the code that I replied to Michael. (with the local procedure)

Anyway, I hunted down one case by raise tobject.create, and running in the debugger, and I committed a fix. The Win32 lazarus now seems to function normally at first glance.

Reply by email

Sven Barth
to Marco van de Voort: Btw the case that I fixed was like this procedure TSomeForm.Getwind... procedure…
"Marco van de Voort" wrote 26 lines
On Fri, Nov 06, 2015 at 05:42:39PM +0100, Michael Van Canneyt wrote: > > by Delphi compatibility... > > Ehm. How can "with" ever be safe ? Btw the case that I fixed was like this procedure TSomeForm.Getwind... procedure setwidthheight(const r : TRect); inline; begin with R do begin width:=right-left; height:=bottom-top; end; end; begin ... setwidtheight(r); end In such case fixing with SELF doesn't work, because self isn't allowed in the nested function. I had to strip the WITH.

Self really isn't allowed in nested functions? O.o

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151107/c85213e8/attachment-0001.html>

Reply by email

Alexander Klenin
to Florian Klaempfl: While I think this is something were a patch would be accepted, my main issue is that the…
Florian Klaempfl wrote 7 lines
Am 06.11.2015 um 20:22 schrieb Luca Olivetti: > El 06/11/15 a les 18:10, Martin Schreiber ha escrit: > >> You are joking, no? It has been discussed on fpc-pascal/fpc-devel several >> times. An IIRC Italian community member then usually shows a syntax >> description of a safe "with" statement from a maybe more than 20 year old >> pascal dialect.

Here is one "recent" discussion:
http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-with-is-evil-isn-t-it-td3219144.html

It is similiar to the proc. var code which is also one of the places only very brave people look at ;)

One nice thing about FPC/Lazarus is that I may disappear for a few years, then look back and see same topics discussed by the same people with the same conclusions ;-)

Alexander S. Klenin

Reply by email

Ondrej Pokorny
to Mark Morgan Lloyd: Just because something is 20+ years old doesn't necessarily make it bad. That syntax…
Mark Morgan Lloyd wrote 15 lines
Luca Olivetti wrote: > with a=somerecord, b=someotherrecord do > begin > a.x:=b.x; > end; Just because something is 20+ years old doesn't necessarily make it bad. That syntax looks OK to me (i.e. make a and b look like consts) but I also find myself wondering what the type rules are, i.e. with pod: TTabSheet= Pages.Objects[deleteAt] do vs with pod= TTabSheet(Pages.Objects[deleteAt]) do

Do not forget that you can overload operators! In particular you can overload the comparison operator to return a record, so your "with a=somerecord do" can already be a valid pascal code now:

*type**
** TMyRec = record**
** I: Integer;**
** end;**
**
** TMyResult = record**
** Res: Integer;**
** end;**
**
**operator = (z1: TMyRec; z2 : TMyRec) b : TMyResult;** **begin**
** Result.Res := z1.I+z2.I;**
**end;**
**
**var**
** m1, m2: TMyRec;**
**begin**
** m1.I := 10;**
** m2.I := 1;**
** with m1=m2 do**
** writeln(Res);**
** readln;**
**end.*

The assignment operator would be better, since it doesn't return a value (in pascal, of course) and thus cannot be used in a with statement now:

*with a:=somerecord, b:=someotherrecord do**
**begin**
** a.x:=b.x;**
**end; **
*
IMO there is no need to set a type of a/b on the left side of the with assignment - the left side should always gain the type from the the right side. In this case you can decide whether the "AS" or the direct re-type should be used:

*with pod := Pages.Objects[deleteAt] as TTabSheet do **
**with pod := TTabSheet(Pages.Objects[deleteAt]) do **
*
-> both are valid and the syntax is already in pascal - why not to use it.

Ondrej
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151107/fb06130b/attachment.html>

Reply by email

Florian Klaempfl
to Ondrej Pokorny
Ondrej Pokorny wrote 31 lines
Do not forget that you can overload operators! In particular you can overload the comparison operator to return a record, so your "with a=somerecord do" can already be a valid pascal code now: *type** ** TMyRec = record** ** I: Integer;** ** end;** ** ** TMyResult = record** ** Res: Integer;** ** end;** ** **operator = (z1: TMyRec; z2 : TMyRec) b : TMyResult;** **begin** ** Result.Res := z1.I+z2.I;** **end;** ** **var** ** m1, m2: TMyRec;** **begin** ** m1.I := 10;** ** m2.I := 1;** ** with m1=m2 do** ** writeln(Res);** ** readln;** **end.* The assignment operator would be better, since it doesn't return a value (in pascal, of course) and thus cannot be used in a with statement now:

Good that we removed another "great" language extennsion already years ago, the support for a C-like assignment operator which returns a result :)))

Reply by email

Florian Klaempfl
to Alexander Klenin: Here is one "recent" discussion: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-w…
Alexander Klenin wrote 17 lines
On Sat, Nov 7, 2015 at 5:58 AM, Florian Klaempfl wrote: > Am 06.11.2015 um 20:22 schrieb Luca Olivetti: >> El 06/11/15 a les 18:10, Martin Schreiber ha escrit: >> >>> You are joking, no? It has been discussed on fpc-pascal/fpc-devel several >>> times. An IIRC Italian community member then usually shows a syntax >>> description of a safe "with" statement from a maybe more than 20 year old >>> pascal dialect. Here is one "recent" discussion: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-with-is-evil-isn-t-it-td3219144.html > It is similiar to the proc. var code which is also one of the places > only very brave people look at ;) One nice thing about FPC/Lazarus is that I may disappear for a few years, then look back and see same topics discussed by the same people with the same conclusions ;-)

Indeed, unfortunatly nothing changed: bug count increases continously and the fixing is done mainly by the long term comitters but people are still proposing to extend the language with more sugar increasing maintainance work.

Reply by email

Michael Van Canneyt
to Alexander Klenin: Here is one "recent" discussion: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-w…
Alexander Klenin wrote 16 lines
On Sat, Nov 7, 2015 at 5:58 AM, Florian Klaempfl wrote: > Am 06.11.2015 um 20:22 schrieb Luca Olivetti: >> El 06/11/15 a les 18:10, Martin Schreiber ha escrit: >> >>> You are joking, no? It has been discussed on fpc-pascal/fpc-devel several >>> times. An IIRC Italian community member then usually shows a syntax >>> description of a safe "with" statement from a maybe more than 20 year old >>> pascal dialect. Here is one "recent" discussion: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-with-is-evil-isn-t-it-td3219144.html > It is similiar to the proc. var code which is also one of the places > only very brave people look at ;) One nice thing about FPC/Lazarus is that I may disappear for a few years, then look back and see same topics discussed by the same people with the same conclusions ;-)

Well, assuming God exists and visits from time to time to look at her creation, she probably thinks the same about humanity.

So FPC really is just a representative sample of humanity. With the same factions.

Michael.

Reply by email

Jürgen Hestermann
to Ondrej Pokorny: You can make sure that if some property is ADDED into the with scope, it doesn't break…
Ondrej Pokorny wrote
So yes, let's not use with :) ... There is no problem with long variable are CodeTools :)

CodeTools do not help you *read* the code.

I prefer to have this:

-----------------------------
with PathArray[High(PathArray)]^ do
    fillchar(StatisticOfFiles,sizeof(StatisticOfFiles),0);
-----------------------------

instead of this:

-----------------------------
fillchar(PathArray[High(PathArray)]^.StatisticOfFiles,sizeof(PathArray[High(PathArray)]^.StatisticOfFiles),0); -----------------------------

Also, the problem of the WITH statement is the same as for identifiers declared in other units. Do you also preceed variables from a used unit with the unit name?

Reply by email

Mattias Gaertner
to Jürgen Hestermann
[...] CodeTools do not help you *read* the code.

It can help you writing the code more readable and helps to read (i.e. understand) the code by hints and find declaration.

Show quoted text 11 lines
[...] ----------------------------- with PathArray[High(PathArray)]^ do fillchar(StatisticOfFiles,sizeof(StatisticOfFiles),0); ----------------------------- instead of this: ----------------------------- fillchar(PathArray[High(PathArray)]^.StatisticOfFiles,sizeof(PathArray[High(PathArray)]^.StatisticOfFiles),0); -----------------------------

An one liner with only one used variable is a pretty safe 'with' and is mostly a matter of taste.

But a complicated expression like PathArray[High(PathArray)]^ can be made more readable (easier to understand) like this:

LastPath:=PathArray[High(PathArray)];
fillchar(LastPath^.StatisticOfFiles,sizeof(LastPath^.StatisticOfFiles),0);

Use Ctrl+Shift+C on LastPath to create the pointer variable.

Mattias

Reply by email

Lukasz Sokol
to Mattias Gaertner
Mattias Gaertner wrote
On Sat, 7 Nov 2015 11:39:44 +0100 J?rgen Hestermann wrote:

[...]

Show quoted text 10 lines
> ----------------------------- > with PathArray[High(PathArray)]^ do > fillchar(StatisticOfFiles,sizeof(StatisticOfFiles),0); > ----------------------------- > > instead of this: > > ----------------------------- > fillchar(PathArray[High(PathArray)]^.StatisticOfFiles,sizeof(PathArray[High(PathArray)]^.StatisticOfFiles),0); > -----------------------------

[...]

LastPath:=PathArray[High(PathArray)]; fillchar(LastPath^.StatisticOfFiles,sizeof(LastPath^.StatisticOfFiles),0);

Will this form produce same code (as in memory footprint and machine code/so-called performance) ?

(but then, the last form, will have the variable declared explicitly, which probably means more complicated code around this region etc.?)

Use Ctrl+Shift+C on LastPath to create the pointer variable. Mattias

el es

Reply by email

Mattias Gaertner
to Lukasz Sokol
Show quoted text 22 lines
[...] On 07/11/15 11:01, Mattias Gaertner wrote: > On Sat, 7 Nov 2015 11:39:44 +0100 > J?rgen Hestermann wrote: > [...] >> ----------------------------- >> with PathArray[High(PathArray)]^ do >> fillchar(StatisticOfFiles,sizeof(StatisticOfFiles),0); >> ----------------------------- >> >> instead of this: >> >> ----------------------------- >> fillchar(PathArray[High(PathArray)]^.StatisticOfFiles,sizeof(PathArray[High(PathArray)]^.StatisticOfFiles),0); >> ----------------------------- [...] > > LastPath:=PathArray[High(PathArray)]; > fillchar(LastPath^.StatisticOfFiles,sizeof(LastPath^.StatisticOfFiles),0); > Will this form produce same code (as in memory footprint and machine code/so-called performance) ?

The above three are not the same.

The second version executes the With-Expression multiple times, so unless the compiler optimizes a lot it will create more code and will be slower.

The first and third versions have the same amount of reads/writes and with optimizations (-O2 or higher) create the same assembler code. Without optimizations the first is a bit faster, because the compiler stores the With-Pointer in a register, while in third version it stores it on the stack.

(but then, the last form, will have the variable declared explicitly, which probably means more complicated code around this region etc.?)

A local variable is bread and butter for the compiler. There is nothing complicated about it.
I would argue that giving an expression a describing name can make code less complicated.

Mattias

Reply by email

Lukasz Sokol
to Mattias Gaertner
Mattias Gaertner wrote 22 lines
The above three are not the same. The second version executes the With-Expression multiple times, so unless the compiler optimizes a lot it will create more code and will be slower. The first and third versions have the same amount of reads/writes and with optimizations (-O2 or higher) create the same assembler code. Without optimizations the first is a bit faster, because the compiler stores the With-Pointer in a register, while in third version it stores it on the stack. > (but then, the last form, will have the variable declared explicitly, which probably means more complicated code around this region etc.?) A local variable is bread and butter for the compiler. There is nothing complicated about it. I would argue that giving an expression a describing name can make code less complicated. Mattias

Thanks, I believe, this should be added into the docs somewhere ;) if it's not already there.

el es

Reply by email

Michael Van Canneyt
to markbass72
markbass72 wrote
hi all I need to consume a web service by attaching a file as MTOM I have not found any documentation for Lazarus, is there a workaround that I could adopt?

To my knowledge:

None exists.
I had the same problem in Delphi, none of the existing toolkits supports it.

I ended up doing the requests with MTOM manually: allow the toolkit to do the request, catch the error, and then parse the request myself.

I have asked the author of WST to look at it, but I do not think this is high priority, as MTOM is rather exotic...

Michael.

Reply by email

Sven Barth
to Mattias Gaertner: On Mon, 9 Nov 2015 10:48:02 +0000 The docs already note that the compiler uses a…
"Mattias Gaertner" wrote 6 lines
On Mon, 9 Nov 2015 10:48:02 +0000 Lukasz Sokol wrote: >[...] > Thanks, I believe, this should be added into the docs somewhere ;) if

it's not already there.

Show quoted text 7 lines
The docs already note that the compiler uses a temporary register for 'With'. http://www.freepascal.org/docs-html/ref/refsu58.html#x155-16500013.2.8 Of course if there is no register left the compiler uses the stack.

Please note that this is an implementation detail. The point a user should care about is that the expression of the with is evaluated only once (before the block of the with is entered). Everything else is up to the compiler.
(I would prefer if it wouldn't be mentioned as is in the documentation)

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151109/65ab98f7/attachment.html>

Reply by email

Jürgen Hestermann
to Sven Barth
Sven Barth wrote 10 lines
> The docs already note that the compiler uses a temporary register > for 'With'. > http://www.freepascal.org/docs-html/ref/refsu58.html#x155-16500013.2.8 > Of course if there is no register left the compiler uses the stack. Please note that this is an implementation detail. The point a user should care about is that the expression of the with is evaluated only once (before the block of the with is entered). Everything else is up to the compiler. (I would prefer if it wouldn't be mentioned as is in the documentation)

This information is very important IMO.
The programmer should know which coding has which performance.

The reason for many slow programs is that
the programmer(s) do not know about such details.
If i.e. a loop over a huge array can be speeded up with a slight coding change it should be done.
The attitude: "don't worry about the details" is wrong IMO.

Reply by email

Sven Barth
to Jürgen Hestermann
"J?rgen Hestermann" wrote 10 lines
Am 2015-11-09 um 14:26 schrieb Sven Barth: > > > > The docs already note that the compiler uses a temporary register > > for 'With'. > > http://www.freepascal.org/docs-html/ref/refsu58.html#x155-16500013.2.8 > > Of course if there is no register left the compiler uses the stack. > > Please note that this is an implementation detail. The point a user

should care about is that the expression of the with is evaluated only once (before the block of the with is entered). Everything else is up to the compiler.

Show quoted text 5 lines
> (I would prefer if it wouldn't be mentioned as is in the documentation) > > This information is very important IMO. The programmer should know which coding has which performance.

Which is solved by saying that the expression is only evaluated once. The user doesn't need to know the detail that the value is kept in a temporary register, because that statement by itself is utterly useless for the user, as on load/store architectures like ARM you /always/ have values in registers if they are worked with and the compiler will happily spill around the contents if necessary.

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151110/ef014155/attachment.html>

Reply by email

Jürgen Hestermann
to Sven Barth
Sven Barth wrote
The user doesn't need to know the detail that the value is kept in a temporary register, because that statement by itself is utterly useless for the user, as on load/store architectures like ARM you /always/ have values in registers if they are worked with and the compiler will happily spill around the contents if necessary.

Does that mean, that local variables and with statements are treated completely identically? Are both held in registers with the same mechanism and will there never be an (speed) adavantage of one of them? If there is only the chance that it may speed up the code (even when only on certain platforms) then I would like to know it.

Reply by email

Mattias Gaertner
to Jürgen Hestermann
[...] Does that mean, that local variables and with statements are treated completely identically?

A local var can be changed. Without optimization the compiler puts the local var on the stack. With optimization enabled the compiler can find out that the local var is only read, which is also true for a with-expression and applies the same optimizations.

Optimizing read only variables is basic code optimization.

Are both held in registers with the same mechanism and will there never be an (speed) adavantage of one of them? If there is only the chance that it may speed up the code (even when only on certain platforms) then I would like to know it.

If speed matters you should enable optimization. When optimization is enabled there is no difference.

Mattias

Reply by email

Sven Barth
to Jürgen Hestermann: Does that mean, that local variables and with statements are treated completely…
"J?rgen Hestermann" wrote
Am 2015-11-10 um 11:32 schrieb Sven Barth: > > The user doesn't need to know the detail that the value is kept in a

temporary register, because that statement by itself is utterly useless for the user, as on load/store architectures like ARM you /always/ have values in registers if they are worked with and the compiler will happily spill around the contents if necessary.

Does that mean, that local variables and with statements are treated

completely identically?

Are both held in registers with the same mechanism and will there never

be an (speed) adavantage of one of them?

If there is only the chance that it may speed up the code (even when only

on certain platforms) then I would like to know it.

It always depends on the specific code (its complexity) and the specific compiler settings (optimizations) and maybe also the target architecture (because of register pressure and such). There is nothing general I can say /except/ that the with expression will be evaluated only once. Thus depending on the circumstances a local variable and the usage of with might behave the same. In simple cases the with /might/ be faster because it won't result in the expression result being stored on the stack, but that's by no means a given.

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151110/518d1f54/attachment.html>

Reply by email

Sven Barth
to Sven Barth
"Sven Barth" wrote 7 lines
Am 10.11.2015 12:27 schrieb "J?rgen Hestermann" < : > > Am 2015-11-10 um 11:32 schrieb Sven Barth: >> >> The user doesn't need to know the detail that the value is kept in a

temporary register, because that statement by itself is utterly useless for the user, as on load/store architectures like ARM you /always/ have values in registers if they are worked with and the compiler will happily spill around the contents if necessary.

> > > Does that mean, that local variables and with statements are treated

completely identically?

> Are both held in registers with the same mechanism and will there never

be an (speed) adavantage of one of them?

> If there is only the chance that it may speed up the code (even when

only on certain platforms) then I would like to know it.

It always depends on the specific code (its complexity) and the specific

compiler settings (optimizations) and maybe also the target architecture (because of register pressure and such). There is nothing general I can say /except/ that the with expression will be evaluated only once. Thus depending on the circumstances a local variable and the usage of with might behave the same. In simple cases the with /might/ be faster because it won't result in the expression result being stored on the stack, but that's by no means a given.

So... I quickly rechecked the code and can now make a more fundated statement. In case of a more complex expression (e.g. not a field that's a class or something like that) the expression will be stored in a temporary /variable/ not a register. Thus the generated code should be the same as for a local variable. For non complex expressions the value is used directly (e.g. as if the with didn't happen), though further optimizations (e.g. the regvars optimization) might improve that.

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151110/6fce5635/attachment.html>

Reply by email

Marco van de Voort
to Mattias Gaertner
Mattias Gaertner wrote 7 lines
>[...] > Anyway, I hunted down one case by raise tobject.create, and running in the > debugger, and I committed a fix. The Win32 lazarus now seems to function > normally at first glance. I replaced many endangered with-blocks in the LCL. ToDo: check the rest of the Lazarus sources.

Ok, I plan finalizing and committing the trect stuff in the coming week.

Reply by email

Anthony Walter
to Juha Manninen

My solution is to define my own TRectI type which can implicitly convert between TRectI <-> TRect. Also I use a TRectF which does the same thing, but with floats as the dimenions ... MyRectInt := TRectI(MyRectFloat); ... There is also TPointI and TPointF ...

{ TRectI }

  TRectI = record
  private
    function GetEmpty: Boolean;
    procedure SetTop(Value: Integer);
    procedure SetLeft(Value: Integer);
    function GetRight: Integer;
    procedure SetRight(Value: Integer);
    function GetBottom: Integer;
    procedure SetBottom(Value: Integer);
    function GetSize: TPointI;
    function GetTopLeft: TPointI;
    function GetBottomLeft: TPointI;
    function GetBottomRight: TPointI;
    function GetTopRight: TPointI;
    function GetMidPoint: TPointI;
  public
    X, Y, Width, Height: Integer;
    class operator Implicit(const Value: TRectI): TRect;
    class operator Implicit(const Value: TRect): TRectI;
    class operator Equal(const A, B: TRectI): Boolean;
    class operator NotEqual(const A, B: TRectI): Boolean;
    class function Create: TRectI; overload; static;
    class function Create(Size: TPointI): TRectI; overload; static;
    class function Create(W, H: Integer): TRectI; overload; static;
    class function Create(X, Y, W, H: Integer): TRectI; overload; static;
    function Equals(const Value: TRectI): Boolean;
    function Contains(X, Y: Integer): Boolean; overload;
    function Contains(const P: TPointI): Boolean; overload;
    procedure Center(X, Y: Integer); overload;
    procedure Center(const P: TPointI); overload;
    procedure Inflate(X, Y: Integer); overload;
    procedure Inflate(const P: TPointI); overload;
    procedure Offset(X, Y: Integer); overload;
    procedure Offset(const P: TPointI); overload;
    property Empty: Boolean read GetEmpty;
    property Left: Integer read X write SetLeft;
    property Top: Integer read Y write SetTop;
    property Right: Integer read GetRight write SetRight;
    property Bottom: Integer read GetBottom write SetBottom;
    property Size: TPointI read GetSize;
    property TopLeft: TPointI read GetTopLeft;
    property BottomLeft: TPointI read GetBottomLeft;
    property BottomRight: TPointI read GetBottomRight;
    property TopRight: TPointI read GetTopRight;
    property MidPoint: TPointI read GetMidPoint;
  end;
  PRectI = ^TRectI;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151111/203ea0d3/attachment.html>

Reply by email

Marco van de Voort
to Bart: Should these be merged to 1.4 fixes branch? Bart
Bart wrote 5 lines
On 11/11/15, Marco van de Voort wrote: > Ok, I plan finalizing and committing the trect stuff in the coming week. Should these be merged to 1.4 fixes branch?

If you want to run 1.4 with trunk yes.

It won't be in 3.0.0, and even 3.0.0 fixes branch is to be decided when the impact is clearer.

So for now FPC trunk only, and see how much dust it throws up.

Reply by email

Marco van de Voort
to Marco van de Voort: Ok, I plan finalizing and committing the trect stuff in the coming week.
Marco van de Voort wrote
> I replaced many endangered with-blocks in the LCL. > ToDo: check the rest of the Lazarus sources. Ok, I plan finalizing and committing the trect stuff in the coming week.

The first batch is committed. Tpoint* is reasonably complete but TRect and -F need some more methods.

The problem is also a bit that TRect is more complicated and my sources span various Delphi versions and are sometimes conflicting.

Reply by email