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

Reply via email to