The Object Teams Blog

Adding team spirit to your objects.

Posts Tagged ‘Java extension

Object Teams now has Lambdas (and more)

leave a comment »

In a previous post I announced that the Luna version of Object Teams will incorporate support for Java 8.

Now that the big rush towards March 18 is over, I took stock how Object Teams fits into the Luna stream, which finally contains all the bits for Java 8 support. The result:

We have our first builds with full support for OT/J on Java 8!

This means, you can now use lambda expressions and more even in OT/J programs, here’s a witness:

Lambda In Parameter Mapping

While this program may not make a lot of sense, it demonstrates a funny piece of syntax. Here’s what you see:

  • The regular class PersonCollection offers a method restrict that takes an argument of a functional type (Predicate)
  • Role Club.Members is played by PersonCollection and makes the base method available via a callout binding (lines 19 f)
  • The role wants to pass just an int value, where the base method expects a Predicate.
  • This incompatibility is bridged by a parameter mapping that maps a lambda expression to the expected parameter (line 20).

This looks funny, because two different uses of the token -> meet on a single line: the first -> is part of the lambda expression, separating the parameter from the body, the second -> is part of the parameter mapping, mapping the expression on the left to the parameter on the right.

Were I to chose the syntax in a green field situation, I would certainly not use the same token for such different purposes. But since we’re basically merging two independent language extensions I had no choice. After some worries that the combined language might not be parseable I’m much relieved to see it actually working!

A very similar situation actually exists concerning type annotations. More on that in a future post.

Remaining steps towards Luna

Merging the entire BETA_JAVA8 code base from JDT into Object Teams is done, but a few regressions (< 30 out of 84,000+ tests) remain from that exercise. But compared to the original JDT efforts for Java 8 this truly is peanuts 🙂

We only have one hurdle still to jump: our bytecode weaver is based on BCEL, for which no update for Java 8 is in sight. This means: we cannot weave into class files that use the Java 8 bytecode version, bummer!

So the real interesting question will be: can we get the long announced alternate weaver using ASM up to speed in time for Luna? I think we can, but it won’t hurt if you wish me luck in this endeavour.

And yes: one day I should start writing meaningful examples using Java 8 features in OT/J code…

Advertisements

Written by Stephan Herrmann

March 30, 2014 at 23:44

Posted in Eclipse, Object Teams, OTDT, OTJLD

Tagged with ,

Get for free what Coin doesn’t buy you

with 2 comments

Ralf Ebert recently blogged about how he extended Java to support a short-hand notation for throwing exceptions, like:

   throw "this is wrong";

It’s exactly the kind of enhancement you’d expect from Project Coin, but neither do they have it, nor would you want to wait until they release a solution.

At this point I gave it a few minutes, adapted Ralf’s code, applied Olivier’s suggestion wrapped it in a little plugin et voilà:

Install

Use this p2 repository, check two features…
Install Medal Java Extensions
…install and restart, and you’re ready to use your “Medal” IDE:
Medal IDE

So that’s basically the same as what Ralf already showed except:

It’s a module!

In contrast to Ralf’s patch of the JDT/Core my little plugin can be easily deployed and installed into any Eclipse (≥3.6.0). It just requires another small feature called “Object Teams Equinox Integration” or “OT/Equinox” for short.

So we’re all going to use our private own ”’dialects of Java?”’ Hm, firstly, once compiled this is of course plain Java, you wouldn’t be able to tell that the sources looked “funny”.

And: here’s the Boss Key: when somebody sniffs about your monitor, a single click will make Eclipse behave “normal”:
Boss Key
In other words, you can ”’dynamically enable/disable”’ this feature at runtime. The OT/Equinox Monitor view in the snapshot shows all known Team instances in the currently running IDE, and the little check boxes simply send activate() / deactivate() messages to the selected instance.

I coined the name Medal as our own playground for Java extensions of this kind. Feel free to suggest/contribute more!

Implementation

For a quick introduction on how to setup an OT/Equinox project in Eclipse I’d suggest our Quick Start (let me know if anything is unclear). For this particular case the key is in defining one little extension:
Extension
which the package explorer will render as:
Viewed in the Package Explorer
Drilling into the Team class ThrowString you’ll see:
ThrowString Outline
The Team class contains two Role classes:

  • Role DontReport binds to class ProblemReporter (not shown in the Outline), intercepts calls to ProblemReporter.cannotThrowType and if the type in question is String, simply ignores the “error”
  • Role Generate binds to class ThrowStatement to make sure the correct bytecodes for creating a RuntimeException are generated

Also, in the Outline you see both kinds of method bindings that are supported by Object Teams:

  • getExceptionType/setExceptionType are getter/setter definitions for field ThrowStatement.exceptionType (callout-to-field in OT/J jargon)
  • Things like “adjustType <- after resolve” establish method call interception (callin bindings in OT/J jargon – the “after” is symbolized by the specific icon)

The actual implementation is really simple, like (full listing of the first role):

protected class DontReport playedBy ProblemReporter {
        cannotThrowType <- replace cannotThrowType;
 
        @SuppressWarnings(&quot;basecall&quot;)
        callin void cannotThrowType(ASTNode exception, TypeBinding exceptionType) {
                if (exceptionType.id != TypeIds.T_JavaLangString)
                        // do the actual reporting only if it's not a string
                        base.cannotThrowType(exception, exceptionType);
        }
}
 

The base-call (base.cannotThrowType) delegates back to the original method, but only if the exception type is not String. The @SuppressWarnings annotation documents that not all control flows through this method will issue a base-call, a decision that deserves a second thought as it means the base plugin (here JDT/Core) does not perform its task fully as usual.

Intercepting resolve has the purpose of replacing type String with RuntimeException so that other parts of the Compiler and the IDE see a well-typed structure.

The method that performs the actual work is generateCode. Since this method is essentially based on the original implementation, the best way to see the difference is (select either the callin method or the callin binding):
Compare Menu
which gives you this compare editor:
Compare Editor
This neatly shows the two code blocks I inserted, one for creating the RuntimeException instance, the other for invoking its constructor. Or, if you just want to read the full role method:

/* This method is partly copied from the base method. */
@SuppressWarnings({"basecall", "inferredcallout"})
callin void generateCode(BlockScope currentScope, CodeStream codeStream) {
        if ((this.bits &amp; ASTNode.IsReachable) == 0)
                return;
        int pc = codeStream.position;
        // create a new RuntimeException:
        ReferenceBinding runtimeExceptionBinding = (ReferenceBinding) this.exceptionType;
        codeStream.new_(runtimeExceptionBinding);
        codeStream.dup();
        // generate the code for the original String expression:
        this.exception.generateCode(currentScope, codeStream, true);
        // call the constructor RuntimeException(String):
        MethodBinding ctor = runtimeExceptionBinding.getExactConstructor(new TypeBinding[]{this.stringType});
        codeStream.invoke(Opcodes.OPC_invokespecial, ctor, runtimeExceptionBinding);
        // throw it:
        codeStream.athrow();
        codeStream.recordPositionsFrom(pc, this.sourceStart);
}
 

You may also fetch the full sources of this little plug-in (plus a feature for easy deployment) to play around with and extend.

Next?

Ralf mentioned that he’d like to play with ways for also extending the syntax. For a starter on how this can be done with Object Teams I recommend my previous posts IDE for your own language embedded in Java? (part 1) and part 2.

Written by Stephan Herrmann

September 12, 2010 at 13:31