Recent

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

Thaddy

  • Hero Member
  • *****
  • Posts: 19165
  • Glad to be alive.
I agree with 440bx that writable constants are really static variables.
Hence my macro. (which is very, very old, not from today, and published here before)

But if it is solved in the compiler it has my blessing: that was an unfortunate decision by a certain Borland guru back in the years.
objects are fine constructs. You can even initialize them with constructors.

440bx

  • Hero Member
  • *****
  • Posts: 6490
So if I understand correctly, what you want is: typed constants should be actual constants (not writable), and a new keyword like static would take over the role of what "writable typed constants" do today? Something like:

Code: Pascal  [Select][+][-]
  1. // before:
  2. procedure Foo;
  3. const
  4.   counter: Integer = 0;
  5. begin
  6.   Inc(counter);
  7. end;
  8.  
  9. // proposed behavior with static:
  10. procedure Foo;
  11. static
  12.   counter: Integer = 0;
  13. begin
  14.   Inc(counter);
  15. end;
  16.  
  17. // proposed behavior with const:
  18. procedure Foo;
  19. const
  20.   counter: Integer = 0;
  21. begin
  22.   Inc(counter); // throw an error
  23. end;
  24.  
Almost.  I would keep the current compiler behavior as far as "const" goes, this to keep compatibility.  IOW, the addition of "static" should not change anything at all as far as how "const" is currently treated.  This means the third "Foo" would throw an error only when writable constants are off, it wouldn't throw an error if they are on.  "Static" is an alternative syntax that has no effect on how the compiler treats "const".  To make this even clearer: if the programmer, for some reason I cannot fathom, wants to use _both_ writable constants and the new "static" keyword, he/she should be allowed to do that (extremely poor programming but it ensures compatibility with the existing code base.)

The proposed/second "Foo" is great.

As far as the usage of "absolute", what I meant is to allow "absolute" in the "static" section.  For instance:
Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. procedure test;
  4. static
  5.   x: integer = 1;
  6.   a: integer absolute x;
  7. begin
  8.   writeln('a (absolute of x) = ', a);
  9.   inc(x);
  10. end;
  11.  
IOW, it should be possible to "absolute" a static variable immediately after its declaration.  The reason for that is, "absolute" is an alias and it is often critical for the programmer to be aware of variable aliasing, having the alias immediately after the declaration of the original variable makes it much more unlikely that the aliasing will be overlooked/missed.

If needed, it will be my pleasure to clarify anything else about the feature and...

Thank you for considering it.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

creaothceann

  • Sr. Member
  • ****
  • Posts: 361
How about keeping the var keyword (since these are variables), but adding the static as an attribute, like the "inline" attribute for subroutines or the "absolute xyz" attribute for variables?

Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. procedure Proc;
  4. var
  5.         first : static boolean = True;    // syntax version 1
  6.         first : boolean = True;  static;  // syntax version 2
  7. begin
  8.         if first then begin  // init?
  9.                 first := False;
  10.                 // do init
  11.         end;
  12. end;

440bx

  • Hero Member
  • *****
  • Posts: 6490
How about keeping the var keyword (since these are variables), but adding the static as an attribute, like the "inline" attribute for subroutines or the "absolute xyz" attribute for variables?
Technically, I believe that would work. 

Personally, I prefer to make the fact that a variable is static more evident/visible and, for this reason, I favor a separate "static" section.

Also, I prefer the word "persistent" instead of "static" as it more clearly describes the variable's behavior but, "static" has the advantage of being well known as a result of being used in C and its derivatives.

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

Fibonacci

  • Hero Member
  • *****
  • Posts: 949
  • Behold, I bring salvation - FPC Unleashed
Personally, I'd prefer the var section approach as well - what @creaothceann suggested. Declaring these in var with an attribute makes the most sense to me, since they really are variables with static storage.

And here's the bonus: this naturally extends to inline variable declarations too:

Code: Pascal  [Select][+][-]
  1. var x: Integer = 1; static;
  2.  

or even shorter with type inference:

Code: Pascal  [Select][+][-]
  1. var x := 1; static;
  2.  

As for absolute - that can be added to inline vars too:

Code: Pascal  [Select][+][-]
  1. var x: Integer := 1;
  2. var a: TMyRec absolute x;
  3.  

Now, about the keyword itself - static, persistent, or keep?

I'd go with either static or keep. Both are short, easy to type, and immediately clear in meaning. persistent is descriptive but annoying to type (and easy to mistype) - not a great quality for a keyword you'll use regularly. Between the two, static has prior art in C/C++ and maps to the exact same concept. keep is a fresh alternative if we want to avoid the C baggage. Either way, both are better than persistent purely from a practical standpoint.
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: 6490
Personally, I strongly prefer clarity over typing convenience, for this reason I prefer persistent because it is the one that best describes the variable's behavior and since it is longer it is less likely to be overlooked.

