Recent

Author Topic: Redeclared constant as variable  (Read 1743 times)

zamronypj

  • New Member
  • *
  • Posts: 17
    • Fano Framework, Free Pascal web application framework
Redeclared constant as variable
« on: July 17, 2019, 02:01:39 am »
Based on article

https://www.thedelphigeek.com/2019/07/when-true-is-not.html

Code: Pascal  [Select]
  1. program fuxkup;
  2.  
  3. var true : boolean = not false;
  4.  
  5. procedure magic;
  6. begin
  7.     true := false;
  8. end;
  9.  
  10. begin
  11.     writeln(true);
  12.     magic();
  13.     writeln(true);
  14. end.
  15.  
  16.  

My initial impression, FreePascal will refuse to compile because of duplicate identifier (because both, true as constant and true as variable, are in scope). But it does not.
Source code above will compile successfully and when run, print

true
false

Is this correct behavior?

« Last Edit: July 17, 2019, 02:20:07 am by zamronypj »
Fano Framework, Free Pascal web application framework https://fanoframework.github.io
Personal Projects https://v3.juhara.com
Github https://github.com/zamronypj

jamie

  • Hero Member
  • *****
  • Posts: 1779
Re: Redeclared constant as variable
« Reply #1 on: July 17, 2019, 02:35:23 am »
Yup, kind of funky ! >:(

They're variables btw..

Akira1364

  • Hero Member
  • *****
  • Posts: 522
Re: Redeclared constant as variable
« Reply #2 on: July 17, 2019, 03:23:15 am »
True and false are not constants or "reserved" words in FPC. They're just magic intrinsic keywords that the compiler registers internally as being equal to 1 and 0.

You can see where it does this here.

PascalDragon

  • Hero Member
  • *****
  • Posts: 523
  • Compiler Developer
Re: Redeclared constant as variable
« Reply #3 on: July 17, 2019, 09:24:33 am »
True and false are not constants or "reserved" words in FPC. They're just magic intrinsic keywords that the compiler registers internally as being equal to 1 and 0.

You can see where it does this here.
The location is right, but your assumption is not: they are indeed simply ordinary constants that are inserted by the compiler into the System unit upon compiling that unit.

Thaddy

  • Hero Member
  • *****
  • Posts: 8521
Re: Redeclared constant as variable
« Reply #4 on: July 17, 2019, 01:02:49 pm »
See also: https://wiki.freepascal.org/User_Changes_3.0#True_and_False_are_not_keywords_anymore so it is intentional.

They can be re-declared as any simple type including strings.
Code: Pascal  [Select]
  1. program trueorfalse;
  2. // silly season code
  3. const
  4.   true = 'yes';
  5.   false = 'no';
  6. begin
  7.   writeln(true,false);
  8. end.
« Last Edit: July 17, 2019, 01:16:58 pm by Thaddy »
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

Akira1364

  • Hero Member
  • *****
  • Posts: 522
Re: Redeclared constant as variable
« Reply #5 on: July 17, 2019, 03:06:20 pm »
The location is right, but your assumption is not: they are indeed simply ordinary constants that are inserted by the compiler into the System unit upon compiling that unit.

Well, I moreso meant constant as in something actually visibly declared somewhere in-source, I.E.

Code: Pascal  [Select]
  1. const TRUE = 1;

as opposed to an internally generated constsym. I know those ultimately amount to the same thing though.

Overall I think why this works is just a matter of "you can always redeclare any identifier that is not an actual reserved word", right?
« Last Edit: July 17, 2019, 03:08:21 pm by Akira1364 »

kupferstecher

  • Sr. Member
  • ****
  • Posts: 289
Re: Redeclared constant as variable
« Reply #6 on: July 17, 2019, 07:35:32 pm »
They're just magic intrinsic keywords that the compiler registers internally as being equal to 1 and 0.
Is this guaranteed on all platforms?
Under Windows 7, Lazarus 2.0.2:
writeln(Integer(true)); // returns 1
writeln(Booltostr(true)); // returns -1

Why I ask, I'd like to do something like that:
Code: Pascal  [Select]
  1. aEnabled: Boolean;
  2. begin
  3.   someRegister:= (Integer(aEnabled) shl 5);
  4. end;

instead of
Code: Pascal  [Select]
  1.   if aEnabled
  2.    then someRegister:= (1 shl 5);
  3.    else someRegister:= 0;

And it would be nice, if the Integer type cast could be dropped somehow (Operator overload?).



Thaddy

  • Hero Member
  • *****
  • Posts: 8521
Re: Redeclared constant as variable
« Reply #7 on: July 17, 2019, 08:21:17 pm »
The integer cast is misplaced here. You should cast to an unsigned type. That should work, except for the sign bit if there is any signed integer type in the original code.
There seems to be a bug in sysutils.BoolToStr(), unless there's also a BooleanToStr().  Pascal Booleans are 0 and 1. C Compatible Bools are 0 and not 0 ( resolved as -1, but any value except 0 will return true)

I would file a bug report against BoolToStr

See https://freepascal.org/docs-html/ref/refse12.html#QQ2-26-29
« Last Edit: July 17, 2019, 08:28:34 pm by Thaddy »
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

kupferstecher

  • Sr. Member
  • ****
  • Posts: 289
Re: Redeclared constant as variable
« Reply #8 on: July 17, 2019, 10:12:07 pm »
Hello Thaddy,

thanks for the documentation link! It's 1 and 0 as you said.

The operator overload I just tried and it compiles.


Furthermore I filed a bug report for booltostr:
https://bugs.freepascal.org/view.php?id=35856

PascalDragon

  • Hero Member
  • *****
  • Posts: 523
  • Compiler Developer
Re: Redeclared constant as variable
« Reply #9 on: July 18, 2019, 09:32:00 am »
Overall I think why this works is just a matter of "you can always redeclare any identifier that is not an actual reserved word", right?
Indeed.

Thaddy

  • Hero Member
  • *****
  • Posts: 8521
Re: Redeclared constant as variable
« Reply #10 on: July 18, 2019, 04:21:57 pm »
Since the bug report was dismissed:
Here's what I propose:
Code: Pascal  [Select]
  1. program properbooleanstrings;
  2. // not BoolToStr() but BooleanToStr().
  3. function BooleanToStr(const a:Boolean):string;inline;
  4. begin
  5.   writestr(BooleanToStr{or maybe use result in some modes},ord(a))
  6. end;
  7.  
  8. begin
  9.   Writeln(BooleanToStr(true));
  10.   Writeln(BooleanToStr(false));    
  11. end.

Doesn't even need sysutils.... :D And works in all modes and respects Pascal type Booleans (0..1) instead of C type Boole (-1,0)..

Of course this also works:
Code: Pascal  [Select]
  1. function BooleanToStr(const a:Boolean):string;inline;
  2. begin
  3.   writestr(BooleanToStr{or maybe use result in some modes},a)
  4. end;
which prints either true or false.

Note the type helper has the same caveat as BoolToStr(), prints -1:
Code: Pascal  [Select]
  1. uses sysutils;
  2. var a:boolean = true;
  3. begin
  4.   writeln(a.Tostring); // using the type helper
  5. end.



« Last Edit: July 18, 2019, 04:56:39 pm by Thaddy »
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

ASerge

  • Hero Member
  • *****
  • Posts: 1360
Re: Redeclared constant as variable
« Reply #11 on: July 23, 2019, 10:02:24 pm »
Since the bug report was dismissed:
Because the only bug is that the documentation for the function is not complete.

Peter H

  • New Member
  • *
  • Posts: 48
Re: Redeclared constant as variable
« Reply #12 on: July 23, 2019, 10:39:54 pm »
So we can write now:
Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. const
  4.   true = not true;
  5. var
  6.   x:boolean;
  7.  
  8. begin
  9.   if true = (x<>x) then
  10.     writeln( 'Hello brave new World!' );
  11.   readln;
  12. end.
  13.  

This is more horrible than writable constants.
Sorry, but this has to be said.
« Last Edit: July 23, 2019, 10:44:57 pm by Peter H »

glorfin

  • Jr. Member
  • **
  • Posts: 61
Re: Redeclared constant as variable
« Reply #13 on: July 24, 2019, 01:55:52 pm »

This is more horrible than writable constants.
Sorry, but this has to be said.

Agreed. Such things should not be compiled. 

Thaddy

  • Hero Member
  • *****
  • Posts: 8521
Re: Redeclared constant as variable
« Reply #14 on: July 24, 2019, 04:30:14 pm »
Writable typed constants are much older than Object Pascal.
They serve - amongst other - a distinct purpose: maintaining state within the context of a procedure or function.
example:
Code: Pascal  [Select]
  1. program state;
  2. {$mode iso} (* ISO mode has no object extensions and $J+ is the default. *)
  3. function HowManyTimesDidYouCallMe:integer;
  4. const T: integer = 0;
  5. begin
  6.   inc(T);
  7.   HowManyTimesDidYouCallMe := T;
  8. end;
  9.  
  10. var i:integer;
  11. begin
  12.   for i := 0 to 9 do writeln(HowManyTimesDidYouCallMe);
  13. end.

So it is actually *very* usefull in a non-object oriented pascal program.

It is just that not many younger programmers appreciate its power.
The state of T is bound by its function (although in the background it is still global, no other procedure or function can access it)
Think of it as a precursor to object extensions.

 
« Last Edit: July 24, 2019, 08:01:37 pm by Thaddy »
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.