/*
 *  interface.jc
 *
 *  The language allows (currently very simple) inheritance from a single interface.
 *  An interface can only have methods, no static functions and no data. All methods
 *  in an interface are implicitly PURE, meaning they cannot have an implementation.
 *  There is a dedicated keyword for declaring interfaces, 'interface'.
 */

import stdlib;
using stdlib;   // get rid of stdlib namespace

/*
 *  IHello
 *
 *  declare a simple interface
 */

interface IHello
{
    method          IHello();
    method          Set(int);
    method int      Get();
}

/*
 *  CHello
 *
 *  The CHello class implements our IHello interface.
 *  It has a int value as data member.
 */

class CHello : IHello
{
    method          CHello()            { m_Value = 0; }
    method          Set(int v)          { m_Value = v; }
    method int      Get()               { return m_Value; }
    method          NotInInterface()    { m_Value *= 5; }

    int m_Value;
}

/*
 *  CFoo
 *
 *  The CFoo class implements our IHello interface, too.
 *  It has a string as data member.
 */

class CFoo : IHello
{
    method          CFoo()              { m_String = ""; }
    method          Set(int v)          { m_String = v; }
    method int      Get()               { return (int) m_String; }

    string m_String;
}

/*
 *  main
 */

function string main(const string[] args)
{
    // create a CHello instance
    CHello hello = new CHello();
    // call it's methods
    hello.Set( 101 );
    int x = hello.Get();
    hello.NotInInterface();

    // print IHello information
    IHelloPrint( hello );

    // create a CFoo instance
    CFoo foo = new CFoo();
    // call it's methods
    foo.Set( 202 );
    int y = foo.Get();

    // print IHello information
    IHelloPrint( foo );

    // get an IHello reference from a CHello
    IHello ihello = hello;

    // call it's methods
    ihello.Set( 303 );
    int z = ihello.Get();

    // print IHello information
    IHelloPrint( ihello );

    return "";
}

/*
 *  IHelloPrint
 */

function IHelloPrint(const IHello hello)
{
    print("* The given object is a ");
    if( typeof(hello) == typeof(CHello) )
    {
        print("CHello\n");
    }
    else if( typeof(hello) == typeof(CFoo) )
    {
        print("CFoo\n");
    }
    printf( "* IHello::Get() returns %d\n", hello.Get() );
}