Search in sources :

Example 16 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ASMAccessorOptimizer method getBeanProperty.

private Object getBeanProperty(Object ctx, String property) throws IllegalAccessException, InvocationTargetException {
    assert debug("\n  **  ENTER -> {bean: " + property + "; ctx=" + ctx + "}");
    if ((pCtx == null ? currType : pCtx.getVarOrInputTypeOrNull(property)) == Object.class && !pCtx.isStrongTyping()) {
        currType = null;
    }
    if (returnType != null && returnType.isPrimitive()) {
        //noinspection unchecked
        wrapPrimitive(returnType);
    }
    boolean classRef = false;
    Class<?> cls;
    if (ctx instanceof Class) {
        if (MVEL.COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS && "class".equals(property)) {
            ldcClassConstant((Class<?>) ctx);
            return ctx;
        }
        cls = (Class<?>) ctx;
        classRef = true;
    } else if (ctx != null) {
        cls = ctx.getClass();
    } else {
        cls = null;
    }
    if (hasPropertyHandler(cls)) {
        PropertyHandler prop = getPropertyHandler(cls);
        if (prop instanceof ProducesBytecode) {
            ((ProducesBytecode) prop).produceBytecodeGet(mv, property, variableFactory);
            return prop.getProperty(property, ctx, variableFactory);
        } else {
            throw new RuntimeException("unable to compileShared: custom accessor does not support producing bytecode: " + prop.getClass().getName());
        }
    }
    Member member = cls != null ? getFieldOrAccessor(cls, property) : null;
    if (member != null && classRef && (member.getModifiers() & Modifier.STATIC) == 0) {
        member = null;
    }
    if (member != null && hasGetListeners()) {
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn(member.getName());
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "integration/GlobalListenerFactory", "notifyGetListeners", "(Ljava/lang/Object;Ljava/lang/String;L" + NAMESPACE + "integration/VariableResolverFactory;)V");
        notifyGetListeners(ctx, member.getName(), variableFactory);
    }
    if (first) {
        if ("this".equals(property)) {
            assert debug("ALOAD 2");
            mv.visitVarInsn(ALOAD, 2);
            return thisRef;
        } else if (variableFactory != null && variableFactory.isResolveable(property)) {
            if (variableFactory.isIndexedFactory() && variableFactory.isTarget(property)) {
                int idx;
                try {
                    loadVariableByIndex(idx = variableFactory.variableIndexOf(property));
                } catch (Exception e) {
                    throw new OptimizationFailure(property);
                }
                return variableFactory.getIndexedVariableResolver(idx).getValue();
            } else {
                try {
                    loadVariableByName(property);
                } catch (Exception e) {
                    throw new OptimizationFailure("critical error in JIT", e);
                }
                return variableFactory.getVariableResolver(property).getValue();
            }
        } else {
            assert debug("ALOAD 1");
            mv.visitVarInsn(ALOAD, 1);
        }
    }
    if (member instanceof Field) {
        Object o = ((Field) member).get(ctx);
        if (((member.getModifiers() & STATIC) != 0)) {
            // Check if the static field reference is a constant and a primitive.
            if ((member.getModifiers() & FINAL) != 0 && (o instanceof String || ((Field) member).getType().isPrimitive())) {
                o = ((Field) member).get(null);
                assert debug("LDC " + valueOf(o));
                mv.visitLdcInsn(o);
                wrapPrimitive(o.getClass());
                if (hasNullPropertyHandler()) {
                    if (o == null) {
                        o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
                    }
                    writeOutNullHandler(member, 0);
                }
                return o;
            } else {
                assert debug("GETSTATIC " + getDescriptor(member.getDeclaringClass()) + "." + member.getName() + "::" + getDescriptor(((Field) member).getType()));
                mv.visitFieldInsn(GETSTATIC, getInternalName(member.getDeclaringClass()), member.getName(), getDescriptor(returnType = ((Field) member).getType()));
            }
        } else {
            assert debug("CHECKCAST " + getInternalName(cls));
            mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
            assert debug("GETFIELD " + property + ":" + getDescriptor(((Field) member).getType()));
            mv.visitFieldInsn(GETFIELD, getInternalName(cls), property, getDescriptor(returnType = ((Field) member).getType()));
        }
        returnType = ((Field) member).getType();
        if (hasNullPropertyHandler()) {
            if (o == null) {
                o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
            }
            writeOutNullHandler(member, 0);
        }
        return o;
    } else if (member != null) {
        Object o;
        if (first) {
            assert debug("ALOAD 1 (B)");
            mv.visitVarInsn(ALOAD, 1);
        }
        try {
            o = ((Method) member).invoke(ctx, EMPTYARG);
            if (returnType != member.getDeclaringClass()) {
                assert debug("CHECKCAST " + getInternalName(member.getDeclaringClass()));
                mv.visitTypeInsn(CHECKCAST, getInternalName(member.getDeclaringClass()));
            }
            returnType = ((Method) member).getReturnType();
            assert debug("INVOKEVIRTUAL " + member.getName() + ":" + returnType);
            mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(member.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
        } catch (IllegalAccessException e) {
            Method iFaceMeth = determineActualTargetMethod((Method) member);
            if (iFaceMeth == null)
                throw new PropertyAccessException("could not access field: " + cls.getName() + "." + property, expr, st, e);
            assert debug("CHECKCAST " + getInternalName(iFaceMeth.getDeclaringClass()));
            mv.visitTypeInsn(CHECKCAST, getInternalName(iFaceMeth.getDeclaringClass()));
            returnType = iFaceMeth.getReturnType();
            assert debug("INVOKEINTERFACE " + member.getName() + ":" + returnType);
            mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(iFaceMeth.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
            o = iFaceMeth.invoke(ctx, EMPTYARG);
        } catch (IllegalArgumentException e) {
            if (member.getDeclaringClass().equals(ctx)) {
                try {
                    Class c = Class.forName(member.getDeclaringClass().getName() + "$" + property);
                    throw new CompileException("name collision between innerclass: " + c.getCanonicalName() + "; and bean accessor: " + property + " (" + member.toString() + ")", expr, tkStart);
                } catch (ClassNotFoundException e2) {
                //fallthru
                }
            }
            throw e;
        }
        if (hasNullPropertyHandler()) {
            if (o == null)
                o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
            writeOutNullHandler(member, 0);
        }
        return o;
    } else if (ctx instanceof Map && (((Map) ctx).containsKey(property) || nullSafe)) {
        assert debug("CHECKCAST java/util/Map");
        mv.visitTypeInsn(CHECKCAST, "java/util/Map");
        assert debug("LDC: \"" + property + "\"");
        mv.visitLdcInsn(property);
        assert debug("INVOKEINTERFACE: get");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        return ((Map) ctx).get(property);
    } else if (first && "this".equals(property)) {
        assert debug("ALOAD 2");
        // load the thisRef value.
        mv.visitVarInsn(ALOAD, 2);
        return this.thisRef;
    } else if ("length".equals(property) && ctx.getClass().isArray()) {
        anyArrayCheck(ctx.getClass());
        assert debug("ARRAYLENGTH");
        mv.visitInsn(ARRAYLENGTH);
        wrapPrimitive(int.class);
        return getLength(ctx);
    } else if (LITERALS.containsKey(property)) {
        Object lit = LITERALS.get(property);
        if (lit instanceof Class) {
            ldcClassConstant((Class) lit);
        }
        return lit;
    } else {
        Object ts = tryStaticAccess();
        if (ts != null) {
            if (ts instanceof Class) {
                ldcClassConstant((Class) ts);
                return ts;
            } else if (ts instanceof Method) {
                writeFunctionPointerStub(((Method) ts).getDeclaringClass(), (Method) ts);
                return ts;
            } else {
                Field f = (Field) ts;
                if ((f.getModifiers() & FINAL) != 0) {
                    Object finalVal = f.get(null);
                    assert debug("LDC " + valueOf(finalVal));
                    mv.visitLdcInsn(finalVal);
                    wrapPrimitive(finalVal.getClass());
                    return finalVal;
                } else {
                    assert debug("GETSTATIC " + getInternalName(f.getDeclaringClass()) + "." + ((Field) ts).getName() + "::" + getDescriptor(f.getType()));
                    mv.visitFieldInsn(GETSTATIC, getInternalName(f.getDeclaringClass()), f.getName(), getDescriptor(returnType = f.getType()));
                    return f.get(null);
                }
            }
        } else if (ctx instanceof Class) {
            /**
         * This is our ugly support for function pointers.  This works but needs to be re-thought out at some
         * point.
         */
            Class c = (Class) ctx;
            for (Method m : c.getMethods()) {
                if (property.equals(m.getName())) {
                    if (MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
                        assert debug("POP");
                        mv.visitInsn(POP);
                        assert debug("INVOKESTATIC " + m.getName());
                        mv.visitMethodInsn(INVOKESTATIC, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
                        returnType = m.getReturnType();
                        return m.invoke(null, EMPTY_OBJ_ARR);
                    } else {
                        writeFunctionPointerStub(c, m);
                        return m;
                    }
                }
            }
            try {
                Class subClass = findClass(variableFactory, c.getName() + "$" + property, pCtx);
                ldcClassConstant(subClass);
                return subClass;
            } catch (ClassNotFoundException cnfe) {
            // fall through.
            }
        } else if (MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
            return getMethod(ctx, property);
        }
        if (ctx == null) {
            throw new PropertyAccessException("unresolvable property or identifier: " + property, expr, st);
        } else {
            throw new PropertyAccessException("could not access: " + property + "; in class: " + ctx.getClass().getName(), expr, st);
        }
    }
}
Also used : IOException(java.io.IOException) PropertyHandler(org.mvel2.integration.PropertyHandler) Map(java.util.Map)

Example 17 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ASMAccessorOptimizer method compileAccessor.

private Accessor compileAccessor() {
    assert debug("<<INITIATE COMPILE>>");
    Object curr = ctx;
    try {
        if (!MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING) {
            while (cursor < end) {
                switch(nextSubToken()) {
                    case BEAN:
                        curr = getBeanProperty(curr, capture());
                        break;
                    case METH:
                        curr = getMethod(curr, capture());
                        break;
                    case COL:
                        curr = getCollectionProperty(curr, capture());
                        break;
                    case WITH:
                        curr = getWithProperty(curr);
                        break;
                }
                // check to see if a null safety is enabled on this property.
                if (fields == -1) {
                    if (curr == null) {
                        if (nullSafe) {
                            throw new OptimizationNotSupported();
                        }
                        break;
                    } else {
                        fields = 0;
                    }
                }
                first = false;
                if (nullSafe && cursor < end) {
                    assert debug("DUP");
                    mv.visitInsn(DUP);
                    Label j = new Label();
                    assert debug("IFNONNULL : jump");
                    mv.visitJumpInsn(IFNONNULL, j);
                    assert debug("ARETURN");
                    mv.visitInsn(ARETURN);
                    assert debug("LABEL:jump");
                    mv.visitLabel(j);
                }
            }
        } else {
            while (cursor < end) {
                switch(nextSubToken()) {
                    case BEAN:
                        curr = getBeanPropertyAO(curr, capture());
                        break;
                    case METH:
                        curr = getMethod(curr, capture());
                        break;
                    case COL:
                        curr = getCollectionPropertyAO(curr, capture());
                        break;
                    case WITH:
                        curr = getWithProperty(curr);
                        break;
                }
                // check to see if a null safety is enabled on this property.
                if (fields == -1) {
                    if (curr == null) {
                        if (nullSafe) {
                            throw new OptimizationNotSupported();
                        }
                        break;
                    } else {
                        fields = 0;
                    }
                }
                first = false;
                if (nullSafe && cursor < end) {
                    assert debug("DUP");
                    mv.visitInsn(DUP);
                    Label j = new Label();
                    assert debug("IFNONNULL : jump");
                    mv.visitJumpInsn(IFNONNULL, j);
                    assert debug("ARETURN");
                    mv.visitInsn(ARETURN);
                    assert debug("LABEL:jump");
                    mv.visitLabel(j);
                }
            }
        }
        val = curr;
        _finishJIT();
        return _initializeAccessor();
    } catch (InvocationTargetException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (IllegalAccessException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (IndexOutOfBoundsException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (PropertyAccessException e) {
        throw new CompileException(e.getMessage(), expr, st, e);
    } catch (CompileException e) {
        throw e;
    } catch (NullPointerException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (OptimizationNotSupported e) {
        throw e;
    } catch (Exception e) {
        throw new CompileException(e.getMessage(), expr, st, e);
    }
}
Also used : Label(org.mvel2.asm.Label) OptimizationNotSupported(org.mvel2.optimizers.OptimizationNotSupported) IOException(java.io.IOException)

Example 18 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ReflectiveAccessorOptimizer method optimizeSetAccessor.

public Accessor optimizeSetAccessor(ParserContext pCtx, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory, boolean rootThisRef, Object value, Class ingressType) {
    this.rootNode = this.currNode = null;
    this.expr = property;
    this.start = start;
    this.first = true;
    this.length = start + offset;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    this.ingressType = ingressType;
    char[] root = null;
    int split = findLastUnion();
    PropertyVerifier verifier = new PropertyVerifier(property, this.pCtx = pCtx);
    if (split != -1) {
        root = subset(property, 0, split++);
        //todo: must use the property verifier.
        property = subset(property, split, property.length - split);
    }
    if (root != null) {
        this.length = end = (this.expr = root).length;
        compileGetChain();
        ctx = this.val;
    }
    if (ctx == null) {
        throw new PropertyAccessException("could not access property: " + new String(property, this.start, length) + "; parent is null: " + new String(expr), expr, this.start);
    }
    try {
        this.length = end = (this.expr = property).length;
        int st;
        this.cursor = st = 0;
        skipWhitespace();
        if (collection) {
            st = cursor;
            if (cursor == end)
                throw new PropertyAccessException("unterminated '['", expr, this.start);
            if (scanTo(']'))
                throw new PropertyAccessException("unterminated '['", expr, this.start);
            String ex = new String(property, st, cursor - st);
            if (ctx instanceof Map) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Map.class)) {
                    propHandlerSet(ex, ctx, Map.class, value);
                } else {
                    //noinspection unchecked
                    ((Map) ctx).put(eval(ex, ctx, variableFactory), convert(value, returnType = verifier.analyze()));
                    addAccessorNode(new MapAccessorNest(ex, returnType));
                }
                return rootNode;
            } else if (ctx instanceof List) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(List.class)) {
                    propHandlerSet(ex, ctx, List.class, value);
                } else {
                    //noinspection unchecked
                    ((List) ctx).set(eval(ex, ctx, variableFactory, Integer.class), convert(value, returnType = verifier.analyze()));
                    addAccessorNode(new ListAccessorNest(ex, returnType));
                }
                return rootNode;
            } else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
                propHandlerSet(ex, ctx, ctx.getClass(), value);
                return rootNode;
            } else if (ctx.getClass().isArray()) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Array.class)) {
                    propHandlerSet(ex, ctx, Array.class, value);
                } else {
                    //noinspection unchecked
                    Array.set(ctx, eval(ex, ctx, variableFactory, Integer.class), convert(value, getBaseComponentType(ctx.getClass())));
                    addAccessorNode(new ArrayAccessorNest(ex));
                }
                return rootNode;
            } else {
                throw new PropertyAccessException("cannot bind to collection property: " + new String(property) + ": not a recognized collection type: " + ctx.getClass(), expr, this.st);
            }
        } else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
            propHandlerSet(new String(property), ctx, ctx.getClass(), value);
            return rootNode;
        }
        String tk = new String(property, 0, length);
        if (hasSetListeners()) {
            notifySetListeners(ctx, tk, variableFactory, value);
            addAccessorNode(new Notify(tk));
        }
        Member member = getFieldOrWriteAccessor(ctx.getClass(), tk, value == null ? null : ingressType);
        if (member instanceof Field) {
            Field fld = (Field) member;
            if (value != null && !fld.getType().isAssignableFrom(value.getClass())) {
                if (!canConvert(fld.getType(), value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + fld.getType(), this.expr, this.start);
                }
                fld.set(ctx, convert(value, fld.getType()));
                addAccessorNode(new DynamicFieldAccessor(fld));
            } else if (value == null && fld.getType().isPrimitive()) {
                fld.set(ctx, PropertyTools.getPrimitiveInitialValue(fld.getType()));
                addAccessorNode(new FieldAccessor(fld));
            } else {
                fld.set(ctx, value);
                addAccessorNode(new FieldAccessor(fld));
            }
        } else if (member != null) {
            Method meth = (Method) member;
            if (value != null && !meth.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
                if (!canConvert(meth.getParameterTypes()[0], value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + meth.getParameterTypes()[0], this.expr, this.start);
                }
                meth.invoke(ctx, convert(value, meth.getParameterTypes()[0]));
            } else if (value == null && meth.getParameterTypes()[0].isPrimitive()) {
                meth.invoke(ctx, PropertyTools.getPrimitiveInitialValue(meth.getParameterTypes()[0]));
            } else {
                meth.invoke(ctx, value);
            }
            addAccessorNode(new SetterAccessor(meth));
        } else if (ctx instanceof Map) {
            //noinspection unchecked
            ((Map) ctx).put(tk, value);
            addAccessorNode(new MapAccessor(tk));
        } else {
            throw new PropertyAccessException("could not access property (" + tk + ") in: " + ingressType.getName(), this.expr, this.start);
        }
    } catch (InvocationTargetException e) {
        throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
    } catch (IllegalAccessException e) {
        throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
    } catch (IllegalArgumentException e) {
        throw new PropertyAccessException("error binding property: " + new String(property) + " (value <<" + value + ">>::" + (value == null ? "null" : value.getClass().getCanonicalName()) + ")", this.expr, st, e);
    }
    return rootNode;
}
Also used : PropertyVerifier(org.mvel2.compiler.PropertyVerifier) List(java.util.List) Map(java.util.Map) WeakHashMap(java.util.WeakHashMap)

