On 19/11/2012, at 1:15 AM, john skaller wrote: > var ch = mk_schannel[int](); > spawn_fthread { write (ch,42); }; > var x:int; > var flag = false; > proc fetch() { > x = read ch; > flag = true; > } > > gen get() = { if not flag do fetch; done return x; } > > println$ #get;
So now, if you make inline get() { .. } this code is now guaranteed to work. If you mess up and nest the inline generator in a function it may fail because functions aren't allowed to have side effects (NOTE: it isn't clear reading a channel should be considered a side effect). Also if that function isn't inlined into a top level procedure the service call will fail (I have not yet implemented a check for improperly located service calls, I should do that). If you call get and the compiler finds it cannot inline it the compilation will fail with a diagnostic. This is a now a programmer error. Inline is not *mandatory* meaning the compiler *will* inline a function so marked, no ifs or buts, unless it cannot. The compiler cannot inline recursive calls to functions unless the call is to a child. I got the logic wrong until recently so it worth explaining: a *call* is recursive if the target function statically contains, directly or indirectly, a call back to the calling function. This means both the caller and callee are recursive. You can also call a recursive function non-recursively. In general the compiler cannot inline recursive functions unless (a) the recursion is tail, and is optimised away into a loop (b) the recursion is through the call to a child. In the call graph, we allow inlining children that call back into their parents since such inlining cannot explode infinitely. Functions are nested statically up to a maximum depth and for a call to be recursive at least one path has to go UP to the parent at some point in the cycle (up meaning to a lesser depth). It is unfortunate this algorithm cannot inline sibling calls: f () => ... g() ...; g() => .. f() ... ; We'd really like to inline once in each of these functions, so we end up with a single object closure instead of two. Unfortunately i don't know how to make this work. More generally we'd like to unroll recursions to some depth, typically one is good because it allows a recursion that exits immediately to have a very low cost (for example recursing down an empty list). Again, I don't know how to do this. The problem is that in recursing we first clone the target and specialise it before inlining, and the call to THAT function isn't recursive any more. So it is very hard to keep a trail to stop that process repeating. Merely detecting recursion doesn't work. My idea is that when cloning the function the actual CALL is marked "noinline". At present, there are no inline-call,inline-apply,noinline-call, or noinline-apply terms in the representation though. More general: unroll-call-n (3, f, arg) which would inline f with arg, and replace itself in the inlined code with unroll-call-n (2, f, arg) so it would be inlined again until the count got to 0. This is non-trivial to get right (because there can be more than one call to deal with). -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ Monitor your physical, virtual and cloud infrastructure from a single web console. Get in-depth insight into apps, servers, databases, vmware, SAP, cloud infrastructure, etc. Download 30-day Free Trial. Pricing starts from $795 for 25 servers or applications! http://p.sf.net/sfu/zoho_dev2dev_nov _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language