Recent

Author Topic: Ann: Deinline: a de-inline-var-alyzer  (Read 3368 times)

440bx

  • Hero Member
  • *****
  • Posts: 6488
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #15 on: April 12, 2026, 12:34:41 pm »
if anything, the ability to inline the "for" index variable clearly proves how much cleaner the resulting code is than having multiple junk variables declared at the function/procedure global level just to control a loop.

It's amazing, the "for" loop is improved by allowing declaring the index locally then someone writes a utility to undo that improvement.  MIGA (Make Indexes Great Again... <chuckle>)

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

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12345
  • Debugger - SynEdit - and more
    • wiki
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #16 on: April 12, 2026, 01:03:56 pm »
if anything, the ability to inline the "for" index variable clearly proves how much cleaner the resulting code is than having multiple junk variables declared at the function/procedure global level just to control a loop.
Quote
It's amazing, the "for" loop is improved by allowing declaring the index locally

Is it?

And is the for var junk? And if it is, then why have it at all?

While not in favour of the following, but if ....
If the for loop var was junk, then surely it was not needed at all (junk shouldn't be needed) then it should be
Code: Pascal  [Select][+][-]
  1. for start to finish do // no (visible) variable
That would yet be clearer (within the conceived underlaying views that seem to drive this matter). It would state that you want to run it several times, but without having a value that increments (or decrements).

If the variable is used/accessed in the loop, then it should not be junk.




And to be honest, if there is a need to clarify a variable then that should be done by giving it a more meaningful name.  That includes several meaningful names for several variables.

With the inline, you solve nothing. Sure the exceptional "one liner loop" but that is nothing, its not generic. (And over time it wont stay a "one liner")

If you have several loops, then with inline you have to search a dozen or more scopes for which var starts/ends where. Especially if that var then appears in more than one scope...
So bad, that at that point you need to give each of those vars a new meaningful and distinct name anyway => so exactly what one does without inline...  (just without inline, there is no need to track dozens of extra scopes / if there is a real need for scopes, then those are procedures)




creaothceann

  • Sr. Member
  • ****
  • Posts: 361
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #17 on: April 12, 2026, 01:25:11 pm »
And is the for var junk? And if it is, then why have it at all?

It is useful in the loop, it's not really useful outside of the loop. Free Pascal already declares the value to be junk after the loop (if not broken early).


And to be honest, if there is a need to clarify a variable then that should be done by giving it a more meaningful name
i, j, x, y are already commonly used as for loop counters.

And I think nobody is arguing about using meaningful names. All we're arguing is where they are declared.


If you have several loops, then with inline you have to search a dozen or more scopes for which var starts/ends where. Especially if that var then appears in more than one scope...

I don't know what programs people usually handle, but the vast majority of loops I have encountered are nested 1 or 2 levels deep, rarely 3. And the declarations are easy to find, since each for loop body is usually indented by an additional level.

440bx

  • Hero Member
  • *****
  • Posts: 6488
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #18 on: April 12, 2026, 01:26:40 pm »
Loop index variables exist primarily to control the loop and, identify a specific iteration. 

Unlike other local variables that are used throughout the function/procedure, the loop indexes very rarely are useful outside the loop they control.  That's what makes them junk variables, they are usually disposable variables and for that reason they should NOT be function/procedure global.

That's also why declaring them in the "for" itself is an improvement.  That declares the index's usefulness is limited to the statements that are part of the loop and nothing else.  Again, for that reason they should NOT be function/procedure global, because their usefulness and scope is limited.

Making them function/procedure global is a conceptual _error_ UNLESS they happen to be useful _throughout_ the _entire_ function/procedure, not just a few statements that are in a loop and, that is unusual.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #19 on: April 12, 2026, 02:52:07 pm »
Off topic: C-operator removal tool announced ;)
objects are fine constructs. You can even initialize them with constructors.

