Sign in Join

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

Mailing lists / fpc-devel / 2019-02

"Blank slate" next version of FPC

108 messages · 27 people · –

Reply by email Subscribe to this list Your subscription

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

Unknown author

I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust.

Strongest features of Pascal (in my opinion):
1. Code readability
2. Strong typing
3. Quick compilation.
4. ???

Strongest features of Rust (from wikipedia):
1. Memory safety (no null pointers, no dangling pointers, no data races in safe code)
2. Memory management with "resource acquisition is initialization"
3. Ownership rules favorable for safety
4. Ad-hoc polymorphism (traits) [instead of traditional OOP class inheritance]
5. ???

Other features worth investigation:
1. Syntax for parallel math (SIMD)
2. Syntax and methodology for parallel algorithms dispatch (GPU via Vulkan, RISC-V coprocessors, etc.)
3. ???

So, what features are desirable for a 21st century programming language in this world of multiple cores? I think a clean slate new language "done the Pascal way" would be beneficial.

Could someone with knowledge of both Pascal and Rust elucidate the advantages of both languages?

Is there interest in combining the syntax of Pascal with the features of Rust et al. to create the next version of FPC?

Thanks!

Reply by email

J. Gareth Moreton

I can't speak for the senior developers, but I think there's a preference that backwards compatibility is maintained, at least between versions of FPC if not Delphi.  At least my preference is to attempt to better support the existing FPC - for example, I tend to do a lot of work and research into x86-64 assembly language, including compiler algorithms that attempt to use the full MM registers where possible.
I think if you want to truly design a new language, or a new dialect of Pascal (as you are implying), it might be best to start with a prototype to showcase its merits.

I don't know much about Rust so I probably can't help you too much, and my mindset with programming very much belongs in the 90s unfortunately, as while I attempt to write cross-platform code, I'm not afraid to drop into raw assembly language if there's a potential speed benefit.

I suppose one 21st Century desire of not so much the language, but the compiler, is the ability to fully utilise modern CPU features like the AVX instruction set and the FMA instructions, but still be able to drop back to SSE2 if compatibility is a major concern.
Just my thoughts.

Gareth aka. Kit

On Fri 15/02/19 05:28 , James via fpc-devel
sent:
I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust.

Strongest features of Pascal (in my opinion):
  1. Code readability
  2. Strong typing
  3. Quick compilation.
  4. ???
 
Strongest features of Rust (from wikipedia):
  1. Memory safety (no null pointers, no dangling pointers, no data races in safe code)
  2. Memory management with "resource acquisition is initialization"   3. Ownership rules favorable for safety
  4. Ad-hoc polymorphism (traits) [instead of traditional OOP class inheritance]
  5. ???

Other features worth investigation:
  1. Syntax for parallel math (SIMD)
  2. Syntax and methodology for parallel algorithms dispatch (GPU via Vulkan, RISC-V coprocessors, etc.)
  3. ???

So, what features are desirable for a 21st century programming language in this world of multiple cores? I think a clean slate new language "done the Pascal way" would be beneficial.

Could someone with knowledge of both Pascal and Rust elucidate the advantages of both languages?

Is there interest in combining the syntax of Pascal with the features of Rust et al. to create the next version of FPC?

Thanks!

Reply by email

Sven Barth
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…

Am Fr., 15. Feb. 2019, 10:07 hat James via fpc-devel <

Show quoted text 7 lines
geschrieben: I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust.

A non backwards compatible version of FPC would not be FPC.

If you want to discuss singular extensions of the language (in a backwards compatible way that respects the spirit of the existing language) that can be done, but I highly doubt that a complete remodelling of the language just to satisfy the next hype language is in the interest of the other core devs (it definitely isn't in mine).

Regards,
Sven

Reply by email

Jonas Maebe
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…
James wrote
I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC.

As mentioned by others, that's not really something any of the current FPC developers are interested in working on. Martin Schreiber, however, was working on a project like that before he passed away, called Mselang: https://github.com/fredvs/mselang .

With him gone, the project is currently somewhat stalled, but at the same time if you wish to work on such a project, it is probably the most advanced of its kind and new contributors are undoubtedly welcome. You can subscribe to the MSE mailing list at
https://sourceforge.net/projects/mseide-msegui/lists/mseide-msegui-talk

Jonas

Reply by email

J. Gareth Moreton

That's an interesting project there.

One thing that does spring to mind though.,, what features of Delphi and FPC made the language unsuitable for Martin Schreiber, and is it anything we developers can possibly address in some way?

Gareth aka. Kit

On Fri 15/02/19 20:32 , Jonas Maebe sent:

James wrote
I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC.

As mentioned by others, that's not really something any of the current FPC developers are interested in working on. Martin Schreiber, however, was working on a project like that before he passed away, called Mselang: https://github.com/fredvs/mselang [1] .

With him gone, the project is currently somewhat stalled, but at the same time if you wish to work on such a project, it is probably the most advanced of its kind and new contributors are undoubtedly welcome. You can subscribe to the MSE mailing list at
https://sourceforge.net/projects/mseide-msegui/lists/mseide-msegui-talk [2]

Jonas

Reply by email

J. Gareth Moreton

Hm, fair enough.  Seems a bit strange to not like a new feature, although Delphi did start getting a bit bloated in places.  Ah well!  Compatibility is never a bad thing though!
Gareth aka. Kit

On Sat 16/02/19 08:27 , Jonas Maebe sent:

J. Gareth Moreton wrote
One thing that does spring to mind though.,, what features of Delphi and FPC made the language unsuitable for Martin Schreiber, and is it anything we developers can possibly address in some way?

He did not like new language features and RTL changes added by Delphi in newer versions (generics, codepage-aware strings, RTL switched to unicode string), and FPC's goal to remain Delphi-compatible.

Jonas

Reply by email

Marco van de Voort
to J. Gareth Moreton: That's an interesting project there. One thing that does spring to mind though.,, what…

Op 2/16/2019 om 1:37 AM schreef J. Gareth Moreton:

Show quoted text 6 lines
That's an interesting project there. One thing that does spring to mind though.,, what features of Delphi and FPC made the language unsuitable for Martin Schreiber, and is it anything we developers can possibly address in some way?

Martin was a loner kind of guy, he did the most of the MSEGUI etc projects alone too.

Reply by email

Jonas Maebe
to J. Gareth Moreton: That's an interesting project there. One thing that does spring to mind though.,, what…
J. Gareth Moreton wrote
One thing that does spring to mind though.,, what features of Delphi and FPC made the language unsuitable for Martin Schreiber, and is it anything we developers can possibly address in some way?

He did not like new language features and RTL changes added by Delphi in newer versions (generics, codepage-aware strings, RTL switched to unicode string), and FPC's goal to remain Delphi-compatible.

Jonas

Reply by email

Florian Klämpfl
to J. Gareth Moreton: Hm, fair enough.  Seems a bit strange to not like a new feature, although Delphi did…
J. Gareth Moreton wrote
Hm, fair enough.  Seems a bit strange to not like a new feature, although Delphi did start getting a bit bloated in places.  Ah well! Compatibility is never a bad thing though!

"Do not break people's code" is one of FPC design goals. So anything not backward is out of scope of FPC. Of course, sometimes we cannot avoid this, but we try as much as possible to break old code.

Reply by email

Michael Van Canneyt
to J. Gareth Moreton: Hm, fair enough.  Seems a bit strange to not like a new feature, although Delphi did…
J. Gareth Moreton wrote
Hm, fair enough.  Seems a bit strange to not like a new feature, although Delphi did start getting a bit bloated in places.  Ah well!  Compatibility is never a bad thing though!

Hm. 'a bit bloated' is the understatement of the year.

I still program mostly using language features of essentially D7. Works fine, and I don't think my productivity is in any way enhanced by all the new features. Maybe enumerators save some typing. And it's not that I haven't tried the new features. What I miss - usually - are libraries to perform common tasks.

I wonder where the success of Javascript comes from ? As a language it is simplicity itself, and yet Javascript thrives.

The only extension to have a real success is TypeScript, which simply introduces some type checking and more or less real 'constants'...

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt

Am Sa., 16. Feb. 2019, 09:58 hat Michael Van Canneyt geschrieben:

Show quoted text 23 lines
On Sat, 16 Feb 2019, J. Gareth Moreton wrote: > Hm, fair enough. Seems a bit strange to not like a new feature, although > Delphi did start getting a bit bloated in places. Ah well! > Compatibility is never a bad thing though! Hm. 'a bit bloated' is the understatement of the year. I still program mostly using language features of essentially D7. Works fine, and I don't think my productivity is in any way enhanced by all the new features. Maybe enumerators save some typing. And it's not that I haven't tried the new features. What I miss - usually - are libraries to perform common tasks. I wonder where the success of Javascript comes from ? As a language it is simplicity itself, and yet Javascript thrives. The only extension to have a real success is TypeScript, which simply introduces some type checking and more or less real 'constants'...

Time for pas2js to change this 😁

Regards,
Sven

Reply by email

Ralf Quint
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…
James wrote
I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust.

I am, like apparently many others, NOT interested in such shenanigans. Either program in Pascal or program in Rust.

Adding newfangled gadgets and gizmos might be all fine and dandy, but don't force it down the throat of everyone as a must. I am not going to throw away 40 years of libraries and snippets away and start from scratch, just so some folks can claim to run with the in-crowd. I got work to do...

Ralf

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

Reply by email

Mattias Gaertner
to Ralf Quint
Show quoted text 6 lines
[...] Adding newfangled gadgets and gizmos might be all fine and dandy, but don't force it down the throat of everyone as a must. I am not going to throw away 40 years of libraries and snippets away and start from scratch, just so some folks can claim to run with the in-crowd. I got work to do...

+1

But FPC has accumulated so many features over the years that it became hard for a newbie to learn the whole language, some old language features are hardly needed anymore and many of the new languages features are hidden behind some modeswitches.

For example I would like to disable TP objects and writeable const and enable advanced records. Are there some command line params to do that?

Mattias

Reply by email

Benito van der Zander
to Florian Klämpfl: "Do not break people's code" is one of FPC design goals. So anything not backward is out…

Hi,

there is NewPascal with improved memory safety/smart pointers: http://newpascal.org/

but we try as much as possible to break old code.

I have noticed that. All my code has been broken by the codepage aware strings and TEncoding

and FPC's goal to remain Delphi-compatible.

So are inline variables coming soon?
http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html

Works fine, and I don't think my productivity is in any way enhanced by all the new features. Maybe enumerators save some typing.

The new features also generate too often weird assembly, and then you have to benchmark is the old code faster or the new one, and then it can turn out the enumerators are slower than an old school loop , or the case of strings is slower than a hashmap, and then the new features need to be avoided.

Best,
Benito

Reply by email

Sven Barth
to Benito van der Zander: there is NewPascal with improved memory safety/smart pointers: http://newpascal.org/ I…

Am Sa., 16. Feb. 2019, 23:44 hat Benito van der Zander geschrieben:

Show quoted text 8 lines
but we try as much as possible to break old code. I have noticed that. All my code has been broken by the codepage aware strings and TEncoding

Introduction of the codepage aware AnsiString was one of the disruptive changes that couldn't really be avoided.
And TEncoding can't have broken anything as that was only introduced then (and one doesn't even need to use it when working with strings).

Show quoted text 6 lines
and FPC's goal to remain Delphi-compatible. So are inline variables coming soon? http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html

We have already decided internally that this feature is where we draw the line. We won't implement it and we are also inclined to say "patches *not* welcome" for that.

Regards,
Sven

Reply by email

Neil Graham
to Ralf Quint: I am, like apparently many others, NOT interested in such shenanigans. Either program in…
Ralf Quint wrote 14 lines
On 2/14/2019 9:28 PM, James via fpc-devel wrote: > I'm interested in starting (or joining) a discussion on the next > (*non* backwards compatible) version of FPC. Instead of being > classically object oriented, there is merit in examining a model with > ad-hoc polymorphism like Rust. I am, like apparently many others, NOT interested in such shenanigans. Either program in Pascal or program in Rust. Adding newfangled gadgets and gizmos might be all fine and dandy, but don't force it down the throat of everyone as a must. I am not going to throw away 40 years of libraries and snippets away and start from scratch, just so some folks can claim to run with the in-crowd. I got work to do...

I think for the most part, if any clean slate is needed for FPC it is for the Libraries and not the language.  A Class library that was built to support the language as it currently stands rather than collecting layers of legacy. TThing TFPThing TFPGThing layers etc.

As such it needn't break any backwards compatibility,  The same language can support the old and the new and users can choose which one they wish to use.  The new would presumably be more coherent and have the benefit of hindsight, the old would remain having the bulk of the existing 3rd party support for many years still.

There's no reason these two can't be developed in parallel by different people.

Reply by email

Ben Grasset
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…

On Fri, Feb 15, 2019 at 4:07 AM James via fpc-devel <

Show quoted text 7 lines
wrote: I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust.

Here's my two cents:

There's nothing overtly wrong at all with FPC as it stands now, IMO. It arguably does have quite a range of features, many of which are borderlines useless nowadays, but I don't think this matters a whole lot.

The idea that it is "bloated" as I sometimes hear doesn't make a whole lot of sense, for one. FPC does not magically add things you don't use to your binary. How would that work? Why would you think it did? It's illogical.

More specifically, the ongoing idea that pops up every now and then that *anything
*new could *ever* be "forced down" anyone's "throat" is moreso the problem, I think. It's sheer nonsense *FUD*, and always has been. You can go *way* back in the archives for this very mailing list and see people making doomsday claims about how the introduction of "for-in" loops, of all things, were somehow going to magically "ruin" the language. Of course, that did not happen, (specifically because the idea made no at all sense to begin with, of course.)

