Recent

Author Topic: FPC Unleashed (inline vars, statement expr, tuples, match, indexed/lazy labels)  (Read 27712 times)

440bx

  • Hero Member
  • *****
  • Posts: 6382
Thank you Fibonacci.  I'm pleased to see that explicit type declaration is supported.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
FpDebug: block-scoped locals fixed

FpDebug now properly shows block-scoped local variables in the "Local Variables" window - just like GDB does.

This is an IDE-side fix, so you need the Unleashed version of Lazarus, not just FPC. The Unleashed package = FPC + Lazarus. FPC brings new features, and Lazarus is catching up with proper support (autocomplete, FpDebug) :)

Test code

Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. procedure main;
  4. var
  5.   g: integer = 9;
  6. begin
  7.   begin
  8.     var i := 1;
  9.     var a := 33;
  10.     writeln(i);  // breakpoint here
  11.   end;
  12.  
  13.   begin
  14.     var i := 2;
  15.     var b := 44;
  16.     writeln(i);  // breakpoint here
  17.   end;
  18. end;
  19.  
  20. begin
  21.   main;
  22. end.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
New feature: Multi-variable initialization

Initialize multiple variables of the same type with a single value. Works in var sections, typed constants, and inline var declarations. Gated by {$modeswitch multivarinit}, on by default in unleashed mode.

var sections

Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. var
  4.   a, b, c: integer = 42;
  5.   ok, done: boolean = false;
  6.   s1, s2: string = 'hello';
  7.  
  8. procedure Test;
  9. var
  10.   x, y, z: integer = 10;
  11. begin
  12.   writeln(x, ' ', y, ' ', z); // 10 10 10
  13. end;

Each variable gets its own independent copy. Changing one does not affect the others.

Typed constants

Code: Pascal  [Select][+][-]
  1. type
  2.   TPoint = record x, y: integer; end;
  3.  
  4. const
  5.   MinX, MinY, MinZ: integer = 0;
  6.   Origin, Default: TPoint = (x: 0; y: 0);

Inline variables

Works with both explicit type and type inference:

Code: Pascal  [Select][+][-]
  1. procedure Test;
  2. begin
  3.   var p, q: integer := 99;
  4.   var i, j := 4;           // both LongInt
  5.   var s1, s2 := 'hello';   // both String
  6. end;

The initializer expression is evaluated once, then assigned to each variable. A function call on the right side executes exactly once:

Code: Pascal  [Select][+][-]
  1. function Init: integer;
  2. begin
  3.   writeln('Init called');
  4.   result := 42;
  5. end;
  6.  
  7. procedure Test;
  8. begin
  9.   var a, b, c := Init; // Init called once
  10.   writeln(a, ' ', b, ' ', c);
  11. end;
  12.  
  13. // output:
  14. //   Init called
  15. //   42 42 42

IDE support

Lazarus CodeTools updated to parse multi-variable typed constants, so code completion works for all names in the list.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Fred vS

  • Hero Member
  • *****
  • Posts: 3882
    • StrumPract is the musicians best friend
New feature: Multi-variable initialization

 ;D
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

440bx

  • Hero Member
  • *****
  • Posts: 6382
New feature: Multi-variable initialization

 ;D
BIG +1 to that 1.  ;D

If only this simple and logical feature could make it into the mainstream FPC... (I guess the first thing to do is to hope for a release first... then maybe other things.)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

creaothceann

  • Sr. Member
  • ****
  • Posts: 335
Could this also be done outside of initializations? I.e. whenever several variables are set to the same value.

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
Could this also be done outside of initializations? I.e. whenever several variables are set to the same value.

That's a good idea, will do.
« Last Edit: April 09, 2026, 10:40:41 am by Fibonacci »
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
Update: Assign to multiple variables at once

Following up on @creaothceann's suggestion - you can now assign one value to multiple existing variables in a single statement:

Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. procedure test;
  4. var
  5.   i, c, z: integer;
  6. begin
  7.   i, c, z := 5;
  8.   writeln(i, ' ', c, ' ', z); // 5 5 5
  9. end;

This extends the existing multivarinit feature, which covered declarations (var a, b := 4). Now the same works for plain assignments to already-declared variables.

The right-hand side is evaluated once, then assigned to each target. A function call executes exactly once:

Code: Pascal  [Select][+][-]
  1. var
  2.   counter: integer = 0;
  3.  
  4. function next: integer;
  5. begin
  6.   inc(counter);
  7.   result := counter * 10;
  8. end;
  9.  
  10. procedure test;
  11. var
  12.   a, b, c: integer;
  13. begin
  14.   a, b, c := next; // called once
  15.   writeln(a, ' ', b, ' ', c);
  16.   writeln('calls: ', counter);
  17. end;
  18.  
  19. // output:
  20. //   10 10 10
  21. //   calls: 1

Gated by {$modeswitch multivarinit}, on by default in unleashed mode.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

440bx

  • Hero Member
  • *****
  • Posts: 6382
I have a simple feature request: consider r1, r2 and r3 to be records, currently FPC allows this:
Code: Pascal  [Select][+][-]
  1. with r1, r2, r3, r1, r2, r3, r1, r2, r3, r1, r2, r3, r1, r2, r3 do
  2. begin
  3. end;
  4.  
