I have to issue a warning to Felix programmers due to being trapped
by this issue myself just now. Consider:

  fun valid: zmq_socket->bool = "$1!=0";
  fun check_socket(x:zmq_socket)= { if x.valid do return x; else ehandler; 
done; }
  gen mk_socket (c: zmq_context) (t:zmq_socket_type_t) => check_socket$ 
zmq_socket (c,t);

  var requester = context.mk_socket ZMQ_REQ;
  requester.close;
  context.term;

This code failed:  context.term terminates a ZMQ context, this operation
blocks until all sockets are closed. You can see here the socket is closed:

      _genout_urv13953  = (int)zmq_close(PTF requester);
   ..
      _genout_urv13814  = (int)zmq_term(PTF context);
  ..

 but the zmq_term call still hangs. 

Can you see the problem? If not .. read the subject line again!
Now look at this code carefully:

  fun check_socket(x:zmq_socket)= { if x.valid do return x; else ehandler; 
done; }

and now at the generated C++:

      if(!((zmq_socket((PTF context),ZMQ_REQ))!=0)) goto _14263;
      _urv14262  = zmq_socket((PTF context),ZMQ_REQ);

Now it is clear. The Felix compiler has opted for lazy evaluation of the
parameter, substituting the argument for the parameter.

this results in TWO sockets being created, but only one is closed, so
the terminate of the context hangs.

** Felix does NOT recognise that the argument has side effects and 
must be evaluated only once (i.e. eagerly).

To ensure eager evaluation:

  fun check_socket(var x:zmq_socket)= { if x.valid do return x; else ehandler; 
done; }
                                   ****
is required. It isn't clear to me at this time if this is a bug or not. 
Basically felix
evaluates

        y = g x;

as

        tmp = g x;
        y tmp;

when g is a generator. In any code if tmp were unused the call to the generator
would be eliminated. This is surprising: generator calls are supposed to be 
evaluated
exactly once. but then, you're supposed to USE the result of any function or 
generator call.

The above problem is the opposite: calling the generator twice.  This problem 
can probably
ALSO occur in straight line code:

val y = g x;
yy := (y,y);

to stop it, same as above:

var y = g x;

I will have to think on this one. If you consider the "val y = g x;" case you 
can
see that the optimisation of the call cannot depend on the compiler 
knowing about generators because in:

  f y;

y is just a val. No generators in sight unless we track backwards to its 
initialiser.
So the compiler is free to copy "y" is a val parameter is given, and its no 
harm.

The problem is if y is replaced by g x in multiple cases. I think the compiler
"forgets" that g x is a generator application.

--
john skaller
skal...@users.sourceforge.net





------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to