It's even more tiresome to see the claim I often see about "go use XYZ language if you want XYZ feature", especially when in many cases *nobody *has mentioned XYZ is *almost never *anyone's point. It's not 2002 anymore. The whole "Pascal vs. C++" or "Pascal vs Java" or "Pascal vs. Whatever Language" idea is *completely ridiculous *nowadays (and has been for years.) Stop mentioning it people. It's not a thing. It's not real.

As far as what we're actually *missing*, the clear biggest is certainly anonymous methods IMO. Where the hell is Blaise Thorne? Can we just find the guy, get him to finish it, and get the thing merged once and for all? Or just use some different implementation? Some kind of tuple functionality (as I believe was discussed in the past) would be a nice addition also.

Reply by email

Ben Grasset
to Jonas Maebe: As mentioned by others, that's not really something any of the current FPC developers are…
PM Jonas Maebe wrote
As mentioned by others, that's not really something any of the current FPC developers are interested in working on. Martin Schreiber, however, was working on a project like that before he passed away

I don't want to speak ill of the dead, but I think you've *hugely* misinterpreted his goals. Martin Schreiber was like the *ultimate* "Delphi 7 was perfect and nobody needs anything beyond its features" sort of person. Basically the polar opposite of what you're saying. The sort of person who really honestly thinks (or thought) that typecasting void pointers back and forth is somehow preferable to just using generics because generics are "bad" for some vague reason they can't explain, and who openly stated that he never planned to add generics to his language (which personally made me decide right then to not bother keeping up to date with the development on it.)

His compiler code was / is just kind of an unreadable mess, to be perfectly honest.

Reply by email

Florian Klämpfl
to Neil Graham: I think for the most part, if any clean slate is needed for FPC it is for the Libraries…
Neil Graham wrote 20 lines
On 17/02/19 10:37 AM, Ralf Quint wrote: > On 2/14/2019 9:28 PM, James via fpc-devel wrote: >> I'm interested in starting (or joining) a discussion on the next >> (*non* backwards compatible) version of FPC. Instead of being >> classically object oriented, there is merit in examining a model with >> ad-hoc polymorphism like Rust. > > I am, like apparently many others, NOT interested in such shenanigans. > Either program in Pascal or program in Rust. > > Adding newfangled gadgets and gizmos might be all fine and dandy, but > don't force it down the throat of everyone as a must. I am not going > to throw away 40 years of libraries and snippets away and start from > scratch, just so some folks can claim to run with the in-crowd. I got > work to do... I think for the most part, if any clean slate is needed for FPC it is for the Libraries and not the language.  A Class library that was built to support the language as it currently stands rather than collecting layers of legacy. TThing TFPThing TFPGThing layers etc.

Also old libraries are still used by people so they cannot be cut down.

Reply by email

Sven Barth
to Ben Grasset: On Fri, Feb 15, 2019 at 4:07 AM James via fpc-devel < Here's my two cents: There's…

Am So., 17. Feb. 2019, 04:42 hat Ben Grasset
geschrieben:

The idea that it is "bloated" as I sometimes hear doesn't make a whole lot of sense, for one. FPC does not magically add things you don't use to your binary. How would that work? Why would you think it did? It's illogical.

For some features that is the case however as they rely on support code in the RTL that can't easily be smartlinked away.

Show quoted text 9 lines
More specifically, the ongoing idea that pops up every now and then that *anything *new could *ever* be "forced down" anyone's "throat" is moreso the problem, I think. It's sheer nonsense *FUD*, and always has been. You can go *way* back in the archives for this very mailing list and see people making doomsday claims about how the introduction of "for-in" loops, of all things, were somehow going to magically "ruin" the language. Of course, that did not happen, (specifically because the idea made no at all sense to begin with, of course.)

Nobody might be *forced* to use a feature, but what is likely is that they at least need to understand it, namely when they use third party code.

As far as what we're actually *missing*, the clear biggest is certainly

Show quoted text 5 lines
anonymous methods IMO. Where the hell is Blaise Thorne? Can we just find the guy, get him to finish it, and get the thing merged once and for all? Or just use some different implementation? Some kind of tuple functionality (as I believe was discussed in the past) would be a nice addition also.

Blaise is still working on it. Some bugs still need to be fixed and then he needs to adjust the code to the points of criticism I had given. Most importantly however are the missing tests. Even if the feature would be perfectly fine and ready to merge I won't integrate it without enough tests that ensure me that we don't break it again with the next possible commit.

Regards,
Sven

Reply by email

Ralf Quint
to Florian Klämpfl: You should have noticed, you follow this list for years/decades ;)?
Florian Klämpfl wrote 10 lines
Am 17.02.19 um 01:47 schrieb Ralf Quint: > On 2/16/2019 12:43 AM, Florian Klämpfl wrote: >> but we try as much as possible to break old code. > > Really? =-O > > Ralf ;-) > You should have noticed, you follow this list for years/decades ;)?

Yup, it's probably close to 25 years now, when it was still referred to as "Florian's Pascal Kompiler"... ;-)

But I NEVER assumed you could be able to do this intentionally... :-P

Ralf 8-)

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

Reply by email

Neil Graham
to Florian Klämpfl: Also old libraries are still used by people so they cannot be cut down.
Florian Klämpfl wrote 8 lines
Am 17.02.19 um 02:42 schrieb Neil Graham: > > I think for the most part, if any clean slate is needed for FPC it is > for the Libraries and not the language.  A Class library that was > built to support the language as it currently stands rather than > collecting layers of legacy. TThing TFPThing TFPGThing layers etc. Also old libraries are still used by people so they cannot be cut down.

That was implied by the rest of my post.   I was imagining a newer cleaner set of libraries for people beginning new projects.   The old class libraries would be still be supported, Projects would typically use entirely one or the other.   It wouldn't be a strict rule though.

Reply by email

Ryan Joseph
to Sven Barth: Am So., 17. Feb. 2019, 04:42 hat Ben Grasset geschrieben: For some features that is the…
On Feb 17, 2019, at 3:24 AM, Sven Barth via fpc-devel wrote: Blaise is still working on it. Some bugs still need to be fixed and then he needs to adjust the code to the points of criticism I had given. Most importantly however are the missing tests. Even if the feature would be perfectly fine and ready to merge I won't integrate it without enough tests that ensure me that we don't break it again with the next possible commit.

Maybe you can ask him if he wants to turn over his progress to the public so maybe one of us can finish it for him. I’ve been hearing about it almost being done for a few years now and like Ben this is the probably the most needed feature to make our lives easier.

As an intermediate measure I was able to make nested functions anonymous but Sven wanted to wait for the real thing.

Regards,
Ryan Joseph

Reply by email

Michael Schnell
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…
. Syntax for parallel math (SIMD)

In Oxygen, you have parallel loops and future variables. This can be used for defining parallelism in the syntax.

I understand that currently RemObjects implemented this as a simple translation of the appropriate .Net framework API, and that it’s only available for Software compiled for such systems, but not (yet) when compiled for native code.

But in theory, the same or similar syntax should be usable to be compiled to do SIMD support (if appropriate) and as syntax candy to support a Thread Pool library for taking advantage of the now ubiquitous SMP hardware – or both at the same time if appropriate (e.g. Matrix calculations).

-Michael

Reply by email

Michael Schnell
to Sven Barth: Am Sa., 16. Feb. 2019, 23:44 hat Benito van der Zander geschrieben: Introduction of the…
codepage aware AnsiString was one of the disruptive changes that couldn't really be avoided.

IMHO, it could have been avoided (largely), but that would have come at the cost of less perfect compatibility with Delphi XE (which even more severely broke compatibility to previous Delphi versions by their rather silly implementation). This obviously was the more important goal.

-Michael

Reply by email

George Bakhtadze
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…

Theoretically there is a way to refresh the language without breaking existing code - a new {$mode}. Or even completely new compiler will not break old code if it can handle .ppu generated by the current one.

And there is much to improve. Not only add modern language features but in syntax itself. As a tooling developer (I had to write a parser) I can say that current syntax is not as clean as I thought. Not even close. So that would be good but not realistic as there is obviously not enough resources for this.

More realistical and may be more useful would indeed be refreshing of RTL. To make this process community driven and to not get a mess in the end there should be guidelines on this: Which libraries are needed most, naming, code style, required test set and so on.

Also third party library developers suffering from absence of a dependency manager (yes, I'm aware of Online Package Manager). Recently was started a project of such tool. But it's initiator doesn't use FPC so FPC compatibility for it will have to add someone else. https://github.com/DelphiPackageManager/PackageManagerRFC/

---
Best Regards, George

15.02.2019, 12:07, "James via fpc-devel" :

Show quoted text 32 lines
I'm interested in starting (or joining) a discussion on the next (*non* backwards compatible) version of FPC. Instead of being classically object oriented, there is merit in examining a model with ad-hoc polymorphism like Rust. Strongest features of Pascal (in my opinion):   1. Code readability   2. Strong typing   3. Quick compilation.   4. ??? Strongest features of Rust (from wikipedia):   1. Memory safety (no null pointers, no dangling pointers, no data races in safe code)   2. Memory management with "resource acquisition is initialization"   3. Ownership rules favorable for safety   4. Ad-hoc polymorphism (traits) [instead of traditional OOP class inheritance]   5. ??? Other features worth investigation:   1. Syntax for parallel math (SIMD)   2. Syntax and methodology for parallel algorithms dispatch (GPU via Vulkan, RISC-V coprocessors, etc.)   3. ??? So, what features are desirable for a 21st century programming language in this world of multiple cores? I think a clean slate new language "done the Pascal way" would be beneficial. Could someone with knowledge of both Pascal and Rust elucidate the advantages of both languages? Is there interest in combining the syntax of Pascal with the features of Rust et al. to create the next version of FPC? Thanks! , _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Sven Barth
to George Bakhtadze
George Bakhtadze wrote
Also third party library developers suffering from absence of a dependency manager (yes, I'm aware of Online Package Manager). Recently was started a project of such tool. But it's initiator doesn't use FPC so FPC compatibility for it will have to add someone else. https://github.com/DelphiPackageManager/PackageManagerRFC/

This is what fppkg's purpose was and still is. And as it's already a part of FPC's infrastructure due to fpmake that will be the way forward.

Regards,
Sven

Reply by email

Paul van Helden
to Sven Barth: Am Sa., 16. Feb. 2019, 23:44 hat Benito van der Zander geschrieben: Introduction of the…
Show quoted text 16 lines
and FPC's goal to remain Delphi-compatible. > > > So are inline variables coming soon? > http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html > We have already decided internally that this feature is where we draw the line. We won't implement it and we are also inclined to say "patches *not* welcome" for that. Regards, Sven

To add a dissenting voice, from someone who has followed FPC development for more than 10 years and used to be very exited about FPC/Lazarus...

Sven's statement just about seals it for me. So then FPC's main goal isn't Delphi compatibility any more? I for one will use inline variable declarations and therefore say goodbye to FPC. Not to start a pro-vs-con discussion in this thread, but personally I see only advantages in more fine-grained control of variable scope. (Plus it has been irritating me for more than 25 years to go to the top to declare variables [and no, auto-declarations by the IDE doesn't fix it for me; e.g. if generics are good, why not duck typing?]). Yes, Embarcadero has done some horrid things to the language, but I don't see this as one of them. As a big fan of the Pascal language, I'd rather break compatibility and see the language evolve than the stoic attitude of the core devs as seen on this list. (And inline vars doesn't break anything!) If Oxygene was open source and (CPU) native, I wouldn't even been reading this list...

/2c

Reply by email

Sven Barth
to Paul van Helden: To add a dissenting voice, from someone who has followed FPC development for more than 10…

Am Mi., 20. Feb. 2019, 08:36 hat Paul van Helden
geschrieben:

Show quoted text 32 lines
and FPC's goal to remain Delphi-compatible. >> >> >> So are inline variables coming soon? >> http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html >> > > We have already decided internally that this feature is where we draw the > line. We won't implement it and we are also inclined to say "patches *not* > welcome" for that. > > Regards, > Sven > > To add a dissenting voice, from someone who has followed FPC development for more than 10 years and used to be very exited about FPC/Lazarus... Sven's statement just about seals it for me. So then FPC's main goal isn't Delphi compatibility any more? I for one will use inline variable declarations and therefore say goodbye to FPC. Not to start a pro-vs-con discussion in this thread, but personally I see only advantages in more fine-grained control of variable scope. (Plus it has been irritating me for more than 25 years to go to the top to declare variables [and no, auto-declarations by the IDE doesn't fix it for me; e.g. if generics are good, why not duck typing?]). Yes, Embarcadero has done some horrid things to the language, but I don't see this as one of them. As a big fan of the Pascal language, I'd rather break compatibility and see the language evolve than the stoic attitude of the core devs as seen on this list. (And inline vars doesn't break anything!) If Oxygene was open source and (CPU) native, I wouldn't even been reading this list...

And we don't agree here. For us inline variables is one of the most horrid if not *the* most horrid thing Embarcadero could have done to Object Pascal.

Regards,
Sven

Reply by email

Michael Schnell
to Sven Barth
. For us inline variables is one of the most horrid if not *the* most horrid thing Embarcadero could have done to Object Pascal.

Can you tell us why ?

(In C I often declare variables just before using them and I indeed would even like to do “for (int i = 0; i<10; i++) {a[i] = a[i+1];} ☺

-Michael

Reply by email

Nikolai Zhubr
to Sven Barth: Am Mi., 20. Feb. 2019, 08:36 hat Paul van Helden geschrieben: And we don't agree here.…

Hi all,

20.02.2019 13:21, Sven Barth via fpc-devel:
[...]

And we don't agree here. For us inline variables is one of the most horrid if not *the* most horrid thing Embarcadero could have done to Object Pascal.

Could you elaborate a bit about it?
While I'm not really sure what they have done exactly (not using latest Delphi and probably not going to), I've somehow got very used to (and confortable with) Java's inline declarations, especially "for (int i = 0; ....)" and similar constructs, and now I find myself doing this way all the time, because:

1. it makes it easier to see the whole picture just looking at the loop body, no need to scroll up; (The loop body might be just 10 lines of code, whereas the whole containing function sometimes has 1000s)

2. it isoltates the scope of such variable(s), therefore preventing some sorts of accidental misuse outside of e.g. the containing loop (which still do happen to me ocasionally in Pascal).

So I'm just wondering, what is wrong with such approach that it is considered so harmfull for Pascal? (Not talking here about possible excessive complexity of actual implementation in compiler, and not talking about the exact syntax chosen for that, just the idea as a whole)

Thank you,

Regards,
Nikolai

Show quoted text 8 lines
Regards, Sven _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Henry Vermaak
to Nikolai Zhubr
Nikolai Zhubr wrote 20 lines
20.02.2019 13:21, Sven Barth via fpc-devel: [...] >And we don't agree here. For us inline variables is one of the most >horrid if not *the* most horrid thing Embarcadero could have done to >Object Pascal. Could you elaborate a bit about it? While I'm not really sure what they have done exactly (not using latest Delphi and probably not going to), I've somehow got very used to (and confortable with) Java's inline declarations, especially "for (int i = 0; ....)" and similar constructs, and now I find myself doing this way all the time, because: 1. it makes it easier to see the whole picture just looking at the loop body, no need to scroll up; (The loop body might be just 10 lines of code, whereas the whole containing function sometimes has 1000s) 2. it isoltates the scope of such variable(s), therefore preventing some sorts of accidental misuse outside of e.g. the containing loop (which still do happen to me ocasionally in Pascal).

I've already tried to make these points, nobody seems to buy it. IIRC Michael (vC) said that functions shouldn't be that long, so then it's not a problem (perhaps his world is perfect, but mine certainly isn't).

I'm mostly more interested in limiting the scope to prevent accidental use, like you. It can also offer more fine grained control of where managed variables get freed.

Henry

Reply by email

Marcos Douglas B. Santos
to Sven Barth: Am Mi., 20. Feb. 2019, 08:36 hat Paul van Helden geschrieben: And we don't agree here.…
AM Sven Barth wrote
And we don't agree here. For us inline variables is one of the most horrid if not *the* most horrid thing Embarcadero could have done to Object Pascal.

+1
Even this isn't break compatibility with past code, it turns the language a mess.
I could say the same for others "new features", but it isn't the place.

regards,
Marcos Douglas

Reply by email

Marcos Douglas B. Santos
to Nikolai Zhubr: 20.02.2019 13:21, Sven Barth via fpc-devel: [...] Could you elaborate a bit about it?…
AM Nikolai Zhubr wrote 19 lines
Hi all, 20.02.2019 13:21, Sven Barth via fpc-devel: [...] > And we don't agree here. For us inline variables is one of the most > horrid if not *the* most horrid thing Embarcadero could have done to > Object Pascal. Could you elaborate a bit about it? While I'm not really sure what they have done exactly (not using latest Delphi and probably not going to), I've somehow got very used to (and confortable with) Java's inline declarations, especially "for (int i = 0; ....)" and similar constructs, and now I find myself doing this way all the time, because: 1. it makes it easier to see the whole picture just looking at the loop body, no need to scroll up; (The loop body might be just 10 lines of code, whereas the whole containing function sometimes has 1000s)

The problem is that you want to see an "i" variable that is index of the loop? The same construction was good for years, but now, as other languages has that feature, Object Pascal is obsolete and should add all that "new features"?

If a function has 1000 lines is a problem in the design, not in the language - in fact, doesn't matter the language in that case.

2. it isoltates the scope of such variable(s), therefore preventing some sorts of accidental misuse outside of e.g. the containing loop (which still do happen to me ocasionally in Pascal).

Again, if you has many variables into a method, is a problem in the design. You must split the code in other methods.
If you have blank lines inside a method, this is another case to split...

regards,
Marcos Douglas

Reply by email

Marcos Douglas B. Santos
to Henry Vermaak: I've already tried to make these points, nobody seems to buy it. IIRC Michael (vC) said…
AM Henry Vermaak wrote 26 lines
On Wed, Feb 20, 2019 at 02:26:20PM +0300, Nikolai Zhubr wrote: > 20.02.2019 13:21, Sven Barth via fpc-devel: > [...] > >And we don't agree here. For us inline variables is one of the most > >horrid if not *the* most horrid thing Embarcadero could have done to > >Object Pascal. > > Could you elaborate a bit about it? > While I'm not really sure what they have done exactly (not using latest > Delphi and probably not going to), I've somehow got very used to (and > confortable with) Java's inline declarations, especially "for (int i = 0; > ....)" and similar constructs, and now I find myself doing this way all the > time, because: > > 1. it makes it easier to see the whole picture just looking at the loop > body, no need to scroll up; (The loop body might be just 10 lines of code, > whereas the whole containing function sometimes has 1000s) > > 2. it isoltates the scope of such variable(s), therefore preventing some > sorts of accidental misuse outside of e.g. the containing loop (which still > do happen to me ocasionally in Pascal). I've already tried to make these points, nobody seems to buy it. IIRC Michael (vC) said that functions shouldn't be that long, so then it's not a problem (perhaps his world is perfect, but mine certainly isn't).

