I'm the CEO of Tailrank. This is my old (personal) blog. See my new blog over at Feedblog.org. Tailrank is proudly hosted by ServerBeach.

My Photo

Reading

June 2008

Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

« Underground Cable Car | Main | EFF Anniversary »

Extending Java using Macros and JSE

I stumbled across JSE about 12 months ago while at Rojo and while very interested I just didn't have time to play with it. Of course I only spent about 5 minutes with the code so and it seems you need more like thirty.

JSE allows you to write macros which then are expanded into source prior to compile. This allows you to easily implement 'foreach' and 'unless' macros and the like (Examples are here).

Foreach is a big win for me because I don't really like the language extensions in JDK 1.5. This should have just been done with a macro language but Ra the SUN god seems to disagree.

The main motivation for setting this up was a 'duration' macro so that I could easily benchmark blocks of code.

For example a poor man's benchmark in Java is just:

long before = System.currentTimeMillis();
//do something expensive
long after = System.currentTimeMillis();
System.out.println( "Duration: " + (after-before) );

Which is a bit ugly.

After I installed JSE this is the first macro I implemented:

duration( "foo" ) {
    //something expensive
}

Which will then print "duration for 'foo': 100ms" ...

Which just rocks my world!

Implementing the macro is simple:

public syntax duration { 
  case #{ 
    duration (?:expression) 
      ?:statement 
  }: 
  return #{ 
    long before = System.currentTimeMillis();
    ?statement 
    long after = System.currentTimeMillis();
    System.out.println( "Duration: " + (after-before) );
  }; 
}

Update: One problem is that all my macro expanded source files have to have a .jse extension which I don't like. I'll have to rename everything. Ideally it would preprocess everything first and then only pre-process as I edit the files.

Update: JSE didn't have support for differential compiles. This means that every time I want to build I'd have to re-apply all my macros regardless if the file was updated or not. It turns out this is a simple patch (included below):

--- JseAntTask.java.orig        2005-09-29 15:10:48.000000000 -0700
+++ JseAntTask.java     2005-09-29 15:07:55.000000000 -0700
@@ -58,14 +58,27 @@
             args.append(new Boolean(lineup).toString());
             args.append(' ').append(new Boolean(recursive).toString());
             args.append(' ').append(new Boolean(verbose).toString());
+
+            int skipped = 0;
             for (int i = 0; i < jseFiles.length; i++) {
                 File jseFile = new File(jseDir, jseFiles[i]);
                 String base = jseFiles[i].substring(0, jseFiles[i].indexOf(".jse"));
                 File javaFile = new File(javaDir, base + ".java");
+
+                if ( javaFile.lastModified() >= jseFile.lastModified() ) {
+                    ++skipped;
+                    continue;
+                }
+
                 log("Generating " + javaFile + " from " + jseFile + ".", Project.MSG_VERBOSE);
                 args.append(' ').append(jseFile.getAbsolutePath());
                 args.append(' ').append(javaFile.getAbsolutePath());
             }
+
+            if ( skipped > 0 ) {
+                log( "Skipped N files (not updated): " + skipped );
+            }
+
             runJava("net.sf.jse.ant.JseAntHelper", args.toString());
         }
     }

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d8341cabb353ef00d8355527bc69e2

Listed below are links to weblogs that reference Extending Java using Macros and JSE:

Comments

The comments to this entry are closed.