Skybuck Flying
2022-05-01 23:35:00 UTC
program TestProgram;
{
Test +-+-+-+-+-+-+-+ plus minus plus minus plus in Delphi
version 0.01 created on 2 may 2022 by Skybuck Flying
I came across this weird code and it actually compiles.
It actually led to a bug when trying to draw a vertical line and Delphi compiler
did not catch it, no hint, no warning, nothing.... let me show you,
it was in opengl but I will show the same effect with vcl canvas methods:
(this happened because the opengl screen/coordinate system was translated
to make the origin 0,0,0 at the center of screen, so imagine a canvas that
somehow does that as well, otherwise imagine opengl vertex call, I will show
both:
openl code:
glVertexf( X, -ScreenHeightHalf );
glVertexf( X, +-ScreenHeightHalf );
vcl code:
MoveTo( X, -ScreenHeightHalf );
LineTo( X, +-ScreenHeightHalf );
The code above is flawed, because the negative sign wins... so
it will infact draw no line at all !
Which is kinda difficult to see, because it requires understanding the precedence
of operators, which operator will win, what are the rules.
Is there an left to right, or right to left rule, or is it just math rules... like
negative wins over positive, or vice versa... hmmmmmm.
Not sure... is it undefined... not sure...
What happened is, as I copied the code from line 1 to line 2, I placed a plus
in front of it, but forgot to illiminate the negative sign and surprise
surprise it actually compiled ! Which leads to the following funny test code
which I also immediately tried and strangely enough it compiles without
any hints or warnings...
It would have been nice if Delphi could catch this situation, and maybe
at least give some kind of hint or warning messages, I think a hint would
be sufficient...
I am also curious what kind of code/assembly is generated and also if this
code ports to c/c++ and other languages, and if other compilers
give any warnings what so ever.
}
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
procedure Main;
var
A, B, C : integer;
begin
writeln('program started');
A := 50;
B := 25;
// C := A + B; // produces 75
// C := A +- B; // the bugged code, produces 25
// nice obfuscation ! =D and that in Delphi/Pascal ?! HOLYFUK.
// C := A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-B; // the funny code produces 75
// C := A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+B; // still produces 75, how ? strange ?
// My hypothesis about what is going on above: Limited compiler operator room/buffer/processing ?
// I am starting to suspect that maybe the compiler has a limited ammount of operators that
// it can handle ?!? Is this the thruth ? I don't know yet.
// nope doesn't seem to be case see below:
// last one wins on the left side ?
// C := A -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+B; // produces 25.
// another case of insane code:
// C := A ------------------------------------------------------B; // produces 75.
// now it does produce an error
// C := A -+*******-----+++----********* B; // error
// C := A ******** B; // error
// C := A / / / / / B; // error
// C := A -- B; // produces 75
// C := A --+ B; // produces 75
// C := A -+- B; // produces 75
// C := A +-- B; // produces 75
// C := A --- B; // produces 25
// C := A ---+ B; // produces 25
// C := A +-+-+-+ B; // produces 25
C := A +-+-+-+-+ B; // produces 75
// to solve it, count the number of negatives... unequal it will subtract equal it will add.
// (cause the negatives negate each other into positive)
writeln( A );
writeln( B );
writeln( C );
writeln('program finished');
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
{
Test +-+-+-+-+-+-+-+ plus minus plus minus plus in Delphi
version 0.01 created on 2 may 2022 by Skybuck Flying
I came across this weird code and it actually compiles.
It actually led to a bug when trying to draw a vertical line and Delphi compiler
did not catch it, no hint, no warning, nothing.... let me show you,
it was in opengl but I will show the same effect with vcl canvas methods:
(this happened because the opengl screen/coordinate system was translated
to make the origin 0,0,0 at the center of screen, so imagine a canvas that
somehow does that as well, otherwise imagine opengl vertex call, I will show
both:
openl code:
glVertexf( X, -ScreenHeightHalf );
glVertexf( X, +-ScreenHeightHalf );
vcl code:
MoveTo( X, -ScreenHeightHalf );
LineTo( X, +-ScreenHeightHalf );
The code above is flawed, because the negative sign wins... so
it will infact draw no line at all !
Which is kinda difficult to see, because it requires understanding the precedence
of operators, which operator will win, what are the rules.
Is there an left to right, or right to left rule, or is it just math rules... like
negative wins over positive, or vice versa... hmmmmmm.
Not sure... is it undefined... not sure...
What happened is, as I copied the code from line 1 to line 2, I placed a plus
in front of it, but forgot to illiminate the negative sign and surprise
surprise it actually compiled ! Which leads to the following funny test code
which I also immediately tried and strangely enough it compiles without
any hints or warnings...
It would have been nice if Delphi could catch this situation, and maybe
at least give some kind of hint or warning messages, I think a hint would
be sufficient...
I am also curious what kind of code/assembly is generated and also if this
code ports to c/c++ and other languages, and if other compilers
give any warnings what so ever.
}
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
procedure Main;
var
A, B, C : integer;
begin
writeln('program started');
A := 50;
B := 25;
// C := A + B; // produces 75
// C := A +- B; // the bugged code, produces 25
// nice obfuscation ! =D and that in Delphi/Pascal ?! HOLYFUK.
// C := A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-B; // the funny code produces 75
// C := A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+B; // still produces 75, how ? strange ?
// My hypothesis about what is going on above: Limited compiler operator room/buffer/processing ?
// I am starting to suspect that maybe the compiler has a limited ammount of operators that
// it can handle ?!? Is this the thruth ? I don't know yet.
// nope doesn't seem to be case see below:
// last one wins on the left side ?
// C := A -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+B; // produces 25.
// another case of insane code:
// C := A ------------------------------------------------------B; // produces 75.
// now it does produce an error
// C := A -+*******-----+++----********* B; // error
// C := A ******** B; // error
// C := A / / / / / B; // error
// C := A -- B; // produces 75
// C := A --+ B; // produces 75
// C := A -+- B; // produces 75
// C := A +-- B; // produces 75
// C := A --- B; // produces 25
// C := A ---+ B; // produces 25
// C := A +-+-+-+ B; // produces 25
C := A +-+-+-+-+ B; // produces 75
// to solve it, count the number of negatives... unequal it will subtract equal it will add.
// (cause the negatives negate each other into positive)
writeln( A );
writeln( B );
writeln( C );
writeln('program finished');
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.