Anyone can split a function in many others. It's not so difficult and, actually, it should be done.

I'm mostly more interested in limiting the scope to prevent accidental use, like you. It can also offer more fine grained control of where managed variables get freed.

Try to see restrictions as a good thing.
In this case, which Pascal doesn't allow to declare inline variables, you must split big functions, which has many local variables, in others to have a better understanding of the algorithm. At the end, you might have a better design and reuse of the code. Everybody wins: you, your code, Pascal team - as they don't need to change the compiler - and Niklaus Wirth might not throw a curse in us.

regards,
Marcos Douglas

Reply by email

Henry Vermaak
to Marcos Douglas B. Santos
Marcos Douglas B. Santos wrote 13 lines
On Wed, Feb 20, 2019 at 8:32 AM Henry Vermaak wrote: > I'm mostly more interested in limiting the scope to prevent > accidental use, like you. It can also offer more fine grained > control of where managed variables get freed. Try to see restrictions as a good thing. In this case, which Pascal doesn't allow to declare inline variables, you must split big functions, which has many local variables, in others to have a better understanding of the algorithm. At the end, you might have a better design and reuse of the code. Everybody wins: you, your code, Pascal team - as they don't need to change the compiler - and Niklaus Wirth might not throw a curse in us.

I don't have many big functions and I've missed scoped variables in Pascal since the early 1990s. It's been standard good practice in software engineering for decades and all the languages I work with support it because it's a good idea, not because it's some newfangled fad.

But big functions happen in the real world. The fpc compiler source has dozens of extremely long functions. Lazarus too. I think the windproc function in the win32 interface is more than 700 lines (look at TWindowProcHelper.DoWindowProc).

Henry

Reply by email

Paul van Helden
to Marcos Douglas B. Santos: Anyone can split a function in many others. It's not so difficult and, actually, it…
Show quoted text 33 lines
> > 1. it makes it easier to see the whole picture just looking at the loop > > body, no need to scroll up; (The loop body might be just 10 lines of code, > > whereas the whole containing function sometimes has 1000s) > > > > 2. it isoltates the scope of such variable(s), therefore preventing some > > sorts of accidental misuse outside of e.g. the containing loop (which still > > do happen to me ocasionally in Pascal). > > I've already tried to make these points, nobody seems to buy it. IIRC > Michael (vC) said that functions shouldn't be that long, so then it's > not a problem (perhaps his world is perfect, but mine certainly isn't). Anyone can split a function in many others. It's not so difficult and, actually, it should be done. > I'm mostly more interested in limiting the scope to prevent accidental > use, like you. It can also offer more fine grained control of where > managed variables get freed. Try to see restrictions as a good thing. In this case, which Pascal doesn't allow to declare inline variables, you must split big functions, which has many local variables, in others to have a better understanding of the algorithm. At the end, you might have a better design and reuse of the code. Everybody wins: you, your code, Pascal team - as they don't need to change the compiler - and Niklaus Wirth might not throw a curse in us.

O dear, now I've dunnit...

So the argument against is: (1) split your long functions, because you should; and (2) Wirth didn't do it, so good it is not.

Long functions *might* be an indication of bad design, but you know, sometimes I have a long function that doesn't make sense to split.

Here is a good article about inline vars:
http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html

What's not to like about for var I:=0 to Count-1 do.. ?
Or var MyDict:=TDictionary<Integer,String>.Create;

Marcos says restrictions are good. The above restricts the number of lines of code while being just as (or more) readable!

Reply by email

Sven Barth
to Nikolai Zhubr: 20.02.2019 13:21, Sven Barth via fpc-devel: [...] Could you elaborate a bit about it?…

Am Mi., 20. Feb. 2019, 12:07 hat Nikolai Zhubr
geschrieben:

Show quoted text 5 lines
So I'm just wondering, what is wrong with such approach that it is considered so harmfull for Pascal? (Not talking here about possible excessive complexity of actual implementation in compiler, and not talking about the exact syntax chosen for that, just the idea as a whole)

Pascal is a language where declaration and use of variables is separated. It makes it easy to see what variables are declared and what type they are. Inline variables mess this up as a variable can be declared somewhere inside the code.
I use C++ to earn my living. I know why I'm not a fan of inline variables as I've been biten by them often enough already.

Regards,
Sven

Reply by email

Dimitrios Chr. Ioannidis
to Henry Vermaak: On Wed, Feb 20, 2019 at 09:47:20AM -0300, Marcos Douglas B. Santos I don't have many big…

Hi,

Στις 20/2/2019 3:25 μ.μ., ο Henry Vermaak έγραψε:

Show quoted text 24 lines
On Wed, Feb 20, 2019 at 09:47:20AM -0300, Marcos Douglas B. Santos wrote: > On Wed, Feb 20, 2019 at 8:32 AM Henry Vermaak > wrote: >> I'm mostly more interested in limiting the scope to prevent >> accidental use, like you. It can also offer more fine grained >> control of where managed variables get freed. > Try to see restrictions as a good thing. In this case, which Pascal > doesn't allow to declare inline variables, you must split big > functions, which has many local variables, in others to have a better > understanding of the algorithm. At the end, you might have a better > design and reuse of the code. Everybody wins: you, your code, Pascal > team - as they don't need to change the compiler - and Niklaus Wirth > might not throw a curse in us. I don't have many big functions and I've missed scoped variables in Pascal since the early 1990s. It's been standard good practice in software engineering for decades and all the languages I work with support it because it's a good idea, not because it's some newfangled fad. But big functions happen in the real world. The fpc compiler source has dozens of extremely long functions. Lazarus too. I think the windproc function in the win32 interface is more than 700 lines (look at TWindowProcHelper.DoWindowProc).

Well, people used to ( apparently still do ) write functions that were hundreds, even thousands of lines long and they used to write them in plain text editors (think Notepad) without the kind of support Lazarus provided. In that environment, declaring a variable hundreds of lines away from where it was used meant that the person reading

if (flag) limit += factor;

didn't have a lot of clues about what flag, limit and factor were. Naming conventions like Hungarian notation were adopted to help with this, and so were rules like declaring things close to where they are used. Of course, these days, it's all about refactoring, and functions are generally less than a page long, making it hard to get very much distance between where things are declared and where they are used. You're operating in a range of 0-20 and quibbling that maybe 7 is ok in this particular instance, while the guy(s) who made the rule would have LOVED to get 7 lines away and was trying to talk someone down from 700. And on top of that, in Lazarus, you can mouse over anything and see its type, is it a member variable, and so on. That means the need to see the line declaring it is lessened.

( not mine but I agree 100% ).

Dimitrios Chr. Ioannidis

Reply by email

Marcos Douglas B. Santos
to Henry Vermaak: On Wed, Feb 20, 2019 at 09:47:20AM -0300, Marcos Douglas B. Santos I don't have many big…
AM Henry Vermaak wrote 27 lines
On Wed, Feb 20, 2019 at 09:47:20AM -0300, Marcos Douglas B. Santos wrote: > On Wed, Feb 20, 2019 at 8:32 AM Henry Vermaak > wrote: > > I'm mostly more interested in limiting the scope to prevent > > accidental use, like you. It can also offer more fine grained > > control of where managed variables get freed. > > Try to see restrictions as a good thing. In this case, which Pascal > doesn't allow to declare inline variables, you must split big > functions, which has many local variables, in others to have a better > understanding of the algorithm. At the end, you might have a better > design and reuse of the code. Everybody wins: you, your code, Pascal > team - as they don't need to change the compiler - and Niklaus Wirth > might not throw a curse in us. I don't have many big functions and I've missed scoped variables in Pascal since the early 1990s. It's been standard good practice in software engineering for decades and all the languages I work with support it because it's a good idea, not because it's some newfangled fad. But big functions happen in the real world. The fpc compiler source has dozens of extremely long functions. Lazarus too. I think the windproc function in the win32 interface is more than 700 lines (look at TWindowProcHelper.DoWindowProc).

Yes, you're right. Big functions happen in the real world... But it doesn't mean those functions are well written only because they exists. IMHO, instead of support those functions, let use a better design to create them.

regards,
Marcos Douglas

Reply by email

Paul van Helden
to Sven Barth: Am Mi., 20. Feb. 2019, 12:07 hat Nikolai Zhubr geschrieben: Pascal is a language where…

On Wed, Feb 20, 2019 at 3:52 PM Sven Barth via fpc-devel <