Fred vS

  • Hero Member
  • *****
  • Posts: 3919
    • StrumPract is the musicians best friend
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #20 on: April 12, 2026, 03:01:10 pm »
Hi Thaddy.

I vote for a de-labelizer (and its goto).
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #21 on: April 12, 2026, 03:03:54 pm »
Hi Thaddy.

I vote for a de-labelizer (and its goto).

Mmmmm, also a good idea, but a whole lot more complex (fpc supports non-local goto's)  :o :D
objects are fine constructs. You can even initialize them with constructors.

Fred vS

  • Hero Member
  • *****
  • Posts: 3919
    • StrumPract is the musicians best friend
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #22 on: April 12, 2026, 03:17:40 pm »
Hi Thaddy.

I vote for a de-labelizer (and its goto).

..., but a whole lot more complex (fpc supports non-local goto's)  :o :D

Yes, I know, I did it for all the label/goto in msegui code because for some operating systems, FPC 3.3.1 had a bug with the label/goto command (which I think has been fixed recently).
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #23 on: April 15, 2026, 10:15:51 am »
Good news, I have a release candidate that also has type inference for known classes, records, objects from the system unit and the complete rtl.
This is implemented as a lookup list in deinlinetypes.pas and can be added to if you want.
The example file is completely solved and most code leaves only few todo's
E.g., the original example file is solved like:
Code: Pascal  [Select][+][-]
  1. program simpleinline;
  2. {$ifdef fpc}{$mode objfpc}{$endif}
  3. uses sysutils,classes;
  4.  
  5. procedure UseSomeInlineVars;
  6. var
  7.   list: TStringlist;
  8.   i: Integer;
  9.   s: String;
  10.   j: Integer;
  11. begin
  12.   list := TStringlist.Create;
  13.   for i := 0 to 10 do
  14.    begin
  15.      s := 'string'+i.toString;
  16.       for j := 0 to 9 do List.Add(Random(100).ToString;
  17.    end;
  18.    writeln(list.text);
  19.    List.free;
  20.    writeln;
  21. end;
  22.  
  23.   UseSomeInlineVars;
  24. end.
That's without human intervention.
It has been tested on a huge Delphi code base.

About its usefulness: the main Freepascal will never have inline vars.
This tool simply corrects the code for you to use in the real Freepascal.
It has no other pretentions.

Happy de-inlining!!!
« Last Edit: April 15, 2026, 10:18:59 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

440bx

  • Hero Member
  • *****
  • Posts: 6488
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #24 on: April 15, 2026, 10:19:28 am »
About its usefulness: the main Freepascal will never have inline vars.
Never say never ;)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #25 on: April 15, 2026, 10:46:35 am »
@440bx
For the time being the fpc release is 3.2.2... :-X
The tool really helps. Try it.
(it also supports things like classes.Tstringlist and such abominalities)
« Last Edit: April 15, 2026, 10:51:53 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

440bx

  • Hero Member
  • *****
  • Posts: 6488
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #26 on: April 15, 2026, 11:31:27 am »
@440bx
The tool really helps. Try it.
While I don't like that inline variables have been implemented the same way as they are in C, generally speaking I like being able to declare variables close to where they are used.  IMO, that enhances locality.

The problem is, the begin/end pairs are lousy scope delimiters and it's obvious they were never intended as such.  That really has a negative impact on what is otherwise a conceptually good feature.
 
The solution to the problem isn't de-inlining, the solution is implementing inline variables _correctly_ which often seems like asking for a square circle in the era of, free-for-all, C derived programming languages.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #27 on: April 15, 2026, 11:48:23 am »
Code: Pascal  [Select][+][-]
  1. var
  2.    i ???
  3. begin
  4.   for var i in Something do
  5.     begin
  6.        // do something
  7.     end;
  8.   for var i in SomethingElse do
  9.     begin
  10.        // do something else
  11.     end;
  12. end;                  
  13.  
That is partly solved but keeps a todo, because I can' t infer i in that case.
Code: Pascal  [Select][+][-]
  1. var
  2.   i: {TODO: add type};
  3. begin
  4.   for i in Something do
  5.     begin
  6.        // do something
  7.     end;
  8.   for i in SomethingElse do
  9.        // do something else
  10. end;
But that can be solved with a renaming pass. Which is not too difficult since I already collect the correct types: only need to resolve the name conflicts in cases where i is used and the types are inferred. That is a corner case, but well worth solving too. It is a corner case: no Delphi code I got from the embarcadero examples used that. It is legal Delphi, so needs a fix? (Basically, yes)

Note this clearly demonstrates the unreadability of inferred inline vars.... You don't know what they mean at any given point in code. Reading, not writing such code.

For other readers: @LeP means that the two different inferred inline var's i are of different types in the same codeblock, e.g. one could be integer the other could be object or whatever.
This is also not solved in the unleashed branch, btw  :) :) (not in my copy)

