Re: [groovy-user] AST transformation to exit loops
Oh. Indeed, I missed the setter ;)
Roshan Dawrani wrote:
>
> I guess it means you should do it as :
>
> class CustomSourceOperation extends
> CompilationUnit.PrimaryClassNodeOperation {
> ........
> public void visitForLoop(ForStatement forStatement) {
> Statement loopStmt = forStatement.getLoopBlock();
> if(!(loopStmt instanceof BlockStatement)) {
> BlockStatement newBlock = new BlockStatement();
> newBlock.addStatement(loopStmt);
> forStatement.setLoopBlock(newBlock);
> }
> ((BlockStatement) forStatement.getLoopBlock())
> .addStatement(buildInterruptNode());
> }
> ........
> }
>
> HTH.
> Roshan
>
> On Mon, Aug 31, 2009 at 8:36 PM, melix <cedric.champeau@...>
> wrote:
>
>>
>> Thanks,
>>
>> What do you mean exactly by stepping back one level ? I mean I see the
>> idea,
>> but I'm not sure on how I can do that with a visitor...
>>
>>
>> HamletDRC wrote:
>> >
>> > My first thought is to just create a new process. In the times in the
>> > past when I've considered spawning a thread vs. spawning a process,
>> > I've almost always regreted choosing threads instead of processes.
>> >
>> > Anyway, if the original loopblock is not an expression then you need
>> > to step back one level and wrap that statement in a BlockExpression
>> > and then put your interrupt handling in that same new block statement.
>> >
>> >
>> > --
>> > Hamlet D'Arcy
>> > hamletdrc@...
>> >
>> >
>> >
>> >
>> > On Wed, Aug 26, 2009 at 4:29 PM, melix<cedric.champeau@...>
>> wrote:
>> >> Hi,
>> >>
>> >> I have written a DSL which is mostly used by non programmers. They
>> write
>> >> "scripts" which are compiled at runtime and given some time to run. To
>> do
>> >> this, each script is run in its own thread. If a timeout is reached,
>> then
>> >> the thread is interrupted. However, you must know that Java does not
>> >> allow
>> >> "killing" a thread, so the elegant (and safe) way to interrupt a
>> thread
>> >> is
>> >> to send the interrupt signal. The thread should periodically check if
>> it
>> >> is
>> >> interrupted and stop.
>> >>
>> >> However, for my users, such considerations are far too difficult to
>> >> understand, and they may not intentionnaly write loops which never
>> exit.
>> >> The
>> >> result is that even if the script timed out, the thread keeps running
>> in
>> >> background.
>> >>
>> >> So I'm trying to use the AST transformations capabilities of Groovy
>> 1.6
>> >> to
>> >> add safe exit conditions at compile time. Basically, for every loop :
>> >>
>> >> for (;;) { ... }
>> >>
>> >> I'd like to add the following statement :
>> >>
>> >> if (Thread.currentThread().isInterrupted()) break;
>> >>
>> >> It doesn't matter if the early exit of a loop triggers some exception,
>> >> the
>> >> idea is to kill the thread.
>> >>
>> >> Same thing should be done on while loops. I managed to write a simple
>> >> test
>> >> case which demonstrates this :
>> >>
>> >> public class InterruptASTTransform {
>> >> public static Statement buildInterruptNode() {
>> >> return new BlockStatement(new Statement[]{
>> >> new IfStatement(
>> >> new BooleanExpression(new
>> >> MethodCallExpression(new
>> >> StaticMethodCallExpression(new ClassNode(Thread.class),
>> "currentThread",
>> >> new
>> >> ArgumentListExpression()), "isInterrupted", new
>> >> ArgumentListExpression())),
>> >> new BreakStatement(), new EmptyStatement())},
>> new
>> >> VariableScope());
>> >> }
>> >>
>> >> public static void main(String[] args) throws
>> NoSuchMethodException,
>> >> InvocationTargetException, IllegalAccessException,
>> InstantiationException
>> >> {
>> >> MyClassLoader cl = new MyClassLoader();
>> >> Class c = cl.parseClass(
>> >> "def t = new Thread({for (;;) {println 'ok'}} as
>> >> Runnable);"
>> >> +
>> >> "t.start();"
>> >> + "t.interrupt();"
>> >> );
>> >> ((Script) c.newInstance()).run();
>> >> }
>> >>
>> >> private static class MyClassLoader extends GroovyClassLoader {
>> >> <at> Override
>> >> protected CompilationUnit
>> >> createCompilationUnit(CompilerConfiguration config, CodeSource source)
>> {
>> >> CompilationUnit cu = super.createCompilationUnit(config,
>> >> source);
>> >> cu.addPhaseOperation(new CustomSourceOperation(),
>> >> Phases.SEMANTIC_ANALYSIS);
>> >> return cu;
>> >> }
>> >> }
>> >>
>> >> private final static class CustomSourceOperation extends
>> >> CompilationUnit.PrimaryClassNodeOperation {
>> >>
>> >> public void call(final SourceUnit source, GeneratorContext
>> >> context,
>> >> ClassNode classNode) throws CompilationFailedException {
>> >> classNode.visitContents(new ClassCodeVisitorSupport() {
>> >> <at> Override
>> >> protected SourceUnit getSourceUnit() {
>> >> return source;
>> >> }
>> >>
>> >> <at> Override
>> >> public void visitForLoop(ForStatement forStatement) {
>> >> ((BlockStatement)
>> >> forStatement.getLoopBlock()).addStatement(
>> >> buildInterruptNode());
>> >> }
>> >> });
>> >> }
>> >> }
>> >>
>> >> }
>> >>
>> >> However, I do have a problem. I can't see how I can add a statement if
>> >> the
>> >> original "loop block" from the for statement is not an expression
>> >> statement.
>> >> For example, the test case will fail with the following loop :
>> >>
>> >> for (;;) println 'ok'
>> >>
>> >> Is there any way to "replace" the loop block ? If not, how could I
>> >> proceed ?
>> >>
>> >> Thanks,
>> >>
>> >> Cedric
>> >>
>> >> ________________________________
>> >> View this message in context: AST transformation to exit loops
>> >> Sent from the groovy - user mailing list archive at Nabble.com.
>> >>
>> >
>> > ---------------------------------------------------------------------
>> > To unsubscribe from this list, please visit:
>> >
>> > http://xircles.codehaus.org/manage_email
>> >
>> >
>> >
>> >
>> > -----
>> > --
>> > Hamlet D'Arcy
>> >
>> >
>>
>> --
>> View this message in context:
>> http://www.nabble.com/AST-transformation-to-exit-loops-tp25159084p25225055.html
>> Sent from the groovy - user mailing list archive at Nabble.com.
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
>>
>> http://xircles.codehaus.org/manage_email
>>
>>
>>
>
>
--
--
View this message in context: http://www.nabble.com/AST-transformation-to-exit-loops-tp25159084p25235556.html
Sent from the groovy - user mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email