Show quoted text 8 lines
wrote: Pascal is a language where declaration and use of variables is separated. It makes it easy to see what variables are declared and what type they are. Inline variables mess this up as a variable can be declared somewhere inside the code.

Now I'm curious. Can you point me to a resource where Pascal is defined such that the separation of declaration from use is a central tenet? I'm not sure, but I doubt I ever look at the variable declarations to help understand the rest of the code...

To me it seems like an artificial limitation which probably made compiler development easier (or compilation faster?). Yet most other languages didn't see the need for this limitation.

(I see Pascal as a C-like language with superior readability. I want the speed of C AND be able to easily understand the code).

I use C++ to earn my living. I know why I'm not a fan of inline variables as I've been biten by them often enough already. Can you provide an example of how inline variables can bite?

Reply by email

Dimitrios Chr. Ioannidis
to Paul van Helden: O dear, now I've dunnit... So the argument against is: (1) split your long functions,…

Hi,

Στις 20/2/2019 3:36 μ.μ., ο Paul van Helden έγραψε:

Show quoted text 42 lines
> > 1. it makes it easier to see the whole picture just looking at the loop > > body, no need to scroll up; (The loop body might be just 10 lines of code, > > whereas the whole containing function sometimes has 1000s) > > > > 2. it isoltates the scope of such variable(s), therefore preventing some > > sorts of accidental misuse outside of e.g. the containing loop (which still > > do happen to me ocasionally in Pascal). > > I've already tried to make these points, nobody seems to buy it.  IIRC > Michael (vC) said that functions shouldn't be that long, so then it's > not a problem (perhaps his world is perfect, but mine certainly isn't). Anyone can split a function in many others. It's not so difficult and, actually, it should be done. > I'm mostly more interested in limiting the scope to prevent accidental > use, like you.  It can also offer more fine grained control of where > managed variables get freed. Try to see restrictions as a good thing. In this case, which Pascal doesn't allow to declare inline variables, you must split big functions, which has many local variables, in others to have a better understanding of the algorithm. At the end, you might have a better design and reuse of the code. Everybody wins: you, your code, Pascal team - as they don't need to change the compiler - and Niklaus Wirth might not throw a curse in us. O dear, now I've dunnit... So the argument against is: (1) split your long functions, because you should; and (2) Wirth didn't do it, so good it is not.

  Even if declaring variables as close as possible to where the variable will be used ( debugging wise not readability wise ) leads to more correct code, the problem is to avoid the temptation to use them in other places too.

  AFAIK, one of Pascal's primary design goals is to won't let you shoot yourself in the foot, and IMO that feature is not in that direction.

Dimitrios Chr. Ioannidis

Reply by email

Paul van Helden
to Dimitrios Chr. Ioannidis

On Wed, Feb 20, 2019 at 4:35 PM Dimitrios Chr. Ioannidis via fpc-devel <

Show quoted text 7 lines
wrote: Even if declaring variables as close as possible to where the variable will be used ( debugging wise not readability wise ) leads to more correct code, the problem is to avoid the temptation to use them in other places too.
Variables declared within a begin...end cannot be used elsewhere. (E.g. for
var I:=0 to .. won't let you use I after the loop).
AFAIK, one of Pascal's primary design goals is to won't let you shoot yourself in the foot, and IMO that feature is not in that direction.

I'd like to see an example how this is less safe.

Reply by email

Marco van de Voort
to Paul van Helden: On Wed, Feb 20, 2019 at 3:52 PM Sven Barth via fpc-devel < Now I'm curious. Can you point…

(sorry for the pm, Paul, should have gone to list)

Op 2/20/2019 om 3:32 PM schreef Paul van Helden:

Show quoted text 15 lines
On Wed, Feb 20, 2019 at 3:52 PM Sven Barth via fpc-devel < > wrote: Pascal is a language where declaration and use of variables is separated. It makes it easy to see what variables are declared and what type they are. Inline variables mess this up as a variable can be declared somewhere inside the code. Now I'm curious. Can you point me to a resource where Pascal is defined such that the separation of declaration from use is a central tenet? I'm not sure, but I doubt I ever look at the variable declarations to help understand the rest of the code...

I'm not really a Pascal semantics guy, but I'll give it a try:

Pascal is block oriented. At the end of a block is always the opener of a new block (var, type, procedure, begin), encountering these tokens in the wrong are typically a warning that something is wrong.Now what is that marker at the end of an inline variable block ? Afaik there is none. The next can be any statement in any form, and you must disambiguate yourself if a variable declaration is meant or not.

From what I can see Embacadero avoids this by keeping all its examples one line, with the VAR on the same line. But Pascal is not line oriented, so this is also odd.

And keep in mind contrary to C/C++, Pascal is a limited lookahead parser.

So the whole feature reeks of Embacadero's desperation to keep bullet lists for new versions filled to keep people upgrading.

It has nothing to do with language design or better C/C++ syntax (*) or whatever. It is just a quick implementation in the hope to score some points with people that have participated in similar threads in Embarcadero groups. They just did a most minimal quick-and-dirty implementation and tossed on the feature matrix. Please upgrade.

(*) it is strange that people complain about scrolling 1000 lines up to see a declaration, but can effortlessly scan those 1000 lines for possible inline declarations without scrolling up.

Reply by email

Martin Frb
to Paul van Helden: O dear, now I've dunnit... So the argument against is: (1) split your long functions,…
Paul van Helden wrote 14 lines
So the argument against is: (1) split your long functions, because you should; and (2) Wirth didn't do it, so good it is not. Long functions *might* be an indication of bad design, but you know, sometimes I have a long function that doesn't make sense to split. Here is a good article about inline vars: http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html What's not to like about for var I:=0 to Count-1 do.. ? Or var MyDict:=TDictionary<Integer,String>.Create;

1) "for" (and other) loops with a long body also exist. So the problem is still there, if I encounter "i" in the middle of a 1000 line for-loop, I still do not see its declaration. So far, no loss, but no gain either.

2) Nested loops exist. If in the middle of such a 1000 line for-loop, I want to declare another loop, then I need to find a free identifier for that variable.
Today, I can do that by looking at the declaration on top of the procedure (and afaik depending on context, the class fields). With inline declaration, I have to find each of the 10 surrounding for-loops, scattered over a 1000 lines (And that is ignoring any variables declared inline, but not as part of a for-loop). I would say that is definitely worse.
But just my 2 cents.

Now do not tell me that those loops should be refactored, because they are based on your statement that this is not always sensible.

3) As for duck typing:
for var i:= Func1 to Func2 do;

What if that is "QWord to int64(or at some future points changes to that)? What will "i" then be? And why?
Or should that be a compile error? (Probably the best)

Reply by email

Martin Frb
to Paul van Helden: On Wed, Feb 20, 2019 at 4:35 PM Dimitrios Chr. Ioannidis via fpc-devel < Variables…
Paul van Helden wrote 11 lines
On Wed, Feb 20, 2019 at 4:35 PM Dimitrios Chr. Ioannidis via fpc-devel < > wrote:   Even if declaring variables as close as possible to where the variable will be used ( debugging wise not readability wise ) leads to more correct code, the problem is to avoid the temptation to use them in other places too. Variables declared within a begin...end cannot be used elsewhere. (E.g. for var I:=0 to .. won't let you use I after the loop)
for var i:=0 to 9 begin end;

That "i" is declared outside the begin end.

Reply by email

Dimitrios Chr. Ioannidis
to Paul van Helden: On Wed, Feb 20, 2019 at 4:35 PM Dimitrios Chr. Ioannidis via fpc-devel < Variables…

Hi,

Στις 20/2/2019 4:46 μ.μ., ο Paul van Helden έγραψε:

Show quoted text 17 lines
On Wed, Feb 20, 2019 at 4:35 PM Dimitrios Chr. Ioannidis via fpc-devel < > wrote:   Even if declaring variables as close as possible to where the variable will be used ( debugging wise not readability wise ) leads to more correct code, the problem is to avoid the temptation to use them in other places too. Variables declared within a begin...end cannot be used elsewhere. (E.g. for var I:=0 to .. won't let you use I after the loop).   AFAIK, one of Pascal's primary design goals is to won't let you shoot yourself in the foot, and IMO that feature is not in that direction.  I'd like to see an example how this is less safe.

Well one of the answer in the Cantu blog has this ( which I changed to lets say a "real world" relative big function ) :

var arr: array...

function Fuckup: boolean;
var I: Integer;
begin
    <....> 20 lines of code
   for var I := Low(arr) to High(arr) do
     if arr[I]..... then
       break;
   <....> 20 lines of code
   Result := (I <= High(arr));
end;

regards,

Dimitrios Chr. Ioannidis

Reply by email

Unknown author
to Unknown author: I'm interested in starting (or joining) a discussion on the next (*non* backwards…

Well, I asked for discussion, and it was given. Thank you all for your input.

To be clear, although I *literally* wrote the words "non backwards compatible", I did not mean it. I should have said that there should be a new compiler mode to access new features. In Rust, there is the concept of "safe" vs "unsafe" code. "Safe" code is guaranteed to be memory and type safe. For a new Pascal mode, code marked "Unsafe" would merely be code written to compile under any of the currently supported modes.

Someone pointed out that a main goal of Pascal was to keep one from shooting oneself in the foot. It is this spirit that I think should be extended (if possible) to adopt at least the memory safe aspect of Rust. There are other programming constructs unrelated to safety which I think merit examination, also.

I might have time later in the year to work on fleshing out the syntax of a new FPC mode. Perhaps someone who is intimately familiar with the compiler internals can mentor me and guide me to understand where I am wrong, and what lines of thought would be productive. I would be willing to pay for the help.

Regardless, thank you for the discussion.
-James

Reply by email

Nikolai Zhubr
to Sven Barth: Am Mi., 20. Feb. 2019, 12:07 hat Nikolai Zhubr geschrieben: Pascal is a language where…

Hi Sven,

20.02.2019 16:51, Sven Barth via fpc-devel:
[...]

Pascal is a language where declaration and use of variables is separated.

I can understand that a language can (and should) try to follow some aesthetic tradition (which, btw, has already been horribly broken many times, imho, although it is not an excuse for further damage). I can also understand that some immature syntactic sugar might introduce e.g. some ambiguities in parsing valid pascal code or some other specific unwanted problems, and if so, it can probably be demonstrated (to some extent at least, by an example or anyhow), and in such case indeed such new syntax should better be avoided.

However, the above statement about "Pascal as a language..." feels somehow strange. I'd say instead, that "Pascal as a language" was designed to be a tool to get job done efficiently, quickly, with confort, elegance, and superiority.

It makes it easy to see what variables are declared and what type they are. Inline variables mess this up as a variable can be declared somewhere inside the code.

Thats exactly what inline declaration does (when used reasonably): it makes it easy to see what variables are declared and what type they are. Well, at least, I see it as the intended purpose.

I use C++ to earn my living. I know why I'm not a fan of inline variables as I've been biten by them often enough already.

Now it is getting even more curious. Admittedly I don't use C too much (and C++ even less so, approximately never), maybe that is why I do not understand your reasoning. Could you maybe give an example of such problematic inline declaration and its negative effect, in C++ at least? Honestly I can't imagine any.

Thank you,

Regards,
Nikolai

Show quoted text 9 lines
Regards, Sven _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Giuliano Colla
to Nikolai Zhubr

Il 20/02/2019 19:11, Nikolai Zhubr ha scritto:

Show quoted text 5 lines
Now it is getting even more curious. Admittedly I don't use C too much (and C++ even less so, approximately never), maybe that is why I do not understand your reasoning. Could you maybe give an example of such problematic inline declaration and its negative effect, in C++ at least? Honestly I can't imagine any.

Very easy: you read your code written some time before, or someone else's code, you miss the inline declaration, because it's buried in the code, and you mistake the variable with another one previously declared, in the outer scope.

I have just met such a situation: I ported from C++ to Pascal an algorithm for the computation of the kinematics of a Delta Robot, and I was badly bitten.
In that case you are just dealing with X,Y,Z coordinates, and Theta0,Theta1,and Theta2 angles, and you find, in the body of a procedure, some X,Y,Z or Theta which have global scope, and some which are just local to some smaller (but not too small) block and which are redeclared inline. Rather hard to tell them apart. Redeclaring inline an index I, which you'll be then using a lot of times, is the best way to shoot you in the feet. Pascal encourages you to use I,J,K at first, then ii,jj,kk etc.

Moreover, using a modern tool such as Lazarus, you never need to scroll 1000 lines to find a declaration: you just press alt+Up to go to the declaration of the symbol over the cursor, and Ctrl+H to go back to the line of code.

Keeping all declarations separated from code is just good programming practice. Mixing declaration and code is bad programming practice, IMO, and I appreciate Pascal for not supporting it.

Giuliano

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

Reply by email

Nikolai Zhubr
to Martin Frb: 1) "for" (and other) loops with a long body also exist. So the problem is still there, if…

Hi,

20.02.2019 17:56, Martin Frb:

1) "for" (and other) loops with a long body also exist. So the problem is still there, if I encounter "i" in the middle of a

This is correct. Inline declaration will not be able to solve all problems in the galaxy, it could just help to relieve some of them.

Show quoted text 11 lines
1000 line for-loop, I still do not see its declaration. So far, no loss, but no gain either. 2) Nested loops exist. If in the middle of such a 1000 line for-loop, I want to declare another loop, then I need to find a free identifier for that variable. Today, I can do that by looking at the declaration on top of the procedure (and afaik depending on context, the class fields). With inline declaration, I have to find each of the 10 surrounding for-loops, scattered over a 1000 lines (And that is ignoring any variables declared inline, but not as part of a for-loop). I would say that is definitely worse.

You've probably missed that inline declartaion syntax is optional, not mandatory, and is intended to only be used where appropriate.