As always. But the Delphi examples (from the online examples directory) all pass with the premise of everything being rtl.
And before commenting, please read the source. It is not really complex, nor long.

@Martin_fr
It also can not be solved with regexpr otherwise I would have done so.
It needs a proper parser, but you know that.

In general I will leave the code as-is since it passed all delphi examples and it will produce a todo. Punishment for sloppy programmers that write or use sloppy code.

If something and somethingelse are properly defined and are of the same type it resolves.
« Last Edit: April 15, 2026, 02:02:27 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

LeP

  • Sr. Member
  • ****
  • Posts: 304
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #28 on: April 15, 2026, 07:08:42 pm »
Note this clearly demonstrates the unreadability of inferred inline vars.... You don't know what they mean at any given point in code. Reading, not writing such code.
For other readers: @LeP means that the two different inferred inline var's i are of different types in the same codeblock, e.g. one could be integer the other could be object or whatever.
Already reported that in other my post a clear example, and yes if you want make it unreadibility you can ... like other function, expression and code.

But that can be solved with a renaming pass. Which is not too difficult since I already collect the correct types: only need to resolve the name conflicts in cases where i is used and the types are inferred. That is a corner case, but well worth solving too. It is a corner case: no Delphi code I got from the embarcadero examples used that. It is legal Delphi, so needs a fix? (Basically, yes)
You means that use the same inline variables in different scope blocks is not legal ? What do you want from Embarcadero, the inline variables were created for this .... and the rules are clear.
But is better not start another war on this argument, too much time wasted on this. FPC as a clear position, so why criticize what others do?
Un Sistema per domarli, un IDE per trovarli, un codice per ghermirli e nel framework incatenarli.
An operating system to tame them, an IDE to find them, a code to catch them and in the framework chain them.

Thaddy

  • Hero Member
  • *****
  • Posts: 19156
  • Glad to be alive.
Re: Ann: Deinline: a de-inline-var-alyzer
« Reply #29 on: April 16, 2026, 06:37:19 am »
No I mean that rule IS legal, but not encountered nor checked before your example. It is simply not in any of the examples in the embarcadero public repository. Again, I wrote that first i inferred integer and second i inferred class in the same block is legal. It is only that my current parser can not - yet - solve duplicate names for different types. And that is because I did not find that in live code.
The parser won't break on it, but writes a todo, like it does if the class/object/record is not in the rtl.

I made small change that fills in duplicate names with different types anyway, but that also requires manual intervention. e.g
Code: Pascal  [Select][+][-]
  1. var
  2.   i:integer;
  3.   i:string; // no todo, but also does not not compile AOTB.
See if I can fix that on the fly into:
Code: Pascal  [Select][+][-]
  1. var
  2.   i:integer;
  3.   i1:string;

That requires a rename in the body too. Since I have depth and scope, that would be possible without large changes to the parser.
« Last Edit: April 16, 2026, 07:38:11 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018