/*******************************************************************************
* Copyright (c) 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.qt.core.qmljs;
public final class QMLExpressionEvaluator {
private QMLExpressionEvaluator() {
}
public static class InvalidExpressionException extends Exception {
private static final long serialVersionUID = 4803923632666457229L;
private IJSExpression offendingExpression;
public InvalidExpressionException(String msg, IJSExpression expr) {
super(msg);
this.offendingExpression = expr;
}
public IJSExpression getOffendingExpression() {
return offendingExpression;
}
}
/**
* Evaluates the given {@link IJSExpression} as a constant expression and returns the result. At the moment this only supports
* very simple expressions involving unary operators and literals alone. Support for more complex expressions will be added as
* needed.
*
* @param expr
* the expression to be evaluated
*
* @throws InvalidExpressionException
* if the given expression can't be reduced to a single constant
*/
public static Object evaluateConstExpr(IJSExpression expr) throws InvalidExpressionException {
if (expr instanceof IJSLiteral) {
return ((IJSLiteral) expr).getValue();
} else if (expr instanceof IJSUnaryExpression) {
IJSUnaryExpression unary = (IJSUnaryExpression) expr;
Object arg = evaluateConstExpr(unary.getArgument());
switch (unary.getOperator()) {
case Plus:
return unaryPlus(arg, unary.getArgument());
case Negation:
return unaryNegate(arg, unary.getArgument());
case BitwiseNot:
return unaryBitwiseNot(arg, unary.getArgument());
case Not:
return unaryNot(arg, unary.getArgument());
default:
}
}
throw new InvalidExpressionException("Cannot reduce '" + expr + "' to a constant", expr); //$NON-NLS-1$ //$NON-NLS-2$
}
private static Object unaryPlus(Object object, IJSExpression expr) throws InvalidExpressionException {
if (object instanceof Byte) {
return +((Byte) object);
} else if (object instanceof Short) {
return +((Short) object);
} else if (object instanceof Integer) {
return +((Integer) object);
} else if (object instanceof Long) {
return +((Long) object);
} else if (object instanceof Float) {
return +((Float) object);
} else if (object instanceof Double) {
return +((Double) object);
}
throw new InvalidExpressionException("Cannot perform unary plus operation on a non-number", expr); //$NON-NLS-1$
}
private static Object unaryNegate(Object object, IJSExpression expr) throws InvalidExpressionException {
if (object instanceof Byte) {
return -((Byte) object);
} else if (object instanceof Short) {
return -((Short) object);
} else if (object instanceof Integer) {
return -((Integer) object);
} else if (object instanceof Long) {
return -((Long) object);
} else if (object instanceof Float) {
return -((Float) object);
} else if (object instanceof Double) {
return -((Double) object);
}
throw new InvalidExpressionException("Cannot perform unary negation operation on a non-number", expr); //$NON-NLS-1$
}
private static Object unaryBitwiseNot(Object object, IJSExpression expr) throws InvalidExpressionException {
if (object instanceof Byte) {
return ~((Byte) object);
} else if (object instanceof Short) {
return ~((Short) object);
} else if (object instanceof Integer) {
return ~((Integer) object);
} else if (object instanceof Long) {
return ~((Long) object);
} else if (object instanceof Float || object instanceof Double) {
return ~((Number) object).longValue();
}
throw new InvalidExpressionException("Cannot perform binary not operation on a non-number", expr); //$NON-NLS-1$
}
private static Object unaryNot(Object object, IJSExpression expr) throws InvalidExpressionException {
if (object instanceof Boolean) {
return !((Boolean) object);
}
throw new InvalidExpressionException("Cannot perform unary not operation on a non-boolean", expr); //$NON-NLS-1$
}
}