Show quoted text 7 lines
But just my 2 cents. Now do not tell me that those loops should be refactored, because they are based on your statement that this is not always sensible. 3) As for duck typing: for var i:= Func1 to Func2 do;

I think it is totally different from "normal" inline declarations and I don't like it actually.

Thank you,

Regards,
Nikolai

Show quoted text 9 lines
What if that is "QWord to int64(or at some future points changes to that)? What will "i" then be? And why? Or should that be a compile error? (Probably the best) _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Ozz Nixon
to Nikolai Zhubr: 20.02.2019 16:51, Sven Barth via fpc-devel: [...] I can understand that a language can…

* Just to note there is a choice - not pitching one is better just, there is someone doing it *
There is a choice of course... built using FPC. I wrote ModernPascal. We do not focus on Windows support as much as other platforms FPC is available for. Per grammar, MP2 (current build) was designed to make my efforts for web development much easier...at the time, I was running Apache 2.2 at home, and 2.4 at work, and constantly tripping over the include files for my Apache Mods. (MP2 is now 18 years old, and very flexible with variables) *NO GUI YET* (Lazarus and Delphi are great for that arena).

It can do
function xyz:boolean;
var
   a:byte;
begin
    a:=1;
    result:=(a=1);
end;
It can do
function xyz:boolean;
begin
   var a:=1;
   result:=(a=1);
end;
It also supports extremely short hand - for scripting:
// no program
// no begin
// just:
    var a:=request.getMethod;
    response.write(a);
// no end.

* We do not support Units in the style you expect, Modern Pascal's are imported DLL/SO/Dynlibs, and we do not care to support Generics. Our end-user base is under 1000 right now. But, we work on the product, with the product, etc., every day, 7 days a week, for 18 years. Linux and Mac binaries are on github.com/3fllc/modernpascal/ (windows binary has a bug in it right now - when we upgraded to FPC 3.0.4 *I* broke something and have not found it - but, not a fire as all of my end users are Linux or Mac.) -- tutorial.modernpascal.com for work in progress manual. We am very open to designs, but, MP2 can still run 99% of Turbo Pascal source... except for far, near, int, absolute, etc.

Reply by email

Martin Frb
to Nikolai Zhubr: 20.02.2019 17:56, Martin Frb: This is correct. Inline declaration will not be able to…
Nikolai Zhubr wrote 12 lines
> 2) Nested loops exist. If in the middle of such a 1000 line for-loop, I > want to declare another loop, then I need to find a free identifier for > that variable.  Today, I can do that by looking at the declaration on > top of the > procedure (and afaik depending on context, the class fields). > With inline declaration, I have to find each of the 10 surrounding > for-loops, scattered over a 1000 lines (And that is ignoring any > variables declared inline, but not as part of a for-loop). I would say > that is definitely worse. You've probably missed that inline declartaion syntax is optional, not mandatory, and is intended to only be used where appropriate.

No I haven't...
But if I read someone else's code, I don't know what they did and what not.

Show quoted text 6 lines
> 3) As for duck typing: > for var i:= Func1 to Func2 do; I think it is totally different from "normal" inline declarations and I don't like it actually.

Nice we agree on some point.

Reply by email

Nikolai Zhubr
to Dimitrios Chr. Ioannidis: Στις 20/2/2019 4:46 μ.μ., ο Paul van Helden έγραψε: Well one of the answer…

Hi,

20.02.2019 18:24, Dimitrios Chr. Ioannidis via fpc-devel: [...]

> I'd like to see an example how this is less safe. Well one of the answer in the Cantu blog has this ( which I changed to lets say a "real world" relative big function ) :

How this example is different from e.g. using normally declared "I, J: Integer" and employing "J" as a loop variable? Wouldn't it do the same error anyway?

Thank you,

Regards,
Nikolai

Show quoted text 34 lines
var arr: array... function Fuckup: boolean; var I: Integer; begin <....> 20 lines of code for var I := Low(arr) to High(arr) do if arr[I]..... then break; <....> 20 lines of code Result := (I<= High(arr)); end; regards, -- Dimitrios Chr. Ioannidis _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Nikolai Zhubr
to Giuliano Colla: Il 20/02/2019 19:11, Nikolai Zhubr ha scritto: Very easy: you read your code written some…

Hi,
20.02.2019 21:28, Giuliano Colla:
[...]

Show quoted text 8 lines
I have just met such a situation: I ported from C++ to Pascal an algorithm for the computation of the kinematics of a Delta Robot, and I was badly bitten. In that case you are just dealing with X,Y,Z coordinates, and Theta0,Theta1,and Theta2 angles, and you find, in the body of a procedure, some X,Y,Z or Theta which have global scope, and some which are just local to some smaller (but not too small) block and which are redeclared inline. Rather hard to tell them apart.

Excellent! Such redeclarations should obviously be borbidden. Otherwise it would loose almost the whole point. Java certainly rejects them. And, it is easy to identify and reject such name clashes in this case, because the offending statement (declaration) can clearly be located.

On the other hand, I've been biten plenty by the already existing name clashes like:

   with Button1 do
   begin
     Left := ClientWidth div 2;
     .....

and here nothing can probably be done to help at compiler part, because the statement is perfectly valid despite so obviously erroneous. I've seen some people even prepending "self." to almost any identifier in a desperate attempt to eliminate ambiguities. (And yes, it looked disgusting enough)

Thank you,

Regards,
Nikolai

Show quoted text 15 lines
Redeclaring inline an index I, which you'll be then using a lot of times, is the best way to shoot you in the feet. Pascal encourages you to use I,J,K at first, then ii,jj,kk etc. Moreover, using a modern tool such as Lazarus, you never need to scroll 1000 lines to find a declaration: you just press alt+Up to go to the declaration of the symbol over the cursor, and Ctrl+H to go back to the line of code. Keeping all declarations separated from code is just good programming practice. Mixing declaration and code is bad programming practice, IMO, and I appreciate Pascal for not supporting it. Giuliano

Reply by email

Marcos Douglas B. Santos
to Nikolai Zhubr: 20.02.2019 21:28, Giuliano Colla: [...] Excellent! Such redeclarations should obviously…
PM Nikolai Zhubr wrote 16 lines
[...] On the other hand, I've been biten plenty by the already existing name clashes like: with Button1 do begin Left := ClientWidth div 2; ..... and here nothing can probably be done to help at compiler part, because the statement is perfectly valid despite so obviously erroneous. I've seen some people even prepending "self." to almost any identifier in a desperate attempt to eliminate ambiguities. (And yes, it looked disgusting enough)

So, instead of add more features, I would recommend we fix some ambiguous structure like this.

regards,
Marcos Douglas

Reply by email

Florian Klämpfl
to Paul van Helden: To add a dissenting voice, from someone who has followed FPC development for more than 10…
Paul van Helden wrote
As a big fan of the Pascal language, I'd rather break compatibility and see the language evolve than the stoic attitude of the core devs as seen on this list.

People could change this attitude by contributing to FPC. But very few do constantly with high quality patches. The current FPC devs are simply overloaded with the areas they have to maintain so it is pretty clear that excitement about new features is very low.

Reply by email

Unknown author
to Nikolai Zhubr: 20.02.2019 18:24, Dimitrios Chr. Ioannidis via fpc-devel: [...] How this example is…
Nikolai Zhubr wrote 9 lines
20.02.2019 18:24, Dimitrios Chr. Ioannidis via fpc-devel: [...] >>  I'd like to see an example how this is less safe. > > Well one of the answer in the Cantu blog has this ( which I changed to > lets say a "real world" relative big function ) : How this example is different from e.g. using normally declared "I, J: Integer" and employing "J" as a loop variable? Wouldn't it do the same error anyway?

i think he's pointing out the two instances of

var I

in the code... one at the top and one in the loop... at best that would be a redeclaration defect in the code to me...

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list unless* *a signed and pre-paid contract is in effect with us.*

Reply by email

Unknown author
to Giuliano Colla: Il 20/02/2019 19:11, Nikolai Zhubr ha scritto: Very easy: you read your code written some…
Giuliano Colla wrote
Keeping all declarations separated from code is just good programming practice. Mixing declaration and code is bad programming practice, IMO, and I appreciate Pascal for not supporting it.

this falls in the same line as keeping business logic separate from data :)

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list unless* *a signed and pre-paid contract is in effect with us.*

Reply by email

Nikolai Zhubr
to Unknown author: i think he's pointing out the two instances of var I in the code... one at the top and…

Hi,

20.02.2019 23:56,
[...]

Show quoted text 11 lines
> How this example is different from e.g. using normally declared "I, J: > Integer" and employing "J" as a loop variable? Wouldn't it do the same > error anyway? i think he's pointing out the two instances of var I in the code... one at the top and one in the loop... at best that would be a redeclaration defect in the code to me...

I'd suppose inline redeclaration of an already existing local variable or parameter name should be prohibited. If Embarcadero allows that then they must be quite crazy...

Thank you,

Regards,
Nikolai

Reply by email

Nikolai Zhubr
to Giuliano Colla: Il 20/02/2019 19:11, Nikolai Zhubr ha scritto: Very easy: you read your code written some…

20.02.2019 21:28, Giuliano Colla:
[...]

Moreover, using a modern tool such as Lazarus, you never need to scroll 1000 lines to find a declaration: you just press alt+Up to go to the declaration of the symbol over the cursor, and Ctrl+H to go back to the line of code.

It's a bit like car manufacturer saying, "we've arranged a steering wheel in the trunk but you need not worry, there are third-party extenders allowing to also access it from a driver's seat."

Keeping all declarations separated from code is just good programming practice. Mixing declaration and code is bad programming practice, IMO, and I appreciate Pascal for not supporting it.

Are you really sure? What about:

procedure Test;
var
   a: integer;
   function b(c: integer): integer;
   begin
     b := 10 + 5 * c;
   end;
var
   d: integer;
begin
   d := b(1); a := 2;
end;

What is it if not mixing declaration and code?

Thank you,

Regards,
Nikolai

Giuliano

Reply by email

Nikolai Zhubr
to Florian Klämpfl: People could change this attitude by contributing to FPC. But very few do constantly with…

Hi,

20.02.2019 23:33, Florian Klämpfl:

Show quoted text 10 lines
Am 20.02.19 um 08:36 schrieb Paul van Helden: > As a big > fan of the Pascal language, I'd rather break compatibility and see the > language evolve than the stoic attitude of the core devs as seen on > this list. People could change this attitude by contributing to FPC. But very few do constantly with high quality patches. The current FPC devs are simply overloaded with the areas they have to maintain so it is pretty clear that excitement about new features is very low.

Now this is fair and reasonable, indeed.

I didn't actually intended to trigger such a blowup, just was curious about some possible specific technical reasons for avoiding inline declarations altogether.

Thank you,

Regards,
Nikolai

_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Sven Barth
to gabor: W dniu 2019-02-16 o 23:37, Benito van der Zander pisze: Who cares ininline variables…

Am Mi., 20. Feb. 2019, 20:45 hat gabor geschrieben:

Show quoted text 7 lines
W dniu 2019-02-16 o 23:37, Benito van der Zander pisze: > So are inline variables coming soon? > http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html Who cares ininline variables since we do not have dynamic packages yet

Those are at least on a good way. 3.2 contains many of the adjustments and extensions needed to allow them. My hope is to enable them some time in 3.3.1.

Regards,
Sven

Reply by email

J. Gareth Moreton

On the contrary... I'm all for new features if they gel well with the language, although I try to research and theorise how they can benefit the compiler and the code it generates.  My current patches haven't been as well-received as I had hoped, possibly due to lack of documentation and provable stability etc.  (The biggest one overhauls the x86 Peephole Optimizer by merging 6 passes into 1 for a speed boost of up to 15% on -O3, but some of the individual optimisation routines are more complex as a result, mostly so -O1 and -O2 don't perform worse). I'm wondering now, in the name of project management, if such feature proposals and patches should come with a comprehensive design spec, if not to justify the changes then to at least explain how everything works.

Gareth aka. Kit

On Wed 20/02/19 20:33 , Florian Klämpfl sent:

Paul van Helden wrote 5 lines
As a big fan of the Pascal language, I'd rather break compatibility and see the language evolve than the stoic attitude of the core devs as seen on this list.

People could change this attitude by contributing to FPC. But very few do constantly with high quality patches. The current FPC devs are simply overloaded with the areas they have to maintain so it is pretty clear that excitement about new features is very low.

Reply by email

Ondrej Pokorny

Am 20.02.19 um 21:33 schrieb Florian Klämpfl

Show quoted text 5 lines
> Am 20.02.19 um 08:36 schrieb Paul van Helden: > As a big >/fan of the Pascal language, I'd rather break compatibility and see the /> >/language evolve than the stoic attitude of the core devs as seen on this /> >/list. / People could change this attitude by contributing to FPC. But very few do constantly with high quality patches.

experience is that contributing to FPC compiler development is just a waste of time. 1.) First you have to convince core compiler developers that your idea is good. This usually starts a long discussion with different opinions like this one. (That's why I don't take part in it.) 2.) If you then hear "patches welcome", take your time and send your patch, you often don't get any kind of feedback and your issue report stays open forever. You actually don't know if your patch is just poor quality or if the people who said "patches welcome" said it just to end the discussion and counted on the fact that you would never send a patch.

You wrote the reason yourself:

The current FPC devs are simply overloaded with the areas they have to maintain so it is pretty clear that excitement about new features is very low.

Yes, this is the true excuse that I also accept.

No rant. Just saying how the reality is. As an external contributor, you cannot change anything - and especially not the attitude of core compiler developers. It's just better to be happy with what FPC offers, don't lose your time and the time of FPC core developers with useless discussions about new features, don't lose your time with developing and sending patches, accept features and behavior you don't like and live with them. If you really want to use your feature set, maintain your own personal FPC fork.

