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