For Loops for non Ordinals
During my work on the other merge requests, I found it really annoying that for loops only work for ordinal types, as records wrapping some ordinal types (like tconstexprint in the compiler) are quite common for certain applications (also bigintegers)
The main problem is that for loops can not that easily be substituted with while or repeat loops. The main reason for this is that for loops make a copy of the target value, and they check for the final value to be overflow safe.
So the simple conversion from:
for i:=min to max do
statement;
would be:
i:=min;
tmpmax:=max; { Must create copy, because max could change between accesses }
if i<=tmpmax then
repeat
statement;
{ Can't do a while i<=tmpmax because of potential overflow }
if i>=tmpmax then
break
else
inc(i);
until false;
Not to mention if there is a continue in the loop, there are a few options, first replace each continue with
if i<=max then
break
else
inc(i);
continue;
or move the check to the beginning:
i:=min;
tmpmax:=max;
firstiter:=true;
if i<=tmpmax then
repeat
if fistiter then
firstiter:=false
else if i=tmpmax then
break
else
inc(i);
statement;
until false;
or for convinience a try-finally can be used, which has other runtime implications:
i:=min;
tmpmax:=max;
if i<=tmpmax then
repeat
try
statement;
finally
if i>=tmpmax then
break
else
inc(i);
end;
until false;
Long story short, emulating a for loop is very complicated to do manually (mainly because overflows are complicated) and very error prone. But custom types that emulate ordinal behavior are quite common.
So I've built a simple substitute, which will take above steps, to allow for-to syntax for any type that overloads <=, >= as well as the + operator for integers.
This includes custom records types, like tconstexprint or the gmp integers, but also floats.
It does so by simply doing above substitutions automatically to transform a for loop into an if->repeat->statement->increment loop