Sunday, July 26, 2009

Improved Complex Number in Groovy

Thank you for last comment in the previous blog. Here's the improved version of Complex Number.

Number.metaClass.plus = { n ->
  if(n instanceof Imaginary) {
    new Complex(r:delegate, i:n.v)
  }
}
Number.metaClass.getI = { ->
  new Imaginary(v: delegate)
}

class Complex {
  def r
  def i
  String toString() {
    "$r + ${i}i"
  }
}
class Imaginary {
  def v
  def plus(n) {
    if(n instanceof Number) new Complex(r:n, i:this.v)
  }
}

def b = 2 + 2.4.i
def c = 4.2.i + 2
println b
println b.class
println c
println c.class


Thursday, June 11, 2009

Complex Number in Groovy

Here's a quick note of making Groovy to support complex numbers:

1. override number operations via metaclass:
Number.metaClass.plus = { n ->
  if(n instanceof Imaginary) {
    return new Complex(r:delegate, i:n.v)
  }
}

2. define class Complex to hold real, r, and imaginary, i, parts
class Complex {
  def r
  def i
  String toString() {
    "$r + ${i}i"
  }
}


3. create class Imaginary to be a wrapper class (I borrow this idea from Scala's implicit converter).
class Imaginary {
  def v
}


4. define i as a global closure. It would be in DefaultGroovyMethods, actually.
def i = { v ->
  new Imaginary(v:v)
}


Then when you write:
def b = 2 + i(2.4)
println b
println b.class


This prints "2 + 2.4i" and the type of b is class Complex.

Saturday, June 06, 2009

Fortress - Hello World

Here's my early experiment of running Fortress Hello world program, which is listed below (taken from the tutorial at MIT by the Fortress team):

component hello
export Executable

run() = println("Hello, World !")

end


I'm a bit surprised that its compilation time is "really" slow. I may be guessing that it's caused by type inference in the Fortress compiler. JVM 1.6.0_12 was used in the experiment. One of my quick conclusion is that Fortress is not suitable for scripting. But I think its compiled program will not be slow (as I mentioned that I am suspecting its type inference engine that makes scripting slow).

Here's 5 times of running:

chanwit@lb /cygdrive/c/fortress/fortress_3625
$ time `bin/fortress chanwit/hello.fss`
bash: Hello,: command not found

real    0m11.393s
user    0m0.244s
sys     0m0.199s

chanwit@lb /cygdrive/c/fortress/fortress_3625
$ time `bin/fortress chanwit/hello.fss`
bash: Hello,: command not found

real    0m11.486s
user    0m0.181s
sys     0m0.214s

chanwit@lb /cygdrive/c/fortress/fortress_3625
$ time `bin/fortress chanwit/hello.fss`
bash: Hello,: command not found

real    0m11.412s
user    0m0.213s
sys     0m0.215s

chanwit@lb /cygdrive/c/fortress/fortress_3625
$ time `bin/fortress chanwit/hello.fss`
bash: Hello,: command not found

real    0m11.377s
user    0m0.197s
sys     0m0.198s

chanwit@lb /cygdrive/c/fortress/fortress_3625
$ time `bin/fortress chanwit/hello.fss`
bash: Hello,: command not found

real    0m11.432s
user    0m0.229s
sys     0m0.198s


Friday, February 27, 2009

Hybrid call site model based on Groovy

I'm trying to model a class structure that support the following features:
  • callsite; separating call and execution semantics to
    • support before/after advice of AspectJ's pointcut-advice model (possible support around advice)
    • further support my typing concerns.
  • support statically resolved callsite (resolving is done at compile-time, but also changeable at runtime)
  • support dynamically resolved callsite (as done in Groovy, JRuby, etc.)
  • must be compatible with Java. i.e., Generated classes can be used as normal Java classes.
My below POC is based on Alex T. implementation. But instead of showing all kind of callsite, I show you here only statically resolved callsite. This callsite is surely fast (I hope it's gonna be at the same level of Java) because it's compile-time thing. The interesting point is that, I have a special class loader for these callsites, namely StaticCallSiteClassLoader. What does it do?  This class loader allows re-definition of these callsites.

What I have observed so far is that All of my callsite classes (_0_println, _1_ctor, _2_render and _3_index) have not been loaded when there is no "direct" reference to them. So they can be fully lazy loading using the StaticCallSiteClassLoader. (I've checked this with java --verbose)

How could these callsites are changed at runtime?
You may see the acallsite, an CallSite array that hold all callsites in the example class. It's intended to be public and can be accessed by, for example, a virtual meta-class.
So what's a virtual meta-class? It's kind of meta-class, but in this case, it's not for controlling behaviour of the class (because all dispatch are static). It's for changing behaviour of callsite by reassigning new callsites object to the callsite array.

Notic that I use WeakReference to hold a callsite class loader. This will be making the class loader GC-able. That's it, after deferenceing all old callsites out of the callsite array, the class loader can be unloaded. Therefore, all callsite class definition are gone as well. Then, we can create a new set of callsites for the current class. This technique would be flexible enough for:
  • changing a static call to be a dynamic call
  • changing a dynamic call back to a static call
  • installing a woven callsite with before, after advice (it features dynamic AOP)
  • inserting type advice, which can lead to bytecode inlining
  • design a hybrid type system to support both static and dynamic typing in the same system.
import java.lang.ref.WeakReference;

import runtime.CallSite;
import classloader.StaticCallSiteClassLoader;
import dm.Render;

public class TestController {

    /* synthetic */
    private static WeakReference<StaticCallSiteClassLoader> cl;

    /* synthetic normal callsite */
    public static class _0_println extends CallSite {...}

    /* synthetic constructor */
    public static class _1_ctor extends CallSite {...}

    /* synthetic inter-type declaration callsite. statically resolved */
    public static class _2_render extends CallSite {...}

    /* synthetic property callsite */
    public static class _3_index extends CallSite {...}

    /* synthetic */
    public static CallSite[] acallsite;

    static {
        cl = new WeakReference<StaticCallSiteClassLoader>(
                    new StaticCallSiteClassLoader(TestController.class)
        );
        acallsite = new CallSite[4];
        acallsite[0] = cl.get().get("_0_println");
        acallsite[1] = cl.get().get("_1_ctor");
        acallsite[2] = cl.get().get("_2_render");
        acallsite[3] = cl.get().get("_3_index");
    }

    public TestController(){
        super();
    }

    public int getIndex() {
        return 10;
    }

    public static void main(String[] args) {
        acallsite[0].callStatic("hello world");
        TestController t = (TestController)(acallsite[1].callConstructor());
        acallsite[2].call(t, "hello world");
        acallsite[0].callStatic(acallsite[3].callGetProperty(t, "index"));
    }

}