com.googlecode.aviator.runtime.op.OperationRuntime Maven / Gradle / Ivy
package com.googlecode.aviator.runtime.op;
import java.util.Map;
import com.googlecode.aviator.exception.IllegalArityException;
import com.googlecode.aviator.lexer.token.OperatorType;
import com.googlecode.aviator.lexer.token.Variable;
import com.googlecode.aviator.runtime.RuntimeUtils;
import com.googlecode.aviator.runtime.type.AviatorFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
/**
* Operation runtime
*
* @author dennis
*
*/
public class OperationRuntime {
private static final ThreadLocal TWO_ARRGS = new ThreadLocal() {
@Override
protected AviatorObject[] initialValue() {
return new AviatorObject[2];
}
};
private static final ThreadLocal ONE_ARG = new ThreadLocal() {
@Override
protected AviatorObject[] initialValue() {
return new AviatorObject[1];
}
};
/**
* Eval with arguments array.
*
* @param args
* @param opType
* @return
*/
public static AviatorObject eval(final Map env, final AviatorObject[] args,
final OperatorType opType) {
AviatorFunction func = RuntimeUtils.getInstance(env).getOpFunction(opType);
AviatorObject ret = eval0(env, args, opType, func);
if (RuntimeUtils.isTracedEval(env)) {
trace(env, opType, ret, args);
}
return ret;
}
private static AviatorObject eval0(final Map env, final AviatorObject[] args,
final OperatorType opType, final AviatorFunction func) {
if (func == null) {
return opType.eval(args, env);
} else {
return evalOpFunction(env, args, opType, func);
}
}
public static AviatorObject evalOpFunction(final Map env,
final AviatorObject[] args, final OperatorType opType, final AviatorFunction func) {
switch (opType.getArity()) {
case 1:
return func.call(env, args[0]);
case 2:
return func.call(env, args[0], args[1]);
case 3:
return func.call(env, args[0], args[1], args[2]);
}
throw new IllegalArityException("Too many arguments.");
}
/**
* Eval with unary operator
*
* @param arg
* @param env
* @param opType
* @return
*/
public static AviatorObject eval(final AviatorObject arg, final Map env,
final OperatorType opType) {
AviatorFunction func = RuntimeUtils.getInstance(env).getOpFunction(opType);
AviatorObject ret = eval0(arg, env, opType, func);
if (RuntimeUtils.isTracedEval(env)) {
trace(env, opType, ret, arg);
}
return ret;
}
private static AviatorObject eval0(final AviatorObject arg, final Map env,
final OperatorType opType, final AviatorFunction func) {
if (func == null) {
AviatorObject[] args = ONE_ARG.get();
args[0] = arg;
return opType.eval(args, env);
} else {
return func.call(env, arg);
}
}
/**
* Just like {@link #eval(AviatorObject, AviatorObject, Map, OperatorType)}, but with difference
* arguments order.
*
* @param left
* @param env
* @param right
* @param opType
* @return
*/
public static AviatorObject eval(final AviatorObject left, final Map env,
final AviatorObject right, final OperatorType opType) {
return eval(left, right, env, opType);
}
/**
* Eval with binary operator
*
* @param left
* @param right
* @param env
* @param opType
* @return
*/
public static AviatorObject eval(final AviatorObject left, final AviatorObject right,
final Map env, final OperatorType opType) {
AviatorFunction func = RuntimeUtils.getInstance(env).getOpFunction(opType);
AviatorObject ret = eval0(left, right, env, opType, func);
if (RuntimeUtils.isTracedEval(env)) {
trace(env, opType, ret, left, right);
}
return ret;
}
private static AviatorObject eval0(final AviatorObject left, final AviatorObject right,
final Map env, final OperatorType opType, final AviatorFunction func) {
if (func == null) {
AviatorObject[] args = TWO_ARRGS.get();
args[0] = left;
args[1] = right;
return opType.eval(args, env);
} else {
return func.call(env, left, right);
}
}
public static final boolean hasRuntimeContext(final Map env,
final OperatorType opType) {
return containsOpFunction(env, opType) || RuntimeUtils.isTracedEval(env);
}
public static boolean containsOpFunction(final Map env,
final OperatorType opType) {
return RuntimeUtils.getInstance(env).getOpsMap().containsKey(opType);
}
private static final String WHITE_SPACE = " ";
private static final String TRACE_PREFIX = " ";
private static String desc(final AviatorObject arg, final Map env) {
if (arg != null) {
return arg.desc(env);
} else {
return Variable.NIL.getLexeme();
}
}
private static void trace(final Map env, final OperatorType opType,
final AviatorObject result, final AviatorObject... args) {
StringBuilder argsDec = new StringBuilder();
argsDec.append(desc(args[0], env));
for (int i = 1; i < args.length; i++) {
if (args[i] != null) {
argsDec.append(WHITE_SPACE).append(opType.token).append(WHITE_SPACE)
.append(desc(args[i], env));
}
}
RuntimeUtils.printlnTrace(env, TRACE_PREFIX + argsDec + " => " + desc(result, env));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy