Recent

Author Topic: New language features?  (Read 29779 times)

Warfley

  • Hero Member
  • *****
  • Posts: 2040
Re: New language features?
« Reply #45 on: June 22, 2023, 07:50:25 pm »
This is very strange halfbaken language design, if it is not a bug. I did not know this.
Why should this be a bug? They just don't allow shadowing variables. In the first case there is no collision, because when the second x gets in scope the first one is already out of scope. In the second example you are trying to introduce the second x when the first one is already in scope.

Note that Pascal already does have restrictions on shadowing. While this is completely fine C++ Code:
Code: C  [Select][+][-]
  1. struct Foo {
  2.     int x;
  3.    
  4.     void bar(int x) {
  5.         std::cout << "x: " << x << " this->x: " << this->x << std::endl;
  6.     }
  7. };
  8.  
  9. int main() {
  10.     Foo foo = {.x = 42};
  11.     foo.bar(32); // prints x: 32 this->x: 42
  12.     return 0;
  13. }
It does not translate to Pascal:
Code: Pascal  [Select][+][-]
  1.   TFoo = class
  2.   public
  3.     x: Integer;
  4.  
  5.     procedure Bar(x: Integer); // Error: Duplicate identifier "x"
  6.   end;

The same holds true for local variables:
Code: Pascal  [Select][+][-]
  1.   TFoo = class
  2.   public
  3.     x: Integer;
  4.  
  5.     procedure Bar;
  6.   end;
  7.  
  8. procedure TFoo.Bar;
  9. var
  10.   x: Integer; // Error: Duplicate identifier "x"
  11. begin
  12.  
  13. end;  
This is because Pascal is much stricter on shadowing than other languages. So this isn't a bug, but just consequently applying the rules already in use with respect to shadowing.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6356
  • Compiler Developer
Re: New language features?
« Reply #46 on: June 22, 2023, 10:03:22 pm »
Maybe
Code: Pascal  [Select][+][-]
  1. yList.Sort(with a, b do a < b)
  2.  

with is already used inside code blocks, thus I'll not accept with due to the potential of apparent/potential ambiguities (even if de facto there wouldn't be any).

Or

Code: Pascal  [Select][+][-]
  1. yList.Sort(function a, b do a < b)
  2.  

No. This would be an ambiguous syntax, because function is already used to introduce ordinary anonymous functions.

Another attempt I have seen to solve this without introducing a new variable is by adding a . For the scoping
Code: Pascal  [Select][+][-]
  1. with TButton.Create do
  2. begin
  3.   .Parent := Self;
  4.   .Caption := ButtonCaption;
  5.   ...
  6. end;
This way you can also avoid shadowing by keeping the original essence of the with statement

Please note that Pascal supports multiple expressions as part of the with-header. And nesting is allowed as well. So this wouldn't solve much...

This is because Pascal is much stricter on shadowing than other languages. So this isn't a bug, but just consequently applying the rules already in use with respect to shadowing.

Please note that it's FPC in non-Delphi modes that is stricter here. Delphi (and FPC in mode Delphi) compiles it.

domasz

  • Hero Member
  • *****
  • Posts: 618
Re: New language features?
« Reply #47 on: June 23, 2023, 12:03:07 am »
I am really glad you are the developer. All those ideas above are terrible and totally not in spirit of Pascal. I am glad you won't accept them.

Warfley

  • Hero Member
  • *****
  • Posts: 2040
Re: New language features?
« Reply #48 on: June 23, 2023, 01:49:54 am »
Please note that Pascal supports multiple expressions as part of the with-header. And nesting is allowed as well. So this wouldn't solve much...
Well it solves the majority of problems, because I would reckon that it is very likely that a with statement will be used within a method, while it's very rare to see multi or. Tested with statements.
So something like this would still be an improvement most of the time, even though there are of course still edge cases.

I have had quite some bugs when I accidentally had a ; after the "do" and before the "begin", which is why I've come to be very wary of the with statement. In principle I really like it, especially for things like this:
Code: Pascal  [Select][+][-]
  1. with TStringList.Create do
  2. try
  3.   LoadFromFile(FileName);
  4.   Data := Values[Key];
  5. finally
  6.   Free;
  7. end;
But the fact that it shadows the self methods is always a risk. So while I think this is definitely a good feature in principle, I only really use it when I know that the intersection between the "self" and the withed type.
So it's basically a good feature that's sadly to dangerous to use in many situations

