use of org.mvel2.ast.And in project mvel by mvel.
the class CoreConfidenceTests method testJIRA209.
public void testJIRA209() {
Map vars = new LinkedHashMap();
vars.put("bal", new BigDecimal("999.99"));
String[] testCases = { // "bal < 100 || bal > 200",
"bal > 200 or bal < 100", "bal > 200 || bal < 100", "bal < 100 and bal > 200", "bal < 100 && bal > 200", "bal > 200 and bal < 100", "bal > 200 && bal < 100" };
Object val1, val2;
for (String expr : testCases) {
System.out.println("Evaluating '" + expr + "': ......");
val1 = MVEL.eval(expr, vars);
assertNotNull(val1);
Serializable compiled = MVEL.compileExpression(expr);
val2 = executeExpression(compiled, vars);
assertNotNull(val2);
assertEquals("expression did not evaluate correctly: " + expr, val1, val2);
}
}
use of org.mvel2.ast.And in project mvel by mvel.
the class CoreConfidenceTests method testConstructor.
public void testConstructor() {
String ex = " TestHelper.method(new Person('bob', 30), new Person('mark', 40, 999, 55, 10));\n";
ParserContext ctx = new ParserContext();
ctx.setStrongTyping(true);
ctx.addImport(TestHelper.class);
ctx.addImport(Person.class);
// string and then executing the wrong constructor on the Person class
try {
MVEL.compileExpression(ex, ctx);
fail("Constructor should not have been found.");
} catch (CompileException e) {
// yay.
}
// fail( "The Person constructor used in the expression does not exist, so an error should have been raised during compilation." );
}
use of org.mvel2.ast.And in project mvel by mvel.
the class MVELInterpretedRuntime method procBooleanOperator.
private int procBooleanOperator(int operator) {
switch(operator) {
case RETURN:
return RETURN;
case NOOP:
return -2;
case AND:
reduceRight();
if (!stk.peekBoolean()) {
if (unwindStatement(operator)) {
return -1;
} else {
stk.clear();
return OP_RESET_FRAME;
}
} else {
stk.discard();
return OP_RESET_FRAME;
}
case OR:
reduceRight();
if (stk.peekBoolean()) {
if (unwindStatement(operator)) {
return OP_TERMINATE;
} else {
stk.clear();
return OP_RESET_FRAME;
}
} else {
stk.discard();
return OP_RESET_FRAME;
}
case CHOR:
if (!BlankLiteral.INSTANCE.equals(stk.peek())) {
return OP_TERMINATE;
}
break;
case TERNARY:
if (!stk.popBoolean()) {
stk.clear();
ASTNode tk;
for (; ; ) {
if ((tk = nextToken()) == null || tk.isOperator(Operator.TERNARY_ELSE))
break;
}
}
return OP_RESET_FRAME;
case TERNARY_ELSE:
captureToEOS();
return OP_RESET_FRAME;
case END_OF_STMT:
if (hasMore()) {
holdOverRegister = stk.pop();
stk.clear();
}
return OP_RESET_FRAME;
}
return OP_CONTINUE;
}
use of org.mvel2.ast.And in project mvel by mvel.
the class JSRInlinerAdapter method visitJumpInsn.
/**
* Detects a JSR instruction and sets a flag to indicate we will need to do
* inlining.
*/
@Override
public void visitJumpInsn(final int opcode, final Label lbl) {
super.visitJumpInsn(opcode, lbl);
LabelNode ln = ((JumpInsnNode) instructions.getLast()).label;
if (opcode == JSR && !subroutineHeads.containsKey(ln)) {
subroutineHeads.put(ln, new BitSet());
}
}
use of org.mvel2.ast.And in project mvel by mvel.
the class JSRInlinerAdapter method emitSubroutine.
/**
* Emits one instantiation of one subroutine, specified by
* <code>instant</code>. May add new instantiations that are invoked by this
* one to the <code>worklist</code> parameter, and new try/catch blocks to
* <code>newTryCatchBlocks</code>.
*
* @param instant
* the instantiation that must be performed.
* @param worklist
* list of the instantiations that remain to be done.
* @param newInstructions
* the instruction list to which the instantiated code must be
* appended.
* @param newTryCatchBlocks
* the exception handler list to which the instantiated handlers
* must be appended.
*/
private void emitSubroutine(final Instantiation instant, final List<Instantiation> worklist, final InsnList newInstructions, final List<TryCatchBlockNode> newTryCatchBlocks, final List<LocalVariableNode> newLocalVariables) {
LabelNode duplbl = null;
if (LOGGING) {
log("--------------------------------------------------------");
log("Emitting instantiation of subroutine " + instant.subroutine);
}
// labels and jump targets as we go:
for (int i = 0, c = instructions.size(); i < c; i++) {
AbstractInsnNode insn = instructions.get(i);
Instantiation owner = instant.findOwner(i);
// Always remap labels:
if (insn.getType() == AbstractInsnNode.LABEL) {
// Translate labels into their renamed equivalents.
// Avoid adding the same label more than once. Note
// that because we own this instruction the gotoTable
// and the rangeTable will always agree.
LabelNode ilbl = (LabelNode) insn;
LabelNode remap = instant.rangeLabel(ilbl);
if (LOGGING) {
// TODO use of default toString().
log("Translating lbl #" + i + ':' + ilbl + " to " + remap);
}
if (remap != duplbl) {
newInstructions.add(remap);
duplbl = remap;
}
continue;
}
// that do not invoke each other.
if (owner != instant) {
continue;
}
if (LOGGING) {
log("Emitting inst #" + i);
}
if (insn.getOpcode() == RET) {
// Translate RET instruction(s) to a jump to the return label
// for the appropriate instantiation. The problem is that the
// subroutine may "fall through" to the ret of a parent
// subroutine; therefore, to find the appropriate ret label we
// find the lowest subroutine on the stack that claims to own
// this instruction. See the class javadoc comment for an
// explanation on why this technique is safe (note: it is only
// safe if the input is verifiable).
LabelNode retlabel = null;
for (Instantiation p = instant; p != null; p = p.previous) {
if (p.subroutine.get(i)) {
retlabel = p.returnLabel;
}
}
if (retlabel == null) {
// code.
throw new RuntimeException("Instruction #" + i + " is a RET not owned by any subroutine");
}
newInstructions.add(new JumpInsnNode(GOTO, retlabel));
} else if (insn.getOpcode() == JSR) {
LabelNode lbl = ((JumpInsnNode) insn).label;
BitSet sub = subroutineHeads.get(lbl);
Instantiation newinst = new Instantiation(instant, sub);
LabelNode startlbl = newinst.gotoLabel(lbl);
if (LOGGING) {
log(" Creating instantiation of subr " + sub);
}
// Rather than JSRing, we will jump to the inline version and
// push NULL for what was once the return value. This hack
// allows us to avoid doing any sort of data flow analysis to
// figure out which instructions manipulate the old return value
// pointer which is now known to be unneeded.
newInstructions.add(new InsnNode(ACONST_NULL));
newInstructions.add(new JumpInsnNode(GOTO, startlbl));
newInstructions.add(newinst.returnLabel);
// Insert this new instantiation into the queue to be emitted
// later.
worklist.add(newinst);
} else {
newInstructions.add(insn.clone(instant));
}
}
// Emit try/catch blocks that are relevant to this method.
for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext(); ) {
TryCatchBlockNode trycatch = it.next();
if (LOGGING) {
// TODO use of default toString().
log("try catch block original labels=" + trycatch.start + '-' + trycatch.end + "->" + trycatch.handler);
}
final LabelNode start = instant.rangeLabel(trycatch.start);
final LabelNode end = instant.rangeLabel(trycatch.end);
// Ignore empty try/catch regions
if (start == end) {
if (LOGGING) {
log(" try catch block empty in this subroutine");
}
continue;
}
final LabelNode handler = instant.gotoLabel(trycatch.handler);
if (LOGGING) {
// TODO use of default toString().
log(" try catch block new labels=" + start + '-' + end + "->" + handler);
}
if (start == null || end == null || handler == null) {
throw new RuntimeException("Internal error!");
}
newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, trycatch.type));
}
for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext(); ) {
LocalVariableNode lvnode = it.next();
if (LOGGING) {
log("local var " + lvnode.name);
}
final LabelNode start = instant.rangeLabel(lvnode.start);
final LabelNode end = instant.rangeLabel(lvnode.end);
if (start == end) {
if (LOGGING) {
log(" local variable empty in this sub");
}
continue;
}
newLocalVariables.add(new LocalVariableNode(lvnode.name, lvnode.desc, lvnode.signature, start, end, lvnode.index));
}
}
Aggregations