Example 19 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class MVELInterpretedRuntime method parseAndExecuteInterpreted.

/**
   * Main interpreter loop.
   *
   * @return value
   */
private Object parseAndExecuteInterpreted() {
    ASTNode tk = null;
    int operator;
    lastWasIdentifier = false;
    try {
        while ((tk = nextToken()) != null) {
            holdOverRegister = null;
            if (lastWasIdentifier && lastNode.isDiscard()) {
                stk.discard();
            }
            /**
         * If we are at the beginning of a statement, then we immediately push the first token
         * onto the stack.
         */
            if (stk.isEmpty()) {
                stk.push(tk.getReducedValue(ctx, ctx, variableFactory));
                /**
           * If this is a substatement, we need to move the result into the d-stack to preserve
           * proper execution order.
           */
                if (tk instanceof Substatement && (tk = nextToken()) != null) {
                    if (isArithmeticOperator(operator = tk.getOperator())) {
                        stk.push(nextToken().getReducedValue(ctx, ctx, variableFactory), operator);
                        if (procBooleanOperator(arithmeticFunctionReduction(operator)) == -1)
                            return stk.peek();
                        else
                            continue;
                    }
                } else {
                    continue;
                }
            }
            if (variableFactory.tiltFlag()) {
                return stk.pop();
            }
            switch(procBooleanOperator(operator = tk.getOperator())) {
                case RETURN:
                    variableFactory.setTiltFlag(true);
                    return stk.pop();
                case OP_TERMINATE:
                    return stk.peek();
                case OP_RESET_FRAME:
                    continue;
                case OP_OVERFLOW:
                    if (!tk.isOperator()) {
                        if (!(stk.peek() instanceof Class)) {
                            throw new CompileException("unexpected token or unknown identifier:" + tk.getName(), expr, st);
                        }
                        variableFactory.createVariable(tk.getName(), null, (Class) stk.peek());
                    }
                    continue;
            }
            stk.push(nextToken().getReducedValue(ctx, ctx, variableFactory), operator);
            switch((operator = arithmeticFunctionReduction(operator))) {
                case OP_TERMINATE:
                    return stk.peek();
                case OP_RESET_FRAME:
                    continue;
            }
            if (procBooleanOperator(operator) == OP_TERMINATE)
                return stk.peek();
        }
        if (holdOverRegister != null) {
            return holdOverRegister;
        }
    } catch (CompileException e) {
        throw ErrorUtil.rewriteIfNeeded(e, expr, start);
    } catch (NullPointerException e) {
        if (tk != null && tk.isOperator()) {
            CompileException ce = new CompileException("incomplete statement: " + tk.getName() + " (possible use of reserved keyword as identifier: " + tk.getName() + ")", expr, st, e);
            ce.setExpr(expr);
            ce.setLineNumber(line);
            ce.setCursor(cursor);
            throw ce;
        } else {
            throw e;
        }
    }
    return stk.peek();
}
Also used : ASTNode(org.mvel2.ast.ASTNode) Substatement(org.mvel2.ast.Substatement)

