[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