Thursday, November 12, 2009

Static Groovy, is it feasible?

Static Groovy seems to be a hot topic. There have been debates about it in the past. And recently, Alex's call for implementation has been posted on Groovy's DZone. Yesterday, Jochen's got his view about it here.

To me, I have been (and still) doing somethings to boost Groovy performance. Actually, it is based on the current call site implementation of Groovy 1.6. But that's another approach (As people said, performance is not only concern for static Groovy, early detection of errors is also what they want).

One of the biggest challenge of implementing static Groovy is that how could we implement a framework like Grails using it. This is really an interesting question to me, as Grails requires a lot of dynamic features of Groovy. So, I try to summarise what static Groovy should be capable of for making a Grails-like framework happen.

Firstly, GORM dynamic finders:
This kind of finders mainly uses missingMethod to perform their actions.

Considering this (posted as a comment in Jochen's blog):

class C {
  def findBy/s/(Object ...) { .. }
}


You may notice "s" in the method name. It is of type String and can be referenced in the method body.
So this is basically, findBy* of Grails. Missing method could be modelled in the same way. For example,

class C2 {
  def /s/(Object ...) { /* doing something with s */ }
}


Secondly, Adding dynamic methods:
This mainly uses in Grails plugins to extend capability of the framework.
The idea of category would be working perfectly for it.

main() {
  A.test()
}

class A {
}

class Plugin {
  static test(A self) { .. }
}


Resolving the test method would be a bit problem as it's not only through the class hierarchy of A, but also other classes that contain methods that crosscut A. It would be a bit easier for a compiler to resolve them, if we have a marker like @extension static test(A self) { ... } to help it.

Thirdly, interception for implementing invokeMethod:
This may probably involves the concept of AOP. But I will note use its terms here. Actually, the example is came from a work in the AOP area.

When you are going to intercept call of existing methods, this could be working:

class C {
  intercept *(X x) {
    proceed(x); // intercepting methodForX only
  }

  intercept *(Y y) {
    proceed(y); // intercepting methodForY only
  }

  intercept *(Object ...) { ... }

  def methodForX(X x) { .. }
 
  def methodForY(Y y) { .. }
}


This concept would be called local interception, where an interceptor is capable of only intercepting methods in the same class. System-wide interception would be doing the same. Anyway, it will be something like AspectJ, in eventually.

To sum up, there are really challenges to implement a static counterpart of Groovy. However as you might see, having enough features to implement a Grails-like framework using such language is not that easy. A lot of things need to be proper implemented. Anyway, this is really an interesting thing to do.


Friday, September 04, 2009

Using AsmNodeBuilder to Test Bytecodes with Pleasure

DSL of Groovy never made me bored. I am working on some bytecode transformation and having a number of tests to run.
Testing low-level transformation means dealing with JVM instructions. For example,

ILOAD 0
INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
LDC 0
INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter
             .compareLessThan(Ljava/lang/Object;Ljava/lang/Object;)Z
IFEQ L2


There is class MethodNode in the tree package of ASM. The class has the field instructions of class InsnList, which contains its method body. In the following, I have InsnList insn = methodNode.instructions; to perform some optimisation over it.

Before making AsmNodeBuilder, I had to create
a test data using Asm's Tree Nodes. Something looks like:

insn.add(new VarInsnNode(ILOAD, 0))

With Groovy and AsmNodeBuilder, now I can write:

insn.append {
  iload 0
}


When comparing results, I had to do:

assert insn.get(0).opcode == ILOAD
assert insn.get(0).var    == 0


Now, it becomes:

assertEquals asm { iload 0 }, insn[0]

Of course, I can also do:

assertEquals asm {
  iload 0
  invokestatic Integer,"valueOf",[int],Integer
}, insn


to assert all instructions in the list.

Look fun? Convinced? There are two classes you may use:

- InsnListHelper.groovy
- AsmNodeBuilder.java (generated from gen_asm_builder.groovy)

Here's how to
  1. call InsnListHelper.install() in the very beginning of your Groovy test case.
  2. Write a test case.
  3. use <InsnList>.append { ... } to create a method body.
  4. do your transformation.
  5. assert the result against an asm { ... } block. Note that Groovy's power assertion won't work with the block for some reasons, use assertEquals instead.
You can also look at an example here.


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.