There is a reason why, even though many languages have taken the concept of with, like Visual Basic, Python or even to some extend C# have changed it. Javascript, which had the original version of with, even removed the feature because it is to dangerous, and this is a relay big step, Javascript usually never removes features (e.g. there are still 2 versions of sqrt or min/max in Javascript because it does not want to remove features).

With is an original and core part of Pascal, so we are stuck with it. But it's simply not good. It's simply a relic from the procedural programming style and it was perfectly well fitted for it's time, but today when most of the code happens in a self scope with hundreds of implicitly scoped methods and properties, this is just a situation it was never designed for. So it's often best to just best to just not use it

ASerge

  • Hero Member
  • *****
  • Posts: 2477
Re: New language features?
« Reply #49 on: June 24, 2023, 03:34:29 pm »
...but today when most of the code happens in a self scope with hundreds of implicitly scoped methods and properties, this is just a situation it was never designed for. So it's often best to just best to just not use it
+1

jamie

  • Hero Member
  • *****
  • Posts: 7605
Re: New language features?
« Reply #50 on: June 24, 2023, 03:48:01 pm »
I've don't think I can remember any bugs that took me more than the time it took to write the code miss using a WITH block statement.

 I use the WITH block statement very much and love it.

 However, that being said, there are times where I think the compiler could be miss behaving in some cases seeking tagged names and such, but in that case, it should be reported as a bug.

 The WITH statement is here to stay and I am one of those that like using that sort of construct because it opens the door for the compiler to better optimize it.
The only true wisdom is knowing you know nothing

Warfley

  • Hero Member
  • *****
  • Posts: 2040
Re: New language features?
« Reply #51 on: June 24, 2023, 08:41:36 pm »
I remember one time where I had a component on which I wanted to draw a graph using canvas. To the left of it was a small panel. You could move the graph around and zoom with the mouse. When I ran it there was an offset problem. Because the graphic was not directly aligned to the border, it wasn't immediately obviously that the offset was exactly the width of the border.

Because all the offset translations were a bit more complex code I first thought I did something in the maths wrong an recalculated everything on paper.
The problem was, I was using with to just write canvas.xxx instead of My control.Canvas.xxx, but I had a ; after the do, so I actually drew everything on the form.
Because the component was transparent, so I could see through, and all the other parts of the form were non transparent so it looked like it was only drawn in the correct area.

Took me 30 min to an hour to find it. I know it's always the worst bugs that you keep remembering for so long, I used with countless times without such errors, but I can't help but notice that VB style with, with .Property instead of just Property would have saved me that bug, and it's not at any significant cost of readability, or extended typing effort. That's basically just an improvement in any way
« Last Edit: June 24, 2023, 08:59:19 pm by Warfley »

deadserious

  • New Member
  • *
  • Posts: 25
Re: New language features?
« Reply #52 on: September 14, 2023, 05:26:46 pm »
The separation of declaration and use are sacret to Pascal and for good reason: inline declaration of variables leads to less maintainable code. It is simply a bad feature and I am glad the core dev's decided not to implement this. Not a majority but 100%.

Since all of those also us C an derivatives they are fully aware of writing unmaintainable code, especially in teams. Such a feature is bad squared.

inline variable declaration is important for proper variable scoping, which when used diligently can proactively eliminate a whole class of hard to find bugs. It's also very useful for eliminating needless memory allocations on managed types which can drastically improve performance in some use cases.  The feature was a welcome addition to Delphi and I hope FPC sees their way to inclusion very soon.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12719
  • FPC developer.
Re: New language features?
« Reply #53 on: September 14, 2023, 05:42:12 pm »

inline variable declaration is important for proper variable scoping, which when used diligently can proactively eliminate a whole class of hard to find bugs. It's also very useful for eliminating needless memory allocations on managed types which can drastically improve performance in some use cases.  The feature was a welcome addition to Delphi and I hope FPC sees their way to inclusion very soon.

There are no performance benefits in grown up compilers, as the compiler can limit the scope automatically with liveliness analysis. 

I'm not aware of any class of bugs that gets fixed by it, please elaborate.

Fibonacci

  • Hero Member
  • *****
  • Posts: 793
  • R.I.P. Free Pascal
Re: New language features?
« Reply #54 on: September 14, 2023, 06:34:17 pm »
How much effort would it take to implement inline variables? When I was modifying compiler source to disable/overwrite/mangle/shorten RTTI as much as possible because I so hate it what I saw was codebase so huge, complex, so hard to change, so hard to add a new feature, to extend syntax. Commits on gitlab are mostly little bugfixes for RTL, nothing going on with the compiler itself.

Delphi has them for 5 years.

Quote from: Introducing Inline Variables in the Delphi Language @ November 8, 2018
In other words, while in the past all local variables where visible in the entire code block, now an inline variable is visible only from the position of its declaration and up to the end of the code block.

IDE too would need to be improved to support visibility of these scoped inline variables. IDE still have problems handling anonymous functions implemended over a year ago.

Delphi's inline variables are scoped in nested begin-end blocks, thats complex. I guess it's a huge work to do.

Does FP dev team have such power to make things like that? Not to mention making new features (that just FPC would have), but implement what already brother Delphi has.

Saying "no, becasue this isnt original pascal", "not a standard", "not ISO pascal" are just excuses, but the truth is it is too hard to implement in reasonable amount of time.

inline declaration of variables leads to less maintainable code. It is simply a bad feature and I am glad the core dev's decided not to implement this.

I am really glad you are the developer. All those ideas above are terrible and totally not in spirit of Pascal. I am glad you won't accept them.

Oh the humanity..

I personally see so much opportunities to use inline variable. Sometimes just need one, Im writing fast, testing code, testing things, need one more variable, need other type variable, change type from A to W, and everytime.. scroll up and find them, or hover over, click, but still need to go back to code, so scroll over tens or hundreds lines of code (I use debug breakpoints to mark the line to locate it visually while grabbing scrollbar and looking for where I was, duh).

Bart

  • Hero Member
  • *****
  • Posts: 5706
    • Bart en Mariska's Webstek
Re: New language features?
« Reply #55 on: September 14, 2023, 06:44:49 pm »
Ctrl+Click, change, Ctrl+H and you're back where you started (Lazarus IDE, that is).

Bart

Fibonacci

  • Hero Member
  • *****
  • Posts: 793
  • R.I.P. Free Pascal
Re: New language features?
« Reply #56 on: September 14, 2023, 06:46:39 pm »
Ok you got me here. But still inline variables IMHO are must have.

BTW. Im not exactly where I were, If I add few new lines of variables or add some lines to a record then after Ctrl+H I land few lines lower/higher. But thanks, didn't know about it.
« Last Edit: September 14, 2023, 06:53:13 pm by Fibonacci »

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: New language features?
« Reply #57 on: September 14, 2023, 07:43:34 pm »
How many bold ideas to change the "rules of the road" of the Pascal language.  :o Special thanks to the FPC developers for their reasonable conservatism.  :)

Warfley

  • Hero Member
  • *****
  • Posts: 2040
Re: New language features?
« Reply #58 on: September 14, 2023, 09:31:50 pm »
How much effort would it take to implement inline variables? When I was modifying compiler source to disable/overwrite/mangle/shorten RTTI as much as possible because I so hate it what I saw was codebase so huge, complex, so hard to change, so hard to add a new feature, to extend syntax. Commits on gitlab are mostly little bugfixes for RTL, nothing going on with the compiler itself.

Delphi has them for 5 years.

Probably not too much, I've started the past few weeks playing around in the compiler, and it may look intimidating at first, but once you find out the interesting points, you will quickly find out that even though the code is really cumbersome to read (no casing at all, inconsistent casing between declaration and usage, mixing of german and english identifier names, etc.), it's surprisingly easy to add new language features, at least as long as they mostly concern AST parsing.

For your specific request, just look at the function read_var_decls in pdecvar.pas. It's a giant function, handling all of the different cases (local definition, global definition, procedure variables, etc.), but when you get down to it, the most important bits are actually not that much, first you must create a tlocalvarsym (great no-casing naming, get used to it, sometimes it's interspersed with snake casing, because who needs consistency anyways) and add it to the functions symtable.

Additionally you need to create the code for the assignment within the AST. For this which you can read the right part of the assignment using the "sub_expr" function to generate a tassignmentnode (with the left hand side being a variable access to your newly created symbol). This should also be pretty straight forward when you look at the assignment code in line 4925 of pexpr.pas.

So just adding inline variables should not be that hard. What is probably going to be harder is tracking scopes, for this you would need to keep a chain (linked list) of currently active tstatementnodes (see statement_block function in pstatmnt.pas) and then map visibility within the "searchsym_maybe_with_symoption" function (symtable.pas).

All in all it should be managable to get a proof of concept quite quickly. But then of course, the devil is in the details, e.g. how does this work with generics, how does it work with anonymous functions, etc.

