My hobbyist coding updates and releases as the mysterious "Mr. Tines"

Sunday 11 January 2009

Python swinging both ways

Following up to the last post I made in my quest for a cross-VM (JVM and CLR), single code-base, polyglot language stack, which doesn't involve any more Java than can be helped. Especially when there is Scala to play with, a language which a reading of the stairway book shows is very nifty indeed.

To summarise where we are, and what we have discovered to date --

  • Python can call Scala and Java happily
  • Java calling into Python is funky and platform dependent; doubly so for Scala
  • Scala cannot both call into java.* classes and compile on .net
  • Low-level Scala pre-defs differ in the Byte type (signed in Java/J#/Scala-JVM, unsigned in Scala-msil)
  • Ruby's predilection for Pascal-case namespaces (fudged in JRuby to match Java's lower-case convention) would require a lot of plumbing around in C# to mate IronRuby to J# or Scala-msil (as the rest of .net uses Pascal-casing).

And then there is this weekend's discovery.

As J# is a barely JDK1.2 implementation at best, I can't use the latest Java splash-screen feature, and have to fall back on older implementations. I have one to hand, back from c. JDK 1.4 days. It uses synchronized(), Object.wait() and Object.notifyAll().

The first is easy enough to deal with when wanting to put as much as possible of this GUI-driving code into Python -- define an interface to hold a code block

public interface ISynchronizedAction
{
  void performAction();
}

and then have a class which knows about the object to synchronize on, and can execute the block in a synchronized scope

public class Synchronized {
  private Object lock;

  public Synchronized(Object lock) {this.lock = lock;}

  public void Lock(ISynchronizedAction action)
  {
    synchronized(lock) {action.performAction();}
  }
}

Except in IronPython, I also discover by dumping the dir() of an object sub-classing java.awt.Window -- inheritance being needed for the splash-screen window class rather than composition, in order to hook the update/repaint APIs -- that neither Object.wait() nor Object.notifyAll() are present to be called. Fortunately the object I want these methods on is the same one I want to synchronize on, the splash-screen window itself, so I was able to just extend Synchronized with

  public void delegateWait() throws InterruptedException
  {
    lock.wait();
  }

  public void delegateNotifyAll()
  {
    lock.notifyAll();
  }

and make the there-and-back-again calls as required.

Then I just had to work around the older dialect's lack of support for .png (by using a .gif) by using the handy Java-1.1 compatible javapng-1.3.0 library to actually paint the image into the splash screen.

As usual, Jython needs the helper .jar file in the CLASSPATH, while IronPython can reference the equivalent .dll from code by assembly file name.

Saturday 10 January 2009

Towards Scala/.net 2.0

A propos of my last bit of banging head against a wall... Oh, and these snippets are definitely offered under the WTFPL.

The main things that the scala-msil compilation balks at when looking at .Net assemblies post framework 1.x are generics; and things marked as var. Looking at the source in http://lampsvn.epfl.ch/svn-repos/scala/msil/trunk/src/, the first changes to make are, first in msil/util/Signature.java, add the extra byte code values

    public static final int ELEMENT_TYPE_VAR = 0x13;     // a class type variable VAR
    /***/
    public static final int  ELEMENT_TYPE_GENERICINST    = 0x15;     // GENERICINST    ...

and then start to do something about parsing them in msil/PEFile.java, in method PEFile.Sig.decodeType0()

        case ELEMENT_TYPE_GENERICINST:
        // Followed by <type> token
        //ELEMENT_TYPE_GENERICINST <an mdTypeDef metadata token> <argument Count> <arg1> ... <argN>
        {
            // base type
            int tmp = readByte();
            if((tmp != ELEMENT_TYPE_VALUETYPE) && (tmp != ELEMENT_TYPE_CLASS))
                throw new RuntimeException("*1*>> "+ byte2hex(tmp) +
        "@" + pos() + " in " + this);   
            int id = decodeInt();
            type = pemodule.getTypeDefOrRef(id);
            if (type == null)   throw new RuntimeException("**>> "+ byte2hex(desc) +
        "@" + pos() + " in " + this);
            // number of type arguments
            int num = decodeInt();
            System.out.println("num = "+num);
            for(int i=0;i<num;++i)
            {
                Type t = decodeType0();
                //TODO: use this information
            }
        }
        break;

        case ELEMENT_TYPE_VAR:
        {
            int index = decodeInt();
            System.out.println("var of type "+index);
            // TODO: actually look up what the index means 
            return Type.GetType("System.Object");
        }

This is necessary but not sufficient -- this still leaves problems with types involving templated subtypes or interfaces, for which the first TODO is probably meaningful. As a consequence we're still a long way from a "hello .net 2.0 world!" example yet; let alone a rebuilt scala-compiler.jar, alas.