where the scope identifiers can be duplicated a number of times which can potentially make which scope is active unclear.  I think it would be nice if the compiler checked that there are no duplicates in the "with" list and if a duplicate is found, emit an error message and refuse to compile the code.

Of course, in this example, there are three records but, that should apply to any number of records.



ETA:

the Update: Assign to multiple variables at once is currently missing in the "What's New" found in the first post.
« Last Edit: April 10, 2026, 07:39:28 am by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
I have a simple feature request: consider r1, r2 and r3 to be records, currently FPC allows this:
Code: Pascal  [Select][+][-]
  1. with r1, r2, r3, r1, r2, r3, r1, r2, r3, r1, r2, r3, r1, r2, r3 do
  2. begin
  3. end;
  4.  
where the scope identifiers can be duplicated a number of times which can potentially make which scope is active unclear.  I think it would be nice if the compiler checked that there are no duplicates in the "with" list and if a duplicate is found, emit an error message and refuse to compile the code.

Of course, in this example, there are three records but, that should apply to any number of records.

A duplicate check is straightforward for plain symbol references like with r1, r2, r1. For arbitrary expressions (with p^, GetRec(), a[i] do) you'd have to define what "duplicate" even means - syntactic equality? Same underlying object? The latter isn't decidable at compile time. So it's doable but not as trivial as it sounds.

I'll consider the error/warning for the simple case.



the Update: Assign to multiple variables at once is currently missing in the "What's New" found in the first post.

Yeah, I was doing a "bigger redesign" of the first post so it took a bit longer. It's updated now :)
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Khrys

  • Sr. Member
  • ****
  • Posts: 421
I think it would be nice if the compiler checked that there are no duplicates in the "with" list and if a duplicate is found, emit an error message and refuse to compile the code.

Oh, that's a nice one. +1

In my experience,  with  somewhat alleviates the lack of inline variable bindings, so I use it quite extensively (and shot myself in the foot a corresponding number of times).

A duplicate check is straightforward for plain symbol references like with r1, r2, r1. For arbitrary expressions (with p^, GetRec(), a[i] do) you'd have to define what "duplicate" even means - syntactic equality? Same underlying object? The latter isn't decidable at compile time. So it's doable but not as trivial as it sounds.

Check if the accessed identifier appears further down the identifier stack (assuming there is such a thing)?

Code: Pascal  [Select][+][-]
  1. with PointOne do begin
  2.   // X -> PointOne.X {TOP ELEMENT}
  3.  
  4.   with PointTwo do begin
  5.     // X -> PointTwo.X {TOP ELEMENT}
  6.     // X -> PointOne.X
  7.  
  8.     with PointThree do begin
  9.       // X -> PointThree.X {TOP ELEMENT}
  10.       // X -> PointTwo.X
  11.       // X -> PointOne.X
  12.  
  13.       WriteLn(X); // PointThree.X, but X has multiple definitions -> error
  14.     end;
  15.   end;
  16. end;

440bx

  • Hero Member
  • *****
  • Posts: 6382
A duplicate check is straightforward for plain symbol references like with r1, r2, r1. For arbitrary expressions (with p^, GetRec(), a[i] do) you'd have to define what "duplicate" even means - syntactic equality? Same underlying object? The latter isn't decidable at compile time. So it's doable but not as trivial as it sounds.

I'll consider the error/warning for the simple case.
Yes, I would limit the compiler's ability to syntactic equality because, as you stated, there are cases that are not decidable at compile time, therefore the compiler should not be responsible for checking those.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fibonacci

  • Hero Member
  • *****
  • Posts: 891
  • Behold, I bring salvation - FPC Unleashed
Check if the accessed identifier appears further down the identifier stack (assuming there is such a thing)?

Code: Pascal  [Select][+][-]
  1. with PointOne do begin
  2.   // X -> PointOne.X {TOP ELEMENT}
  3.  
  4.   with PointTwo do begin
  5.     // X -> PointTwo.X {TOP ELEMENT}
  6.     // X -> PointOne.X
  7.  
  8.     with PointThree do begin
  9.       // X -> PointThree.X {TOP ELEMENT}
  10.       // X -> PointTwo.X
  11.       // X -> PointOne.X
  12.  
  13.       WriteLn(X); // PointThree.X, but X has multiple definitions -> error
  14.     end;
  15.   end;
  16. end;

That would break a lot of existing code though. Shadowing in with is well-defined and people rely on it. Example:

Code: Pascal  [Select][+][-]
  1. with Pen, Brush do begin
  2.   Color := clRed;   // Brush.Color shadows Pen.Color
  3.   Width := 2;       // Pen.Width - only exists on Pen
  4. end;
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

creaothceann

  • Sr. Member
  • ****
  • Posts: 335
Shadowing can also happen when including units, or with global vs. local identifiers.

The compiler could theoretically show warnings - but some (most?) users would consider it noise, and it'd make compiling slower.

440bx

  • Hero Member
  • *****
  • Posts: 6382
I think it would be nice if the compiler emitted a warning (or note) when a variable or field is shadowed/masked (limited to syntactic matching.)

However, it would affect compilation speed but, it can be implemented in a way that would make the impact fairly small.

I think it would be nice to have it as an _optional_ compilation feature, i.e, the compiler doesn't do it unless instructed to.

Anyway, that's a different feature than simply checking for duplicates in the "with" list.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018