Just some more thoughts on the closure bug.

To remind you of the problem: when Felix inlines code,
a parameter can be replaced by its argument.

When the argument is a variable, the value my change.

When calling a function this can't happen: functions can't
change the value of non-local variables.

So it is safe to do this substitution .. provided the value
of the variable is used immediately.

The PROBLEM comes when the function creates a closure which
is executed later. Then it will refer to the current value
of the variable, instead of the value at the time the
closure was created.

In particular this happens when you have a loop containing
a partial call to a curried function, which stores the 
closures somewhere for later execution .. I ran into
this creating callbacks for Gtk buttons with code like:

fun pushed(x:int) (y:int) => x + y;

var a = 1;
whilst ...
  register_callback(pushed a);
  a++
...


This code failed because pushed a was inlined, so that
the closure was the function

        fun (y:int) => a + y;

Copying the variable does not help at all:

var a_saved = a;
register_callback(pushed a);

now just calculates a_saved + y instead.

This problem can't arise in functional code, in particular
if the whilst loop is replaced by a recursion, there should
be a distinct stack frame for each call (hopefully not 
optimised away because that would re-introduce the problem).

What is actually required is that the compiler generate
two closures: there has to be a closure for the outer
function of pushed containing a copy of the value of a
at the time it is created, which is then executed.
That execution returns the second closure, which is bound
to it (the first closure is its parent).

That closure can't be optimised away because a fresh
and distinct one is created in each pass through the loop
AND because the closure it returns refers to its parameter x.

BUT if it is not done in a loop we want to optimise it away,
and just use a saved copy of the variable in the caller.

I still have NO idea how to do this. The problem can now
be fixed by 

noinline fun pushed(x:int) (y:int) => x + y;

but it should not be necessary to write that.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to