DLR Inverted Foreach Control: Threads, Continuations, or ...?

Jul 30, 2009 at 8:37 PM

I'll call it "Inverted Iteration" for want of better terminology.

How does the DLR implement things like the following
(following Ruby's "generator" model for doing the same thing)
(using C#-like syntax for universality)

public static void MyMethod(YieldObject yo) {
     foreach (int i in {1,2,3,4,5,7}) {
             try {
                 yo.LikeYieldReturnVal(" deduct points"+i*i*i);
                 Transfer(HisPointAccount, MyPointAccount, 1000000.00D);
             } catch (Exception e) {
               throw new Exception("Mooch: ERROR+e");

The "yo" object can be passed down to subroutines implementing
for example a binary tree.                         

OK HOWTO's I know:
    TurnMethodInsideOut: C#: I can't do this; uses super-macro
            to turn MyMethod inside out; so yield returns are
            turned into an iterator's return values; context/state
            of inverted code is maintained
    Continuatiobs: Ruby: Generators Use Continuations in DLR?
            (By the way I haven't found any .Net language that
            I'm sure has first-class continuations; Ruby has
            Monad Continuations, but that seems to be just a
            programming technique for passing alternative choices
            as the last argument to every function call, adding
            to the front for depth-first backtracking)
    Threads: launch a thread executing this process and arrange
            synchronization around YieldObject and Enumerator.
    FunWithStack: make a copy of the runtime stack between "here"
            (which is the yo.LikeYieldReturnVal) upward until
            we find a marker for creation of yo;
            Use that as the new stack, faking return from
            yo creation back into the original stack
    MuchMoreFunWithStack: I'm brave and I've implemented
            runtime so that every function call has, at
            the beginning of every function's stack frame,
            a pointer to the position of the stack following
            the function finish.  This lets me stick the SP
            into a newly malloc'd (and managed) block of size
            500K bytes. Then I set up hardware/CPU to call
            me if there's a write beyond that block; if so,
            I create a new 512K block, preserving the integrity
            of the linked-list frames of invocation

or ...?

Really appreciate help on this.


Jul 30, 2009 at 9:00 PM

I'm not sure if I understand the question. We don’t have any support for continuations in DLR, IronRuby or IronPython. IronPython supports generators similar to C# (a state machine is generated). Ruby doesn't have generators (at least Ruby 1.8, which IronRuby is compatible with). Ruby’s yield expression is just a call to given block (lambda method).