Please don't misunderstand me - I want to stress that in the end I do like this attitude of FPC core developers to be very critical about external patches and new features. It could end up in a horrible mess if every idea and every patch is applied. I do like the attitude "if I am not 100% sure about a patch/feature, I don't apply it". I just have to dispute that we (external contributors) can change something.

(Just a note: I regret that Sven withdrew his IfThen compiler intrinsic, though :) )

Ondrej

Reply by email

Unknown author
to Unknown author: Well, I asked for discussion, and it was given. Thank you all for your input. To be…
James wrote 5 lines
Someone pointed out that a main goal of Pascal was to keep one from shooting oneself in the foot. It is this spirit that I think should be extended (if possible) to adopt at least the memory safe aspect of Rust. There are other programming constructs unrelated to safety which I think merit examination, also.

we already have this, don't we? the biggest problem i see is the lack of proper buffer, stack, and heap checking when folks are developing their programs... i mean if you have a 1024byte destination buffer you're going to fill from another buffer, check how much is in the originating buffer before just blindly copying it over to the destination buffer... not checking for things like that is just lazy... hell, deploy with stack and heap checking enabled... slower? really? with today's machines? it doesn't make that much difference, in the long run... the system will still be waiting 95+% of the time for something to do...

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list unless* *a signed and pre-paid contract is in effect with us.*

Reply by email

Florian Klämpfl
to Ondrej Pokorny: Am 20.02.19 um 21:33 schrieb Florian Klämpfl experience is that contributing to FPC…
Ondrej Pokorny wrote 10 lines
Am 20.02.19 um 21:33 schrieb Florian Klämpfl > > Am 20.02.19 um 08:36 schrieb Paul van Helden: > > As a big > >/fan of the Pascal language, I'd rather break compatibility and see the /> >/language evolve than the stoic attitude of the core devs as seen on this /> >/list. / > People could change this attitude by contributing to FPC. But very few > do constantly with high quality patches. experience is that contributing to FPC compiler development is just a waste of time. 1.) First you have to convince core compiler developers that your idea is good.

Well, it is not about ideas but contribution in the sense of maintenance as I mentioned below. So basically bug fixing, release building and testing etc.

The number of unfixed bugs in the bug tracker continuously increases and this is a reason to be very careful with new "ideas". I have also a lot of ideas where I could slap together a half-baken patch (well, actually I often do, most of it is in my private git repository), but finalizing everything and fixing bugs is what's missing.

Reply by email

Ben Grasset
to Benito van der Zander: there is NewPascal with improved memory safety/smart pointers: http://newpascal.org/ I…

On Sat, Feb 16, 2019 at 5:44 PM Benito van der Zander wrote

it can turn out the enumerators are slower than an old school loop

The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent!

Reply by email

Paul van Helden
to Ben Grasset
AM Ben Grasset wrote 13 lines
On Sat, Feb 16, 2019 at 5:44 PM Benito van der Zander wrote > it can turn out the enumerators are slower than an old school loop > The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent! How do you make a (for in) enumerator with a record? I don't use them for

exactly this reason, and they did seem to be another useful language feature that turned out to be poorly implemented by Embarcadero. (Haven't checked with FPC).

Reply by email

Sven Barth
to Paul van Helden
Paul van Helden wrote 19 lines
On Fri, Feb 22, 2019 at 2:35 AM Ben Grasset < > wrote: On Sat, Feb 16, 2019 at 5:44 PM Benito van der Zander < > wrote it can turn out the enumerators are slower than an old school loop The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent!  How do you make a (for in) enumerator with a record? I don't use them for exactly this reason, and they did seem to be another useful language feature that turned out to be poorly implemented by Embarcadero. (Haven't checked with FPC).

Just as you would a class (an object is fine, too, by the way). You can take a look at the testcase here:
https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/tforin25.pp?view=markup

Regards,
Sven

Reply by email

Ben Grasset
to Paul van Helden: exactly this reason, and they did seem to be another useful language feature that turned…
AM Paul van Helden wrote 5 lines
How do you make a (for in) enumerator with a record? I don't use them for exactly this reason, and they did seem to be another useful language feature that turned out to be poorly implemented by Embarcadero. (Haven't checked with FPC).

Here's an example (for FPC) that demonstrates it by implementing the "take-while" pattern:

program TakeWhileExample;
{$mode Delphi}{$H+}{$J-}
{$modeswitch NestedProcVars}
{$ImplicitExceptions Off}
{$PointerMath On}
type
  TSlice<T> = record
  public type
    PT = ^T;
    ArrayType = array of T;
  private
    FFirst, FLast, FCurrent: PT;
    function GetCurrent: T; inline;
  public
    function GetEnumerator: TSlice<T>; inline;
    function MoveNext: Boolean; inline;
    class function TakeWhile(const A: ArrayType; function F(const Val: T):
Boolean): TSlice<T>; static; inline;
    property Current: T read GetCurrent;
  end;
  TTestFunc<T> = function(const Val: T): Boolean;
  function TSlice<T>.GetCurrent: T;
  begin
    Result := FCurrent^;
  end;
  function TSlice<T>.GetEnumerator: TSlice<T>;
  begin
    Result := Self;
    with Result do FCurrent := FFirst - 1;
  end;
  function TSlice<T>.MoveNext: Boolean;
  begin
    Inc(FCurrent);
    Exit((FCurrent <= FLast) and (FFirst  FLast));
  end;
  function Test(const Val: SizeUInt): Boolean; inline;
  begin
    Exit((Val < 50000000));
  end;
  class function TSlice<T>.TakeWhile(const A: ArrayType; function F(const
Val: T): Boolean): TSlice<T>;
  var
    I: SizeUInt;
    X: TTestFunc<T> absolute F;
    //FPC generates slightly better code for the "absolute" way, not sure
why...
  begin
    with Result do begin
      FFirst := @A[0];
      FLast := @A[0];
      for I := 0 to High(A) do
        case X(A[I]) of
          True: Inc(FLast);
          False: Exit();
        end;
    end;
  end;
var
  I, J: SizeUInt;
  Arr: TSlice<SizeUInt>.ArrayType;
begin
  SetLength(Arr, 100000000);
  for I := 0 to 99999999 do Arr[I] := I;
  I := 0;
  J := 0;
  for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do J := I;
  WriteLn(J);
end.

Reply by email

Benito van der Zander
to Ben Grasset

Hi,

The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent!

that's what I do.

But the generated assembly is still worse than an old for loop, because it keeps all the fields of the record in memory.

for example

  for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do J := I;

generates something like this

0000000000401290 488b45f0                 mov -0x10(%rbp),%rax 0000000000401294 488b00                   mov    (%rax),%rax 0000000000401297 488905b22a0300           mov %rax,0x32ab2(%rip)        # 0x433d50 <U_$P$PROJECT1_$$_I>
project1.lpr:75                           J := I; 000000000040129E 488905bb2a0300           mov %rax,0x32abb(%rip)        # 0x433d60 <U_$P$PROJECT1_$$_J>
project1.lpr:74                           for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do
00000000004012A5 488345f008               addq   $0x8,-0x10(%rbp) project1.lpr:69                           begin 00000000004012AA 488b45e8                 mov    -0x18(%rbp),%rax project1.lpr:74                           for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do
00000000004012AE 483b45f0                 cmp    -0x10(%rbp),%rax 00000000004012B2 720a                     jb     0x4012be <main+334> 00000000004012B4 483b45e0                 cmp    -0x20(%rbp),%rax 00000000004012B8 7404                     je     0x4012be <main+334> 00000000004012BA b001                     mov    $0x1,%al 00000000004012BC eb02                     jmp    0x4012c0 <main+336> 00000000004012BE 30c0                     xor    %al,%al 00000000004012C0 84c0                     test   %al,%al 00000000004012C2 75cc                     jne    0x401290 <main+288>

Nearly every line is accessing some memory, when it could keep everything in a few registers. amd64 has 16 registers, but fpc seems to only know three when records are involved

Cheers,
Benito

Ben Grasset wrote 94 lines
On Fri, Feb 22, 2019 at 1:07 AM Paul van Helden < > wrote:  How do you make a (for in) enumerator with a record? I don't use them for exactly this reason, and they did seem to be another useful language feature that turned out to be poorly implemented by Embarcadero. (Haven't checked with FPC). Here's an example (for FPC) that demonstrates it by implementing the "take-while" pattern: program TakeWhileExample; {$mode Delphi}{$H+}{$J-} {$modeswitch NestedProcVars} {$ImplicitExceptions Off} {$PointerMath On} type   TSlice<T> = record   public type     PT = ^T;     ArrayType = array of T;   private     FFirst, FLast, FCurrent: PT;     function GetCurrent: T; inline;   public     function GetEnumerator: TSlice<T>; inline;     function MoveNext: Boolean; inline;     class function TakeWhile(const A: ArrayType; function F(const Val: T): Boolean): TSlice<T>; static; inline;     property Current: T read GetCurrent;   end;   TTestFunc<T> = function(const Val: T): Boolean;   function TSlice<T>.GetCurrent: T;   begin     Result := FCurrent^;   end;   function TSlice<T>.GetEnumerator: TSlice<T>;   begin     Result := Self;     with Result do FCurrent := FFirst - 1;   end;   function TSlice<T>.MoveNext: Boolean;   begin     Inc(FCurrent);     Exit((FCurrent <= FLast) and (FFirst FLast));   end;   function Test(const Val: SizeUInt): Boolean; inline;   begin     Exit((Val < 50000000));   end;   class function TSlice<T>.TakeWhile(const A: ArrayType; function F(const Val: T): Boolean): TSlice<T>;   var     I: SizeUInt;     X: TTestFunc<T> absolute F;     //FPC generates slightly better code for the "absolute" way, not sure why...   begin     with Result do begin       FFirst := @A[0];       FLast := @A[0];       for I := 0 to High(A) do         case X(A[I]) of           True: Inc(FLast);           False: Exit();         end;     end;   end; var   I, J: SizeUInt;   Arr: TSlice<SizeUInt>.ArrayType; begin   SetLength(Arr, 100000000);   for I := 0 to 99999999 do Arr[I] := I;   I := 0;   J := 0;   for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do J := I;   WriteLn(J); end. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

J. Gareth Moreton

I feel like a beginner when I say that I've never used advanced records or enumerators before, or the "for-in" loop.  There's definite room for improvement there though, for sure.

I think the problem with the compiler is that it seeks to keep the record together in concurrent storage.  Storing individual fields in registers is essentially splitting it up, even if everything stays synchronised.  Given that the reference is an offset from %rbp, the compiler will know for sure that the variable is local, so there won't be any problems with multi-threading that prevents a lot of temporary register storage for safety reasons.
It could definitely be an area of research.  There are two possible approaches that I can see... look via the peephole optimiser to see if a variable on the stack can be optimised into a register, or look via the node compiler's second pass (converts nodes into assembly language) to see if a local variable of a record type can have its fields stored in registers.  The latter, while preferred, may be implausible with advanced records because of the methods.

Gareth aka. Kit

On Sat 23/02/19 00:17 , Benito van der Zander sent: Hi,

The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent! 
that's what I do.

But the generated assembly is still worse than an old for loop, because it keeps all the fields of the record in memory.
for example

  for I in TSlice.TakeWhile(Arr, Test) do J := I;

generates something like this

0000000000401290 488b45f0                 mov    -0x10(%rbp),%rax
0000000000401294 488b00                   mov    (%rax),%rax
0000000000401297 488905b22a0300           mov    %rax,0x32ab2(%rip)        # 0x433d50
project1.lpr:75                           J := I;
000000000040129E 488905bb2a0300           mov    %rax,0x32abb(%rip)        # 0x433d60
project1.lpr:74                           for I in TSlice.TakeWhile(Arr, Test) do
00000000004012A5 488345f008               addq   $0x8,-0x10(%rbp)
project1.lpr:69                           begin 00000000004012AA 488b45e8                 mov    -0x18(%rbp),%rax
project1.lpr:74                           for I in TSlice.TakeWhile(Arr, Test) do
00000000004012AE 483b45f0                 cmp    -0x10(%rbp),%rax
00000000004012B2 720a                     jb     0x4012be
00000000004012B4 483b45e0                 cmp    -0x20(%rbp),%rax
00000000004012B8 7404                     je     0x4012be
00000000004012BA b001                     mov    $0x1,%al
00000000004012BC eb02                     jmp    0x4012c0
00000000004012BE 30c0                     xor    %al,%al
00000000004012C0 84c0                     test   %al,%al
00000000004012C2 75cc                     jne    0x401290

Nearly every line is accessing some memory, when it could keep everything in a few registers. amd64 has 16 registers, but fpc seems to only know three when records are involved

Cheers,
Benito 
Am 22.02.19 um 16:51 schrieb Ben Grasset:
On Fri, Feb 22, 2019 at 1:07 AM Paul van Helden wrote:  How do you make a (for in) enumerator with a record? I don't use them for exactly this reason, and they did seem to be another useful language feature that turned out to be poorly implemented by Embarcadero. (Haven't checked with FPC).
Here's an example (for FPC) that demonstrates it by implementing the "take-while" pattern:

  program TakeWhileExample;
  {$mode Delphi}{$H+}{$J-} {$modeswitch NestedProcVars}

{$ImplicitExceptions Off} {$PointerMath On}
type   TSlice = record   public type     PT = ^T;     ArrayType = array of T;   private     FFirst, FLast, FCurrent: PT;     function GetCurrent: T; inline;   public     function GetEnumerator: TSlice; inline;     function MoveNext: Boolean; inline;     class function TakeWhile(const A: ArrayType; function F(const Val: T): Boolean): TSlice; static; inline;     property Current: T read GetCurrent;   end;

    TTestFunc = function(const Val: T): Boolean;
    function TSlice.GetCurrent: T;   begin     Result := FCurrent^;  

