use of org.mvel2.debug.Debugger in project mvel by mvel.
the class MVELRuntime method execute.
/**
* Main interpreter.
*
* @param debugger Run in debug mode
* @param expression The compiled expression object
* @param ctx The root context object
* @param variableFactory The variable factory to be injected
* @return The resultant value
* @see org.mvel2.MVEL
*/
public static Object execute(boolean debugger, final CompiledExpression expression, final Object ctx, VariableResolverFactory variableFactory) {
Object v1, v2;
ExecutionStack stk = new ExecutionStack();
ASTNode tk = expression.getFirstNode();
Integer operator;
if (tk == null)
return null;
try {
do {
if (tk.fields == -1) {
/**
* This may seem silly and redundant, however, when an MVEL script recurses into a block
* or substatement, a new runtime loop is entered. Since the debugger state is not
* passed through the AST, it is not possible to forward the state directly. So when we
* encounter a debugging symbol, we check the thread local to see if there is are registered
* breakpoints. If we find them, we assume that we are debugging.
*
* The consequence of this of course, is that it's not ideal to compileShared expressions with
* debugging symbols which you plan to use in a production enviroment.
*/
if (debugger || (debugger = hasDebuggerContext())) {
try {
debuggerContext.get().checkBreak((LineLabel) tk, variableFactory, expression);
} catch (NullPointerException e) {
// do nothing for now. this isn't as calus as it seems.
}
}
continue;
} else if (stk.isEmpty()) {
stk.push(tk.getReducedValueAccelerated(ctx, ctx, variableFactory));
}
if (variableFactory.tiltFlag()) {
return stk.pop();
}
switch(operator = tk.getOperator()) {
case RETURN:
variableFactory.setTiltFlag(true);
return stk.pop();
case NOOP:
continue;
case TERNARY:
if (!stk.popBoolean()) {
// noinspection StatementWithEmptyBody
while (tk.nextASTNode != null && !(tk = tk.nextASTNode).isOperator(TERNARY_ELSE)) ;
}
stk.clear();
continue;
case TERNARY_ELSE:
return stk.pop();
case END_OF_STMT:
/**
* If the program doesn't end here then we wipe anything off the stack that remains.
* Althought it may seem like intuitive stack optimizations could be leveraged by
* leaving hanging values on the stack, trust me it's not a good idea.
*/
if (tk.nextASTNode != null) {
stk.clear();
}
continue;
}
stk.push(tk.nextASTNode.getReducedValueAccelerated(ctx, ctx, variableFactory), operator);
try {
while (stk.isReduceable()) {
if ((Integer) stk.peek() == CHOR) {
stk.pop();
v1 = stk.pop();
v2 = stk.pop();
if (!isEmpty(v2) || !isEmpty(v1)) {
stk.clear();
stk.push(!isEmpty(v2) ? v2 : v1);
} else
stk.push(null);
} else {
stk.op();
}
}
} catch (ClassCastException e) {
throw new CompileException("syntax error or incomptable types", new char[0], 0, e);
} catch (CompileException e) {
throw e;
} catch (Exception e) {
throw new CompileException("failed to compileShared sub expression", new char[0], 0, e);
}
} while ((tk = tk.nextASTNode) != null);
return stk.peek();
} catch (NullPointerException e) {
if (tk != null && tk.isOperator() && tk.nextASTNode != null) {
throw new CompileException("incomplete statement: " + tk.getName() + " (possible use of reserved keyword as identifier: " + tk.getName() + ")", tk.getExpr(), tk.getStart());
} else {
throw e;
}
} finally {
OptimizerFactory.clearThreadAccessorOptimizer();
}
}
use of org.mvel2.debug.Debugger in project mvel by mvel.
the class DebuggerTests method testDebuggerInvoke.
public void testDebuggerInvoke() {
count = 0;
MVELRuntime.resetDebugger();
MVELRuntime.setThreadDebugger(new Debugger() {
public int onBreak(Frame frame) {
if (frame.getFactory().isResolveable("a1")) {
a1++;
}
if (frame.getFactory().isResolveable("a4")) {
a4++;
System.out.println("HEI " + frame.getLineNumber());
}
count++;
return 0;
}
});
String src = "a1=7;\na2=8;\na3=9;\na4=10;\na5=11;\na6=12;\na7=13;\na8=14;";
ParserContext ctx = new ParserContext();
ctx.setSourceFile("mysource");
ctx.setDebugSymbols(true);
ExpressionCompiler c = new ExpressionCompiler(src, ctx);
CompiledExpression compexpr = c.compile();
System.out.println(decompile(compexpr));
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 1);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 3);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 7);
VariableResolverFactory factory = new DefaultLocalVariableResolverFactory();
MVEL.executeDebugger(compexpr, null, factory);
System.out.println(a1);
System.out.println(a4);
System.out.println(count);
assertEquals(2, a1);
// test passes but the breakpoint should be received by line 7, not by line 3
assertEquals(1, a4);
// three breakpoints FAILS
assertEquals(3, count);
}
use of org.mvel2.debug.Debugger in project mvel by mvel.
the class DebuggerTests method testBreakpointsAcrossComments2.
public void testBreakpointsAcrossComments2() {
ParserContext ctx = new ParserContext();
ctx.setSourceFile("test2.mv");
ctx.setDebugSymbols(true);
ExpressionCompiler compiler = new ExpressionCompiler(// 1
"// This is a comment\n" + // 2
"//Second comment line\n" + // 3
"//Third Comment Line\n" + // 4
"\n" + // 5
"//Test\n" + // 6
"System.out.println('4');\n" + // 7
"//System.out.println('5'); \n" + // 8
"a = 0;\n" + // 9
"b = 1;\n" + " a + b", // 10
ctx);
CompiledExpression compiled = compiler.compile();
MVELRuntime.registerBreakpoint("test2.mv", 6);
MVELRuntime.registerBreakpoint("test2.mv", 8);
MVELRuntime.registerBreakpoint("test2.mv", 9);
MVELRuntime.registerBreakpoint("test2.mv", 10);
final Set<Integer> breaked = new HashSet<Integer>();
Debugger testDebugger = new Debugger() {
public int onBreak(Frame frame) {
System.out.println("Breakpoint [source:" + frame.getSourceName() + "; line:" + frame.getLineNumber() + "]");
breaked.add(frame.getLineNumber());
return 0;
}
};
MVELRuntime.setThreadDebugger(testDebugger);
assertEquals(1, MVEL.executeDebugger(compiled, null, new MapVariableResolverFactory(createTestMap())));
assertEquals("did not break at expected lines", Make.Set.<Integer>$()._(6)._(8)._(9)._(10)._(), breaked);
}
use of org.mvel2.debug.Debugger in project mvel by mvel.
the class DebuggerTests method testDebuggerInvoke2.
public void testDebuggerInvoke2() {
count = 0;
MVELRuntime.resetDebugger();
MVELRuntime.setThreadDebugger(new Debugger() {
public int onBreak(Frame frame) {
count++;
return 0;
}
});
String src = "a1=7;\na2=8;\nSystem.out.println(\"h\");\nac=23;\nde=23;\nge=23;\ngef=34;";
ParserContext ctx = new ParserContext();
ctx.setSourceFile("mysource");
ctx.setDebugSymbols(true);
ExpressionCompiler c = new ExpressionCompiler(src, ctx);
CompiledExpression compexpr = c.compile();
System.out.println(decompile(compexpr));
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 1);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 2);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 3);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 4);
MVELRuntime.registerBreakpoint(ctx.getSourceFile(), 5);
VariableResolverFactory factory = new DefaultLocalVariableResolverFactory();
MVEL.executeDebugger(compexpr, null, factory);
System.out.println(count);
assertEquals(5, count);
}
use of org.mvel2.debug.Debugger in project mvel by mvel.
the class DebuggerTests method testBreakpointsAcrossComments.
public void testBreakpointsAcrossComments() {
String expression = // 1
"/** This is a comment\n" + // 2
" * Second comment line\n" + // 3
" * Third Comment Line\n" + // 4
" */\n" + // 5
"System.out.println('4');\n" + // 6
"System.out.println('5');\n" + // 7
"a = 0;\n" + // 8
"b = 1;\n" + // 9
"a + b";
ParserContext ctx = new ParserContext();
ctx.setSourceFile("test2.mv");
ctx.setDebugSymbols(true);
ExpressionCompiler compiler = new ExpressionCompiler(expression, ctx);
System.out.println("Expression:\n------------");
System.out.println(expression);
System.out.println("------------");
CompiledExpression compiled = compiler.compile();
MVELRuntime.registerBreakpoint("test2.mv", 9);
final Set<Integer> linesEncountered = new HashSet<Integer>();
Debugger testDebugger = new Debugger() {
public int onBreak(Frame frame) {
linesEncountered.add(frame.getLineNumber());
System.out.println("Breakpoint Encountered [source:" + frame.getSourceName() + "; line:" + frame.getLineNumber() + "]");
System.out.println("vars:" + frame.getFactory().getKnownVariables());
System.out.println("Resume Execution");
return 0;
}
};
MVELRuntime.setThreadDebugger(testDebugger);
assertEquals(1, MVEL.executeDebugger(compiled, null, new MapVariableResolverFactory(createTestMap())));
assertTrue("Debugger did not break at line 9", linesEncountered.contains(9));
}
Aggregations