Example 20 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

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();
    variableFactory.setTiltFlag(false);
    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;
        }
    }
}
Also used : ExecutionStack(org.mvel2.util.ExecutionStack) ASTNode(org.mvel2.ast.ASTNode)

Aggregations

CompileException (org.mvel2.CompileException)23 List (java.util.List)8 Map (java.util.Map)8 IOException (java.io.IOException)7 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)7 ArrayList (java.util.ArrayList)6 Function (org.mvel2.ast.Function)4 TypeDescriptor (org.mvel2.ast.TypeDescriptor)4 WeakHashMap (java.util.WeakHashMap)3 ParserContext (org.mvel2.ParserContext)3 Proto (org.mvel2.ast.Proto)3 ExpressionCompiler (org.mvel2.compiler.ExpressionCompiler)3 StringAppender (org.mvel2.util.StringAppender)3 Label (org.mvel2.asm.Label)2 ASTNode (org.mvel2.ast.ASTNode)2 EndOfStatement (org.mvel2.ast.EndOfStatement)2 CompiledExpression (org.mvel2.compiler.CompiledExpression)2 DefaultLocalVariableResolverFactory (org.mvel2.integration.impl.DefaultLocalVariableResolverFactory)2 ItemResolverFactory (org.mvel2.integration.impl.ItemResolverFactory)2 ExecutionStack (org.mvel2.util.ExecutionStack)2