[fpc-devel] Pure function development discussion

J. Gareth Moreton gareth at moreton-family.com
Sun Aug 12 16:04:38 CEST 2018


 Limiting pure functions to the definitions of constants severely limits
their usefulness, and programmers may just ignore them completely and
calculate their results by hand where needed (e.g. replacing ln(2) with
0.69 etc.).  They're designed to replace entire function calls with
pre-calculated results at compile-time, thereby providing a massive speed
and size saving, and in places where you might least expect, depending on
how functions are expanded recursively.  For example, say you have a
binary search function that's declared "inline", and you pass in a constant
array of a static size.  The function call is expanded and the parameter
propagated.  You may then call a function that calculates the base-2
logarithm of the array's size, rounded down, as this is equal to the
maximum number of iterations required in the search loop.  Since the size
is a constant (since the parameter is propagated unchanged), so too will
its logarithm, so the call is replaced with the pre-calculated result. 
Since this logarithm is relatively small (e.g. a list of size 200 will
return a value of 7), this may cause the loop to be unrolled, providing yet
more speed boosts by removing the need for branch prediction.  That's in a
very ideal world, of course, where all the optimisations work in unison.
 Also, even with your suggestion, there are some cases where the programmer
can be deliberately malicious, such as defining a constant to equal the
result of a pure function, and then referencing the constant inside the
function itself.  I do have an idea though: I may treat them as a kind of
inline expression that references are replaced with (e.g. with "const LN2 =
ln(2)", replacing references to LN2 with the actual ln(2) call) until it's
been successfully evaluated, after which the constant can just be replaced
with its value.  If a function turns out to be impure during evaluation of
the constant, or appears to have an infinite loop (the compiler will fail
the evaluation if it reaches an upper limit on node count or stack depth),
then an error is thrown and the constant marked invalid, hence the compiler
will fail cleanly.

 Granted, I may put constant evaluation on the side for the moment and
actually get the compile-time evaluation to work first.  I'm just trying
to think of every possible eventuality and cleanly cover the all.

 Gareth aka. Kit

 On Sun 12/08/18 15:28 , "Dmitry Boyarintsev" skalogryz.lists at gmail.com
sent:
 On Sat, Aug 11, 2018 at 8:50 PM J. Gareth Moreton  wrote:
 How and when is the constant defined? Should such constructs be disallowed
and constants only allowed to be declared in other units that use the unit
that contains the pure functions in its interface section? What would be
the ideal and cleanest behaviour?

 Why don't you limit the purity only for expressions explicitly defined at
"const" section?If the function call is found at any place other than
"const" section, the function would be executed as a regular run-time
function.Pretty clean.

 thanks,Dmitry
  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20180812/3b2ab60e/attachment.html>


More information about the fpc-devel mailing list