[ImageJ-devel] Macros and scripting in Imagej 2.0
Johannes Schindelin
Johannes.Schindelin at gmx.de
Fri Sep 9 01:00:20 CDT 2011
Hi,
On Wed, 7 Sep 2011, Johannes Schindelin wrote:
> Grant wrote:
>
> > As mentioned in the chat, BeanShell is interesting for the fact that
> > it is syntactically very similar to the ImageJ Macro language - The
> > Macro Language is a DSL (domain specific language) for image
> > processing and manipulating the ImageJ environment. "Porting" it to
> > Beanshell (as suggested by Dscho) sounds like a good idea.
>
> But it is not at all without problems. The most urgent problem is that
> the macro language has this quite surprising feature that you can assign
> variables thusly:
>
> getDimensions(width, height, depth, channels, frames);
>
> That is so out of line with C/Java like languages that it is impossible
> to support in Beanshell. I am currently looking into hacking the
> Beanshell interpreter to work around such problems, but it is hard.
So here are my findings (after spending way too much time on this issue):
If I (ab-)use javassist before loading Beanshell to do the following:
CtClass clazz = pool.get("bsh.BSHArguments");
CtMethod method = CtNewMethod.make(
"public String[] getParameterNames() {\n"
+ " String[] result = new String[jjtGetNumChildren()];\n"
+ " for (int i = 0; i < result.length; i++) try {\n"
+ " result[i] = ((bsh.SimpleNode)jjtGetChild(i)).firstToken.image;\n"
+ " } catch (Exception e) {}\n"
+ " return result;\n"
+ "}", clazz);
clazz.addMethod(method);
pool.toClass(clazz);
clazz = pool.get("bsh.BSHMethodInvocation");
method = clazz.getMethod("eval", "(Lbsh/CallStack;Lbsh/Interpreter;)Ljava/lang/Object;");
method.insertBefore("Object result = "
+ "BSHHelper.handleSpecial(getNameNode().getName($1.top()).toString(),"
+ " getArgsNode().getParameterNames(), $1.top());"
+ "if (result != Boolean.FALSE) return result;");
pool.toClass(clazz);
... and then have the following definition in a class called BSHHelper:
public static Object handleSpecial3(String functionName,
String[] firstTokens, NameSpace nameSpace) {
if (!functionName.equals("getText"))
return Boolean.FALSE;
try {
nameSpace.setTypedVariable(firstTokens[0],
String.class, "Hello", false);
} catch (Exception e) {
IJ.handleException(e);
}
return null;
}
... then a Beanshell script "getText(blabla);" will define the variable
"blabla" to the value "Hello".
This is all horribly convoluted and I need to streamline it and introduce
checks and stuff, but at least I now know that we can overcome that
obstacle.
But that'll have to wait until after sleeping.
Ciao,
Johannes
More information about the ImageJ-devel
mailing list