end;

    function TSlice.GetEnumerator: TSlice;   begin     Result := Self;

    with Result do FCurrent := FFirst - 1;   end;   function TSlice.MoveNext: Boolean;   begin     Inc(FCurrent);     Exit((FCurrent

Links:
------
[1]
[2]
[3] http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Ben Grasset
to Benito van der Zander: that's what I do. But the generated assembly is still worse than an old for loop, because…

There's not really any way to do what that does with a normal for loop without copying the array though, which is whole point basically.

Here's the actual assembly I get from FPC for "main":

.section .text.n_main,"x"
.balign 16,0x90
.globl PASCALMAIN
PASCALMAIN:
.globl main
main:
.Lc12:
.seh_proc main
pushq %rbp
.seh_pushreg %rbp
.Lc14:
.Lc15:
movq %rsp,%rbp
.Lc16:
leaq -176(%rsp),%rsp
.seh_stackalloc 176
movq %rbx,-136(%rbp)
movq %rdi,-128(%rbp)
movq %rsi,-120(%rbp)
movq %r12,-112(%rbp)
.seh_savereg %rbx, 40
.seh_savereg %rdi, 48
.seh_savereg %rsi, 56
.seh_savereg %r12, 64
.seh_endprologue
call fpc_initializeunits
movq $100000000,-8(%rbp)
leaq RTTI_$P$TAKEWHILEEXAMPLE_$$_def00000014(%rip),%rdx leaq -8(%rbp),%r9
leaq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rcx
movl $1,%r8d
call fpc_dynarray_setlength
movq $-1,%rdx
.p2align 4,,10
.p2align 3
.Lj35:
addq $1,%rdx
movq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax
movq %rdx,(%rax,%rdx,8)
cmpq $99999999,%rdx
jnae .Lj35
xorl %esi,%esi
xorl %ebx,%ebx
leaq P$TAKEWHILEEXAMPLE_$$_TEST$QWORD$$BOOLEAN(%rip),%rax movq %rax,-88(%rbp)
movq $0,-80(%rbp)
movq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax
movq %rax,-56(%rbp)
movq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax
movq %rax,-48(%rbp)
movq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rcx
call fpc_dynarray_high
movq %rax,%rdi
movq $-1,%r12
.p2align 4,,10
.p2align 3
.Lj39:
addq $1,%r12
movq U_$P$TAKEWHILEEXAMPLE_$$_ARR(%rip),%rax
movq (%rax,%r12,8),%rcx
call *-88(%rbp)
testb %al,%al
je .Lj38
addq $8,-48(%rbp)
.p2align 4,,10
.p2align 3
cmpq %r12,%rdi
jnbe .Lj39
.Lj38:
leaq -56(%rbp),%rax
vmovups (%rax),%xmm1
vmovsd 16(%rax),%xmm0
vmovups %xmm1,-32(%rbp)
vmovsd %xmm0,-16(%rbp)
movq -32(%rbp),%rax
subq $8,%rax
movq %rax,-16(%rbp)
jmp .Lj47
.p2align 4,,10
.p2align 3
.Lj46:
movq -16(%rbp),%rax
movq (%rax),%rsi
movq %rsi,%rbx
.Lj47:
addq $8,-16(%rbp)
movq -24(%rbp),%rax
cmpq -16(%rbp),%rax
jnae .Lj52
cmpq -32(%rbp),%rax
je .Lj52
movb $1,%al
jmp .Lj50
.Lj52:
xorb %al,%al
.Lj50:
testb %al,%al
jne .Lj46
call fpc_get_output
movq %rax,%rsi
movq %rbx,%r8
movq %rsi,%rdx
xorl %ecx,%ecx
call fpc_write_text_uint
movq %rsi,%rcx
call fpc_writeln_end
call fpc_do_exit
movq -136(%rbp),%rbx
movq -128(%rbp),%rdi
movq -120(%rbp),%rsi
movq -112(%rbp),%r12
leaq (%rbp),%rsp
popq %rbp
ret
.seh_endproc
.Lc13:

PM Benito van der Zander wrote 153 lines
Hi, The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent! that's what I do. But the generated assembly is still worse than an old for loop, because it keeps all the fields of the record in memory. for example > for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do J := I; generates something like this 0000000000401290 488b45f0 mov -0x10(%rbp),%rax 0000000000401294 488b00 mov (%rax),%rax 0000000000401297 488905b22a0300 mov %rax,0x32ab2(%rip) # 0x433d50 <U_$P$PROJECT1_$$_I> project1.lpr:75 J := I; 000000000040129E 488905bb2a0300 mov %rax,0x32abb(%rip) # 0x433d60 <U_$P$PROJECT1_$$_J> project1.lpr:74 for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do 00000000004012A5 488345f008 addq $0x8,-0x10(%rbp) project1.lpr:69 begin 00000000004012AA 488b45e8 mov -0x18(%rbp),%rax project1.lpr:74 for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do 00000000004012AE 483b45f0 cmp -0x10(%rbp),%rax 00000000004012B2 720a jb 0x4012be <main+334> 00000000004012B4 483b45e0 cmp -0x20(%rbp),%rax 00000000004012B8 7404 je 0x4012be <main+334> 00000000004012BA b001 mov $0x1,%al 00000000004012BC eb02 jmp 0x4012c0 <main+336> 00000000004012BE 30c0 xor %al,%al 00000000004012C0 84c0 test %al,%al 00000000004012C2 75cc jne 0x401290 <main+288> Nearly every line is accessing some memory, when it could keep everything in a few registers. amd64 has 16 registers, but fpc seems to only know three when records are involved Cheers, Benito Am 22.02.19 um 16:51 schrieb Ben Grasset: On Fri, Feb 22, 2019 at 1:07 AM Paul van Helden wrote: > How do you make a (for in) enumerator with a record? I don't use them > for exactly this reason, and they did seem to be another useful language > feature that turned out to be poorly implemented by Embarcadero. (Haven't > checked with FPC). > Here's an example (for FPC) that demonstrates it by implementing the "take-while" pattern: program TakeWhileExample; {$mode Delphi}{$H+}{$J-} {$modeswitch NestedProcVars} {$ImplicitExceptions Off} {$PointerMath On} type TSlice<T> = record public type PT = ^T; ArrayType = array of T; private FFirst, FLast, FCurrent: PT; function GetCurrent: T; inline; public function GetEnumerator: TSlice<T>; inline; function MoveNext: Boolean; inline; class function TakeWhile(const A: ArrayType; function F(const Val: T): Boolean): TSlice<T>; static; inline; property Current: T read GetCurrent; end; TTestFunc<T> = function(const Val: T): Boolean; function TSlice<T>.GetCurrent: T; begin Result := FCurrent^; end; function TSlice<T>.GetEnumerator: TSlice<T>; begin Result := Self; with Result do FCurrent := FFirst - 1; end; function TSlice<T>.MoveNext: Boolean; begin Inc(FCurrent); Exit((FCurrent <= FLast) and (FFirst FLast)); end; function Test(const Val: SizeUInt): Boolean; inline; begin Exit((Val < 50000000)); end; class function TSlice<T>.TakeWhile(const A: ArrayType; function F(const Val: T): Boolean): TSlice<T>; var I: SizeUInt; X: TTestFunc<T> absolute F; //FPC generates slightly better code for the "absolute" way, not sure why... begin with Result do begin FFirst := @A[0]; FLast := @A[0]; for I := 0 to High(A) do case X(A[I]) of True: Inc(FLast); False: Exit(); end; end; end; var I, J: SizeUInt; Arr: TSlice<SizeUInt>.ArrayType; begin SetLength(Arr, 100000000); for I := 0 to 99999999 do Arr[I] := I; I := 0; J := 0; for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do J := I; WriteLn(J); end. _______________________________________________ fpc-devel maillist - _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Jonas Maebe
to J. Gareth Moreton: I feel like a beginner when I say that I've never used advanced records or enumerators…
J. Gareth Moreton wrote
Given that the reference is an offset from %rbp, the compiler will know for sure that the variable is local, so there won't be any problems with multi-threading that prevents a lot of temporary register storage for safety reasons.

Unpacking records could be done if their address is not taken anywhere. The compiler already supports keeping records in registers under the same conditions, but only up to a certain size (two native registers) and only using the same layout as they would have in memory (so no explicit splitting out fields into separate registers).

On x86, it does this less often than on other architectures, because that architecture does not have efficient instructions to extract/insert bits from/into registers. However, one improvement that could be made there in the compiler is to ignore this fact if every field of the record already corresponds to exactly one register.

Jonas

Reply by email

J. Gareth Moreton

Indeed, most of the instructions for bit extracting appeared later for SSE and AVX.  I did find one instruction that works with general-purpose registers, named BEXTR, but it only extracts contiguous bits and requires BMI1.

Gareth aka. Kit

On Sat 23/02/19 10:27 , Jonas Maebe sent:

J. Gareth Moreton wrote 5 lines
Given that the reference is an offset from %rbp, the compiler will know for sure that the variable is local, so there won't be any problems with multi-threading that prevents a lot of temporary register storage for safety reasons.

Unpacking records could be done if their address is not taken anywhere. The compiler already supports keeping records in registers under the same conditions, but only up to a certain size (two native registers) and only using the same layout as they would have in memory (so no explicit splitting out fields into separate registers).

On x86, it does this less often than on other architectures, because that architecture does not have efficient instructions to extract/insert bits from/into registers. However, one improvement that could be made there in the compiler is to ignore this fact if every field of the record already corresponds to exactly one register.

Jonas

Reply by email

Ryan Joseph
to Ben Grasset: On Sat, Feb 16, 2019 at 5:44 PM Benito van der Zander wrote The trick with enumerators is…
On Feb 21, 2019, at 7:34 PM, Ben Grasset wrote: The trick with enumerators is to never make them classes, and use advanced records instead, I've found. This way you avoid the heap allocation and the implicit try/finally. Also make sure you inline the MoveNext and GetCurrent!

Here’s this implicit try/finally block on heap allocation thing again. Can someone please explain this? Some months ago someone complained FPC was doing this on all TObject.Create calls. Is that true?

Regards,
Ryan Joseph

Reply by email

Marco van de Voort
to Ryan Joseph

Op 2019-02-23 om 15:35 schreef Ryan Joseph:

Here’s this implicit try/finally block on heap allocation thing again. Can someone please explain this? Some months ago someone complained FPC was doing this on all TObject.Create calls. Is that true?

Yes.

Reply by email

Ryan Joseph
to Marco van de Voort
On Feb 24, 2019, at 9:14 AM, Marco van de Voort wrote: Yes.

Can it be turned off? I don’t use FPC with exceptions and I don’t even use the RTL usually so I don’t need these. Honestly this should have a mode switch if it’s impacting all code regardless of whether a program actually uses exceptions or not.

Regards,
Ryan Joseph

Reply by email

Marco van de Voort
to Ryan Joseph

Op 2019-02-24 om 15:19 schreef Ryan Joseph:

Show quoted text 5 lines
> On Feb 24, 2019, at 9:14 AM, Marco van de Voort wrote: > > Yes. Can it be turned off?

Not that I know. Maybe $implicitexceptions  off where the class is declared, but I doubt it.

I don’t use FPC with exceptions and I don’t even use the RTL usually so I don’t need these. Honestly this should have a mode switch if it’s impacting all code regardless of whether a program actually uses exceptions or not.

Even then it would not work for already compiled units (including the system ones like TObject.Create)

It is part of the language, people have lived with it over 20 years. If it bothers you, help making exceptions cheaper (table based exceptions/seh)

Reply by email

Jonas Maebe
to Marco van de Voort
Marco van de Voort wrote
It is part of the language, people have lived with it over 20 years. If it bothers you, help making exceptions cheaper (table based exceptions/seh)

They're already working for Linux/i386 and LLVM targets in de debug_eh branch. And of course for Win64 (and Win32 for the most part if you compile a custom compiler).

Jonas

Reply by email

Martin Frb
to Jonas Maebe
Jonas Maebe wrote 9 lines
On 24/02/2019 15:22, Marco van de Voort wrote: > It is part of the language, people have lived with it over 20 years. > If it bothers you, help making exceptions cheaper (table based > exceptions/seh) They're already working for Linux/i386 and LLVM targets in de debug_eh branch. And of course for Win64 (and Win32 for the most part if you compile a custom compiler).

Will there be any efforts to add debug info, so a debugger can find except and finally blocks?
https://bugs.freepascal.org/view.php?id=34881

Or maybe I am missing some existing info?

With the information currently available, switching to seh (as implemented) currently means a degradation of the debugging experience.

Reply by email

Jonas Maebe
to Martin Frb: Will there be any efforts to add debug info, so a debugger can find except and finally…
Martin Frb wrote 15 lines
On 24/02/2019 15:24, Jonas Maebe wrote: > On 24/02/2019 15:22, Marco van de Voort wrote: >> It is part of the language, people have lived with it over 20 years. >> If it bothers you, help making exceptions cheaper (table based >> exceptions/seh) > > They're already working for Linux/i386 and LLVM targets in de debug_eh > branch. And of course for Win64 (and Win32 for the most part if you > compile a custom compiler). > Will there be any efforts to add debug info, so a debugger can find except and finally blocks? https://bugs.freepascal.org/view.php?id=34881 Or maybe I am missing some existing info?

There is a presumably a standard approach for this, which should be investigated by a Windows developer before we try to create our own solution. I don't know what the standard way to handle this with Dwarf-based EH either (maybe the debugger is supposed to parse the EH tables?)

Jonas

Reply by email

Ryan Joseph
to Marco van de Voort: Op 2019-02-24 om 15:19 schreef Ryan Joseph: Not that I know. Maybe $implicitexceptions …
Show quoted text 9 lines
On Feb 24, 2019, at 9:22 AM, Marco van de Voort wrote: Not that I know. Maybe $implicitexceptions off where the class is declared, but I doubt it. > I don’t use FPC with exceptions and I don’t even use the RTL usually so I don’t need these. Honestly this should have a mode switch if it’s impacting all code regardless of whether a program actually uses exceptions or not. Even then it would not work for already compiled units (including the system ones like TObject.Create) It is part of the language, people have lived with it over 20 years. If it bothers you, help making exceptions cheaper (table based exceptions/seh)

I must say that’s disappointing because FPC is usually so good about allowing you to opt into extra features via $modeswitch (one of the reasons I don’t stress about feature bloat like in other languages). I would suggest we make this a compilers switch that is on by default but can be disabled.

Regards,
Ryan Joseph

Reply by email

Martin Frb
to Jonas Maebe: There is a presumably a standard approach for this, which should be investigated by a…
Jonas Maebe wrote 22 lines
On 24/02/2019 15:36, Martin Frb wrote: > On 24/02/2019 15:24, Jonas Maebe wrote: >> On 24/02/2019 15:22, Marco van de Voort wrote: >>> It is part of the language, people have lived with it over 20 >>> years. If it bothers you, help making exceptions cheaper (table >>> based exceptions/seh) >> >> They're already working for Linux/i386 and LLVM targets in de >> debug_eh branch. And of course for Win64 (and Win32 for the most >> part if you compile a custom compiler). >> > Will there be any efforts to add debug info, so a debugger can find > except and finally blocks? > https://bugs.freepascal.org/view.php?id=34881 > > Or maybe I am missing some existing info? There is a presumably a standard approach for this, which should be investigated by a Windows developer before we try to create our own solution. I don't know what the standard way to handle this with Dwarf-based EH either (maybe the debugger is supposed to parse the EH tables?)

Its not that easy.

The best the debugger can do, is to find the entry point of the handlers. e.g.  __FPC_finally_handler
For those there may even be symbols in the debug info, or from the linker..., so given that the debugger only needs to deal with fpc, knowing that name is fine.

The except handlers (only on windows 64) can be gotten by intercepting the entry to a kernel method...

But what can for example not be gotten, is the finally handler. You can intercept __FPC_finally_handler (on 32 bit, there is a similar handler for except), but you do not know where this calls the finally handler. Now of course, __FPC_finally_handler get the address for the actual finally from the SEH info. I do not know if that part is standardized, or if the SEH tables can contain compiler dependent data.

But parsing the SEH tables is problematic too. The debugger would have to know everytime that they change.
With an external debugger like gdb, if this process needs to be controlled by the IDE, then it will be extremely slow. Constantly having to read the SEH info. And having to update dozens of breakpoints. Because as it stands, the debugger needs to have a breakpoint for each and every finally handler that is surrounding the current code. There no longer is a single point.

Well there is: If the debugger can for that, it then needs to have reliable info, thaw will be stable for future fpc versions, on how to parse the arguments of this function, to find the finally handler that will be called.

As long as the format of those arguments are not documented and stable (forward compatible), it will not be practical to intercept for finally.

--------------
On win 64 for "except" this is the case. The code calls the windows api (unwind), and that is documented, so the debugger knows where the address of the except handler is.
The debugger can then set a temp breakpoint, and intercept the except handler.

For finally (and 32 bit except) no kernel method is called.

--------------
Further more / Different issue.
Finally handlers are now subroutines.
That means (if there was no exception) "step over" will step over the entire finally handler. That is not desirable.

I don't think it is possible to tell gdb that this subroutine is part of the same code.
Well maybe, it would have to be tested. Gdb actually always steps-in. And then tests if it needs to step out.
Maybe if the at_pc_low/high would include the finally handler, and there was no separate dwarf function entry, maybe then it would work (though that might break locals, depends on if dwarf_frame info is used by gdb, to unroll the (e/r)bp.

Otherwise at least a concept could be found, that FpDebug could in future use to detect that a finally sub, is not a sub (well worst case fpdebug can look at the mangled name).

--------------
All this is based on what I have seen for win32/64 IIRC there is talk of SEH on other OS? Which may lead to similar issues.

Reply by email

Jonas Maebe
to Ryan Joseph: I must say that’s disappointing because FPC is usually so good about allowing you to…
Ryan Joseph wrote
> On Feb 24, 2019, at 9:22 AM, Marco van de Voort wrote: > It is part of the language, people have lived with it over 20 years. If it bothers you, help making exceptions cheaper (table based exceptions/seh) I must say that’s disappointing because FPC is usually so good about allowing you to opt into extra features via $modeswitch

It's is an inherent part of the "class" feature. Without it, any exception that gets thrown in a constructor (or in any code called by a constructor) will cause memory leaks.

(one of the reasons I don’t stress about feature bloat like in other languages). I would suggest we make this a compilers switch that is on by default but can be disabled.

You can disable these exception frames with {$implicitexceptions off}. If you want to disable it for TObject, you have to recompile the system unit with that switch, since the code for TObject's constructor is inside that unit.
ld never do this.

Jonas

Reply by email

Marco van de Voort
to Florian Klämpfl: Actually, it is only cheaper if no exceptions are raised. Raising an exception is very…

Op 2019-02-24 om 15:40 schreef Florian Klämpfl:

Show quoted text 8 lines
Am 24.02.19 um 15:22 schrieb Marco van de Voort: > > it bothers you, help making exceptions cheaper (table based > exceptions/seh) Actually, it is only cheaper if no exceptions are raised. Raising an exception is very expensive when the table driven approach is used.

I know, but the constructor try finally is not hit that hard under normal circumstances, so that is a case where it would be a netto plus

Reply by email

Martin Frb
to Jonas Maebe: It's is an inherent part of the "class" feature. Without it, any exception that gets…
Jonas Maebe wrote 6 lines
You can disable these exception frames with {$implicitexceptions off}. If you want to disable it for TObject, you have to recompile the system unit with that switch, since the code for TObject's constructor is inside that unit. ld never do this.

Actually use {$implicitexceptions off} on your inherited constructor, and do omit the call to "inherited Create" where it would call TObject.Create.
That assumes, that TObject is the only parent in the RTL (or fpc packages)

But it seems that the current way of protecting the constructor is more costly than needed.
Each constructor (and each parent constructor) has/have a try/except.

The parent constructor should only need this, if they are called directly, but not if they are called via inherited (equals called on the instance).

In fact if I do "ObjIntstance.Create()" an implicit try/except is created. In the except handler is a test, that will skip calling the destructor in this case, meaning there will be no action in the except handler.

The constructor code already tests if it is called on an instance or not, to decide if it needs to call NewInstance.
It could do the same (actually use the very same conditional block) to decide on creating the try/except.

This would reduce the amount of times, that an implicit handler is actually created.

Reply by email

Ryan Joseph
to Jonas Maebe: It's is an inherent part of the "class" feature. Without it, any exception that gets…
On Feb 24, 2019, at 10:48 AM, Jonas Maebe wrote: It's is an inherent part of the "class" feature. Without it, any exception that gets thrown in a constructor (or in any code called by a constructor) will cause memory leaks.

Not very useful if we don’t use exceptions though. :) I still don’t understand why exceptions aren’t enabled with a mode switch like advanced records or type helpers especially considering everyone that uses classes is now paying a price for it (without even knowing!).

> (one of the reasons I don’t stress about feature bloat like in other languages). I would suggest we make this a compilers switch that is on by default but can be disabled. You can disable these exception frames with {$implicitexceptions off}. If you want to disable it for TObject, you have to recompile the system unit with that switch, since the code for TObject's c

How can I test to verify if this works or not? Martin makes it sound like there’s some other considerations for subclasses.

Regards,
Ryan Joseph

Reply by email

Jonas Maebe
to Ryan Joseph
Ryan Joseph wrote 8 lines
> On Feb 24, 2019, at 10:48 AM, Jonas Maebe wrote: > > > It's is an inherent part of the "class" feature. Without it, any exception that gets thrown in a constructor (or in any code called by a constructor) will cause memory leaks. Not very useful if we don’t use exceptions though. :) I still don’t understand why exceptions aren’t enabled with a mode switch like advanced records or type helpers especially considering everyone that uses classes is now paying a price for it (without even knowing!).

Many routines in standard units can raise exceptions. If you use the sysutils unit anywhere, any run time error is also converted into an exception. It's an inherent part of the language and RTL. This is not C++ where the language tries to be both assembler and lisp at the same time.

How can I test to verify if this works or not?

Throw an exception in a constructor, compile with -gh and notice you got yourself a memory leak.

Martin makes it sound like there’s some other considerations for subclasses.

That is not what he said.

Jonas

Reply by email

Michael Schnell
to Jonas Maebe: Unpacking records could be done if their address is not taken anywhere. The compiler…
The compiler already supports keeping records in registers under the same conditions, but only up to a certain size (two native registers) and only using the same layout as they would have in memory (so no explicit splitting out fields into separate registers).

Using record fields as independent variables if appropriate could be a nice very high-level optimization strategy (AFAIK, GNU C does this easily). With X64 architecture and others that have many registers this seems to make a lot of sense, but it also would allow to allocate seldom used fields ion the stack.

-Michael

Reply by email

Anton Shepelev
to Sven Barth: Am Mi., 20. Feb. 2019, 12:07 hat Nikolai Zhubr geschrieben: Pascal is a language where…

Sven Barth:

Show quoted text 7 lines
Pascal is a language where declaration and use of variables is separated. It makes it easy to see what variables are declared and what type they are. Inline variables mess this up as a variable can be declared somewhere inside the code. I use C++ to earn my living. I know why I'm not a fan of inline variables as I've been biten by them often enough already.

I agree for my own reasons.

As Wirth himself pointed out in the title of a book, programs comprise two conceptually separate parts: data structures and algorithms that work on them. The separation of variable declaration and their use follows this view, so that every Pascal routine has a data declaration/definition section and an executable begin..end block. This beautiful concept forms a cornerstone of all Wirth languages and is certainly worth keeping.

I find code with intermixed variable declarations less readable because the declaraions no longer stand out but are buried within imperative statements. In order to navigate to a variable declaration from the point of its use other than the first one, the reader must scan the whole subprogram upwards, rather than the small declaration section.

Intermixed variable declarations harm perception. When reading an algorithm, I am focused on what it does. Whenever I encounter a new variable declared in the middle of a function body, I have to perform a mental context switch and update the data model associated with the algorithm.

Whenever the programmer grows annoyed of jumping to the declaration section and back to code, he knows it is time to cut his spaghetti into more manageable parts.

Inline variables are simply ugly, disrupting the aesthetical rhythm of code:

  a := a + Func1( b );
  int b := Func2( a );
  a := a - Func3( b );

Also worth reference are Bart's thoughts on the subject, in two parts:

http://al.howardknight.net/msgid.cgi?ID=155215407800 http://al.howardknight.net/msgid.cgi?ID=155215418300

Please, do not turn Pascal into another C# or Java.

Please, do not forward replies to my e-mail.

Reply by email

Nikolai Zhubr
to Anton Shepelev

Hi,

09.03.2019 21:06, Anton Shepelev:
[...]

> Pascal is a language where declaration and use of > variables is separated. It makes it easy to see what

[...]

Show quoted text 9 lines
a := a + Func1( b ); int b := Func2( a ); a := a - Func3( b ); Also worth reference are Bart's thoughts on the subject, in two parts: http://al.howardknight.net/msgid.cgi?ID=155215407800 http://al.howardknight.net/msgid.cgi?ID=155215418300

In short, if you let me, the all so lengthy and endless reasons boil down to approx these simple 3:

1. It might let people write ugly, horid, unreadable, unreliable code.
2. It might require you to scan some lines up to see the declaration.
3. Name clashes are possible (if implemented and/or used incorrectly).

And regarding all these: yes, as it is now, no much more, no much less.

No one would decide to declare "x", "y" in a declaration section and separately "z" somewhere deep in the body if "x, y, z" are actually coordinates of a point, unless s/he does that on a sole purpose of intentionally mocking colleagues and producing LOLs.

Its pretty odd to deny nowadays that block-local declarations do have their valid use and work just fine, if used reasonably. I'll certainly continue using them, where appropiate (in Java). Also I'll certainly continue using FPC because it is an absolutely brilliant and efficient product anyway with apparently no real-world alternative except just Java. On the other hand, Java's syntax is not as descriptive and has some ugliness in parts (and it hurts my eyes plenty). Therefore, my initial question was out of a (real-world motivated) curiosity regarding how (and why) declarations would ideally be better arranged so as to achive readability and reliability in various cases, considering both C's approach, Java's approach and maybe Embarcadero's approach, however as just a reference, not a requirement for immediate implementation "just because they all have it". So far I've only got the abovementioned cases 1-3 which are in fact irrelevant. Plus a general "declaration and use is separated" mantra which I fail to find sufficiently enlightening either. Well, ok. It is not a showstopper. At least not until a typical function gets 10000 lines long (which I try to resist :) ).

Thank you,

Regards,
Nikolai

Please, do not turn Pascal into another C# or Java.

Reply by email

Unknown author
to Anton Shepelev: Sven Barth: I agree for my own reasons. As Wirth himself pointed out in the title of a…
Anton Shepelev wrote
Whenever the programmer grows annoyed of jumping to the declaration section and back to code, he knows it is time to cut his spaghetti into more manageable parts.

BINGO! give this man a cigar!

FWIW: this annoyance at jumping back and forth is also a sign of laziness and not doing the job properly :lol:

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list unless* *a signed and pre-paid contract is in effect with us.*

Reply by email