/*
 *  cofunction.jc
 *
 *  Test using cofunctions (JewelScript's coroutines)
 */

// import and use our standard lib
import stdlib;
using stdlib;

/*  cofunction Generator()
 *
 *  A simple cofunction that counts from 'a' to 'b' inclusively
 *  - returns one value each time it is resumed
 *  - returns -1 if run-through
 */

cofunction int Generator(int a, int b)
{
    for( int y = a; y <= b; y++ )
        yield y;
    yield -1;
}

/*
 *  global variable g_test
 *
 *  This instantiates our cofunction and assigns the resulting thread context to a global variable.
 *  Thread context variables can only be references, and never be const.
 */

Generator g_Test = new Generator(2, 3);

/*
 *  class Foo
 *
 *  Test having a cofunction's thread context as a class member.
 *  As with all member variables, thread context variables must be initialized in the class constructor.
 */

class Foo
{
    method Foo()
    {
        m_Test = new Generator(3, 5);
    }

    Generator m_Test;
}

/*
 *  function main
 *
 *  Resume the various instances of our cofunction.
 */

function string main(const string[] args)
{
    // Instantiate our cofunction in a local variable
    Generator test = new Generator(4, 7);

    // resume 'g_Test' five times
    print( "\n\nGlobal thread 'g_Test':\n" );
    for( int i = 0; i < 5; i++ )
        printf( "%2d ", g_Test() );

    // resume 'foo.m_Test' five times
    print( "\n\nclass 'Foo' member thread 'm_Test':\n" );
    Foo foo = new Foo();
    for( int i = 0; i < 5; i++ )
        printf( "%2d ", foo.m_Test() );

    // resume 'test' five times
    print( "\n\nfunction main local thread 'test':\n" );
    for( int i = 0; i < 5; i++ )
        printf( "%2d ", test() );

    return "";
}