haXe Type System Extensions for Async Calls

posted on 2006-01-06

Here’s an interesting problem to tackle. haXe is a common language targeting different platforms (Flash, JavaScript and Neko) with different API. It would be nice to have some kind of integrated RPC so you can directly and transparently call JS code from Flash, or Neko (server side) from JS (client side).

For example, let’s say you want to access the server filesystem from Flash. First you’ll have to connect to the server and negociate the rights to do this, but that’s not the difficult part. Ideally, you would just use the File class directly and if you have the rights all calls would be forwarded to the server and responses sent back transparently.

class File {
    public function new( name : String ) {
         ...
    }
    public function write( data : String ) : Void {
         ...
    }
    public function close() : Void {
         ...
    }
    public function size() : Int {
         ...
    }
}

The problem here is that File is implemented using haXe Neko APIs which are not available from Flash. Actually, when compiling haXe for Flash program, you don’t even have access to the File class since it’s in a separate directory.

In that situation, you would endup normally to write a FileProxy class that would implement the methods in terms of crossplatform RPC calls and use this proxy class instead of the original one. The idea behind Type System Extension is to have theses proxy automatically generated and correctly handled by the type system.

In order to have this work, we need to introduce a special parametrized type named Proxy. For instance you will first instanciate a Proxy<File> and then manipulate it as a File. A Proxy have the same methods as its parameter but all calls are forwarded using RPC.

To be able to pass the typechecker, the Proxy need to look for more directories so we can find the File class. Then, instead of fully typing and compiling it, we only need to parse it and extract the types of public methods and fields. This will build the type of the Proxy. As a consequence you cannot rely on haXe type inference of the proxied class, all the File methods must be correctly typed (in the case they’re not, maybe just removing them from the Proxy type is a sound possibility).

But this is not enough. RPC sometimes assume that the calls are synchronous, so every call is “waiting” for the answer of the server before returning. This is not possible with Flash and JS, since all network calls are asynchronous. The Proxy need then to make all methods return values asynchronous, for example transforming the method :

public function size() : Int

into the following :

public function size() : Async<Int>

with Async having the following definition for example :

class Async<T> {
      public var onValue : T -> Void; // event callback
}

This way instead of using transparantly the File class, you’ll do somethink like :

      var f : Proxy<File> = ... // instanciate
      f.write("hello world!"); // transparent call
      var size : Async<Int> = f.size(); // async call
      size.onValue = function(s : Int) {
           trace("file size is " + s);
      }

(the local variable types here are optional, they’re not needed since there is local type inference but it helps clarifying the example).

There is several problems left :

  • Classes platform : right now there is no “platform” information for a class, so if the File had one method that would return another File, the Proxy can’t know it should turn it into Async<Proxy<File>> instead of just Async<File> which is not correct.
  • Object persistance : since you create an object on the “other side”, you need to keep references of them. This can be done by keeping a connection open. All objects are free when the connection close (with maybe some chances to reconnect). But when an object is no longer needed, the client need to explicitly free it (by adding free() to the Proxy type). This is a limitation of the platforms that don’t offer finalizers for objects.

After being able to specify “platform” information for a class, it should be possible to write an Asynchronous RPC engine directly in haXe. This would enable inter-platform Proxy-transparent communications, with only some extensions to the type system.

Leave a Reply

You must be logged in to post a comment.