That said, since you're the one implementing the feature, you have the advantage in making the decision ;)

I have a concern about using "static", I believe that word is used someplace else too, don't remember where but, if that's correct, using it to create persistent variables might lead to ambiguities.

« Last Edit: April 12, 2026, 01:23:46 am by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fibonacci

  • Hero Member
  • *****
  • Posts: 949
  • Behold, I bring salvation - FPC Unleashed
Don't worry - the keyword will be syntax-highlighted by the IDE just like any other reserved word, so there's no risk of overlooking it regardless of its length ;)
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

ccrause

  • Hero Member
  • *****
  • Posts: 1117
How about keeping the var keyword (since these are variables), but adding the static as an attribute, like the "inline" attribute for subroutines or the "absolute xyz" attribute for variables?

Code: Pascal  [Select][+][-]
  1. {$mode unleashed}
  2.  
  3. procedure Proc;
  4. var
  5.         first : static boolean = True;    // syntax version 1
  6.         first : boolean = True;  static;  // syntax version 2
  7. begin
  8.         if first then begin  // init?
  9.                 first := False;
  10.                 // do init
  11.         end;
  12. end;

Note the current Pascal rules for declaring variables. The current situation is that a variable modifier either follows immediately after the type and optional expression (only the absolute modifier], or after a semicolon.  The use of a semicolon in my opinion is unnecessary (perhaps even inconsistent) since it is used generally to separate statements.  I consider modifiers as part of the variable declaration and therefore should not be separated from the preceding declaration by a semicolon.

That said, note that syntax version 1 does not fit into the current variable declaration rules.  My only request is that the Pascal language is not further polluted with arbitrary syntax,

ccrause

  • Hero Member
  • *****
  • Posts: 1117
Also, I prefer the word "persistent" instead of "static" as it more clearly describes the variable's behavior but, "static" has the advantage of being well known as a result of being used in C and its derivatives.

While I agree from an English language perspective, in data handling circles persistence refers to data storage outside of the process. Typically storage to file or database (e.g. tiOPF).

MarkMLl

  • Hero Member
  • *****
  • Posts: 8572
Inline variables do _not_ violate Pascal's intended form.  Proof of that is visible everywhere in the language, e.g, nested functions/procedure allow the programmer to create another group of variables and, there is no limit established by the language in the number of them.

The real problem is not the inline variables, the real problem is misusing the begin/end (compound statement) construction as a scoping structure ...

I agree. As I've said earlier, the introduction of a function (etc.) header introduces a new scope, which applies until the end of the statement(s) that follow it.

Quote
... which it was _obviously_ never meant to be.

That intention is arguable IMO. Pascal got to where it currently is because earlier implementors didn't mark the stack (AKA create a new stack frame) every time they encountered begin. That is, however, an implementation detail.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

creaothceann

  • Sr. Member
  • ****
  • Posts: 361
I prefer the word "persistent" instead of "static" as it more clearly describes the variable's behavior but, "static" has the advantage of being well known as a result of being used in C and its derivatives.

"static" is already used for static fields (and static methods), so it would make sense.


Note the current Pascal rules for declaring variables. The current situation is that a variable modifier either follows immediately after the type and optional expression (only the absolute modifier], or after a semicolon.  The use of a semicolon in my opinion is unnecessary (perhaps even inconsistent) since it is used generally to separate statements.  I consider modifiers as part of the variable declaration and therefore should not be separated from the preceding declaration by a semicolon.

Speaking of attributes (called modifiers for subroutines), there's also the syntax for property specifiers which uses no semicolon between type, index, read and write. And then there's the default attribute, which follows after the semicolon...


That said, note that syntax version 1 does not fit into the current variable declaration rules.

I only included it because "static boolean" sounds nice... But it would probably look worse with multiple attributes.


[...] in data handling circles persistence refers to data storage outside of the process.

One could argue that a variable with this attribute is located outside (of the subroutine).

I just remembered that Free Pascal has another concept for the storage of variables: threadvar. This creates 3 types of regions:

Code: [Select]
var               in subroutines  -->  local stack frame
var       outside of subroutines  -->  global data (.bss / .data segment)
threadvar outside of subroutines  -->  global data (.bss / .data segment) for each thread

So as an alternative to a "var" block with the "static" attribute, we could introduce the globalvar block. It would work like a global var block, except that the variables declared in it are only known to the subroutine.
« Last Edit: April 12, 2026, 10:25:53 am by creaothceann »

440bx

  • Hero Member
  • *****
  • Posts: 6490
I've read everyone's view on what the name of the feature should be and, I still prefer persistent, second choice would be static because it is already known (maybe) to programmers familiar with C and C++, which I believe is a large percentage of programmers but, the word "static", unlike "persistent" does not really indicate that the variable's existence is independent of the scope in which it is declared.