It is quite easy to do add something as a proof of concept, but it of course is much harder to do it right. And of course, you need a lot of tests.

Oh the humanity..

I personally see so much opportunities to use inline variable. Sometimes just need one, Im writing fast, testing code, testing things, need one more variable, need other type variable, change type from A to W, and everytime.. scroll up and find them, or hover over, click, but still need to go back to code, so scroll over tens or hundreds lines of code (I use debug breakpoints to mark the line to locate it visually while grabbing scrollbar and looking for where I was, duh).

As I stated before, requiring scoping for your variables is at most just a hotfix for unreadable code. When you have to jump hundreds of lines of code, your code is to complex.
One of the typical examples for very good code is the Linux kernel, it's probably the best and most consistently structured large code base in existance, and pretty much everyone who has worked with it praises the code quality. And it archives this with ony a few rules, and one strict ruler (Torvalds) who enforces them with an iron fist.
Two of those are, functions should not be larger than 1-2 (console) screens (i.e. ~40 lines), and variables are always declared on the top of the function, which they do voluntarily, even though C allows inline variables, they do not use that feature to have better code.

For example, I've just gone into the kernel source and took a kernel/dma/remap.c file at random, I never saw this file before, I just clicked somewhere. And in this file there are only 4 functions relating to DMA remapping, the longest of which looks like this:
Code: C  [Select][+][-]
  1. /*
  2.  * Remaps an allocated contiguous region into another vm_area.
  3.  * Cannot be used in non-sleeping contexts
  4.  */
  5. void *dma_common_contiguous_remap(struct page *page, size_t size,
  6.                         pgprot_t prot, const void *caller)
  7. {
  8.         int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
  9.         struct page **pages;
  10.         void *vaddr;
  11.         int i;
  12.  
  13.         pages = kvmalloc_array(count, sizeof(struct page *), GFP_KERNEL);
  14.         if (!pages)
  15.                 return NULL;
  16.         for (i = 0; i < count; i++)
  17.                 pages[i] = nth_page(page, i);
  18.         vaddr = vmap(pages, count, VM_DMA_COHERENT, prot);
  19.         kvfree(pages);
  20.  
  21.         return vaddr;
  22. }
Variable definitions on the top, and not more than 14 lines of code.

Of course there are a few exceptions, especially driver code tends to get a bit messy, most of the kernel code looks like this (just go and look for yourself: https://github.com/torvalds/linux/tree/master/kernel).

There is no reason to write giant unreadable functions. If the Linux kernel can have such clean and well structured code, and still be one of the largest and most important software projects in the world, while also having enough performance to power the OS running in billions of devices, then there is no reason why whatever (comparatively) small app you are writing cant.
« Last Edit: September 14, 2023, 09:36:54 pm by Warfley »

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: New language features?
« Reply #59 on: September 14, 2023, 11:41:22 pm »
But still inline variables IMHO are must have.
Inline variables are just another bad idea imported from C.  Particularly the way they are implemented in C and in Delphi (overloading the compound statement construction to also define a scope - a purpose for which it is rather _ill_ suited.)

Just to give a hint about why inline variables are a bad idea: if a language allows inline variables then it should also allow inline types (why would it allow one an not the other ?) and also allow inline constants (same reason.)  By the time you're done, just do away with having to declare the variable(s) beforehand and you end up with "good" old BASIC.  What a way of making progress, going backwards to the gold standard of spaghetti code.

And if someone is going to say I'm exaggerating... I'd like to point out that the argument for inline variables is _convenience_.  I claim it is also very convenient to do away with having to pre-declare variables (but, I'd never claim it's a good idea.)



There is no reason to write giant unreadable functions.
I can definitely agree that there is no good reason to write _unreadable_ functions.

As far as "giant" functions, as long as the function has a well defined purpose, the number of lines it takes to implement it is NOT what will make it easy or hard to understand.   It is much too common to see functions broken into umpteen pieces (for no good reason except: no giant functions because Moses got that rule from a higher power that appeared next to a burning hard drive), that forces the programmer's focus to jump umpteen times (the umpteen functions) to determine how a particular step is done.  Essentially, it is spaghetti code and even worse, since now there are umpteen functions - which are more often than not, not nested in the function that uses it - the programmer has to wonder _where_ else those functions are used (only to figure out that the majority of them are used in only one place) which makes maintenance more difficult and cumbersome.

Maybe in a couple hundred years programming will start going in the right direction.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018