persistent is the semantically logical choice.

Another possibility that comes to mind is owned denoting that it resides in global storage but it is owned by the function/procedure in which it is declared.  I still prefer persistent.


ETA:

For the record, even calling it mxyzptlk beats anything that is associated with "writable constants" ;)

« Last Edit: April 12, 2026, 11:03:31 am by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

ccrause

  • Hero Member
  • *****
  • Posts: 1117
I just remembered that Free Pascal has another concept for the storage of variables: threadvar. This creates 3 types of regions:

Code: [Select]
var               in subroutines  -->  local stack frame
var       outside of subroutines  -->  global data (.bss / .data segment)
threadvar outside of subroutines  -->  global data (.bss / .data segment) for each thread

So as an alternative to a "var" block with the "static" attribute, we could introduce the globalvar block. It would work like a global var block, except that the variables declared in it are only known to the subroutine.

True.  So two options for indicating the semantics.  This is a decision that is IMHO more important than what to call this specific feature, since it determines the syntax of other similar potential features.

A somewhat similar new* feature (specific to AVR target) is to specify storage of variables (flash/program memory, EEPROM, default is to load all data into RAM).  Here the decision was taken to specify the storage location as a modifier/attribute since this allowed passing this information into subroutines by allowing the section modifier as optional for parameter declaration, which has a potential knock-on effect on code generation inside the subroutine. 

In contrast to this, the AVRco Pascal compiler implements a similar feature by using a memory page concept that is set by the user declaring a pragma with the memory page name before the global var block.  This compiler also supports a bunch of other features that overlap somewhat with FPC/Delphi Pascal but with incompatible syntax.

My only point with this is that the syntax of a feature should not be an arbitrary decision, it should fit in with some overall syntax philosophy that allows future extensions without changes to the basic syntax.

* New because it isn't merged, the proposal is not new.

440bx

  • Hero Member
  • *****
  • Posts: 6490
Strictly speaking, in Pascal, a variable's lifespan should not be controlled by a modifier.  In Pascal, a different lifespan should imply a different declaration section.  That's the reason there is a separate "type" section, a "const" section and a "var" section. 

In a function/procedure, the "var" section is supposed to consist of all the variables that exist in the scope of the function/procedure.  if some value is supposed to persist then it should NOT be declared in the "var" section, it should be declared in its own section. 

This allows the programmer who is reading code to see a distinct pattern that provides information.  For instance, in the code:
Code: Pascal  [Select][+][-]
  1. type
  2.   TSOMETYPE = record
  3.     SomeField   : boolean;
  4.   end;
  5.  
  6. const
  7.   ACONSTANT     = 3;
  8.  
  9. static
  10.   SomeName      : integer = 0;
  11.   SomeotherName : array[1..4] of char absolute SomeName;
  12.  
  13. var
  14.   Local1, Local2, Local3 : single = 1.0;
  15.   Small                  : boolean = false;
  16.  
  17. begin
  18.   <statements>
  19. end;
  20.  
In the above code there are 4 distinct, easily identifiable sections and, the presence of each section gives instant information to the programmer such as, are static variables used in the function/procedure.  If  static is just an attribute in the "var" section, the programmer's mind has to parse and read the entire "var"  section to find out if static vars exist instead of simply recognizing a pattern.

That's also the reason why begin/end are _lousy_ scope delimiters because they mix a construct that is meant to create a group of statements (the compound statement) with the creation of a scope.  Functions/Procedures are scope delimiters, not compound statements.  Anyway, since Delphi copied that dismally poor design from C, it is a given that it will be perpetuated in FPC.

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

creaothceann

  • Sr. Member
  • ****
  • Posts: 361
Strictly speaking, in Pascal, a variable's lifespan should not be controlled by a modifier.

I wonder if there is a rule for that defined somewhere?

Technically Free Pascal doesn't control a variable's lifespan by a modifier, since the static modifier only applies to fields, i.e. part of a record or class. I have to admit that I was always thinking of them as variables too, especially since they can be declared in a var block...


In Pascal, a different lifespan should imply a different declaration section.  That's the reason there is a separate "type" section, a "const" section and a "var" section.

Types and constants don't have a runtime lifespan though, they only "exist" during compilation. (Some constants may have an address, some may not.)


In a function/procedure, the "var" section is supposed to consist of all the variables that exist in the scope of the function/procedure.

Well, the variables in addition to the subroutine parameters (minus those declared as const) and function results.


If some value is supposed to persist then it should NOT be declared in the "var" section, it should be declared in its own section.

Yes, but only because classic Pascal would require that this "own section" should be outside of the subroutine.


In conclusion, I think I'm fine with static attribute, or a static/persistent/globalvar section, or both.
« Last Edit: April 12, 2026, 01:04:54 pm by creaothceann »

 

TinyPortal © 2005-2018