use of io.github.wysohn.triggerreactor.core.script.wrapper.Accessor in project TriggerReactor by wysohn.
the class Interpreter method unwrapVariable.
private Token unwrapVariable(Token varToken) throws InterpreterException {
if (varToken.type == Type.ID) {
Object var = vars.get(varToken.value);
return parseValue(var);
} else if (varToken.type == Type.GID) {
return convertValue(gvars, varToken);
} else if (varToken.type == Type.ACCESS) {
Accessor accessor = (Accessor) varToken.value;
Object var;
try {
var = accessor.evaluateTarget();
} catch (NoSuchFieldException e) {
throw new InterpreterException("Unknown field " + accessor, e);
} catch (Exception e) {
throw new InterpreterException("Unknown error " + e.getMessage(), e);
}
return parseValue(var);
} else {
throw new InterpreterException("Unresolved id " + varToken);
}
}
use of io.github.wysohn.triggerreactor.core.script.wrapper.Accessor in project TriggerReactor by wysohn.
the class Interpreter method interpret.
/**
* @param node
* @return return codes in Executor. null if execution continues.
* @throws InterpreterException
*/
private Integer interpret(Node node) throws InterpreterException {
try {
if (interrupter != null && interrupter.onNodeProcess(node)) {
return Executor.STOP;
}
if (node.getToken().type == Type.BODY || "IF".equals(node.getToken().value) || "ELSEIF".equals(node.getToken().value) || "WHILE".equals(node.getToken().value)) {
return null;
} else if (node.getToken().type == Type.EXECUTOR) {
String command = (String) node.getToken().value;
Object[] args = new Object[node.getChildren().size()];
for (int i = args.length - 1; i >= 0; i--) {
Token argument = stack.pop();
if (isVariable(argument)) {
argument = unwrapVariable(argument);
}
args[i] = argument.value;
}
if (interrupter != null && interrupter.onCommand(context, command, args)) {
return null;
} else {
if (!executorMap.containsKey(command))
throw new InterpreterException("No executor named #" + command + " found!");
return executorMap.get(command).execute(sync, context, args);
}
} else if (node.getToken().type == Type.PLACEHOLDER) {
String placeholderName = (String) node.getToken().value;
Object[] args = new Object[node.getChildren().size()];
for (int i = args.length - 1; i >= 0; i--) {
Token argument = stack.pop();
if (isVariable(argument)) {
argument = unwrapVariable(argument);
}
args[i] = argument.value;
}
if (!placeholderMap.containsKey(placeholderName))
throw new InterpreterException("No placeholder named $" + placeholderName + " found!");
Object replaced = placeholderMap.get(placeholderName).parse(context, args);
if (replaced == null) {
replaced = "$" + placeholderName;
}
if (replaced instanceof Number) {
double d = ((Number) replaced).doubleValue();
if (d % 1 == 0) {
// whole number
stack.push(new Token(Type.INTEGER, (int) d));
} else {
stack.push(new Token(Type.DECIMAL, d));
}
} else {
stack.push(new Token(Type.EPS, replaced));
}
} else if (node.getToken().type == Type.OPERATOR_A) {
Token right = stack.pop();
Token left = stack.pop();
if (isVariable(right)) {
right = unwrapVariable(right);
}
if (isVariable(left)) {
left = unwrapVariable(left);
}
switch((String) node.getToken().value) {
case "+":
if (left.type == Type.STRING || right.type == Type.STRING) {
stack.push(new Token(Type.STRING, String.valueOf(left.value) + String.valueOf(right.value)));
} else {
if (left.isInt() && right.isInt()) {
int leftVal = left.toInt(), rightVal = right.toInt();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal + rightVal));
} else {
double leftVal = left.isInt() ? left.toInt() : left.toDouble();
double rightVal = right.isInt() ? right.toInt() : right.toDouble();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal + rightVal));
}
}
break;
case "-":
if (left.isInt() && right.isInt()) {
int leftVal = left.toInt(), rightVal = right.toInt();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal - rightVal));
} else {
double leftVal = left.isInt() ? left.toInt() : left.toDouble();
double rightVal = right.isInt() ? right.toInt() : right.toDouble();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal - rightVal));
}
break;
case "*":
if (left.isInt() && right.isInt()) {
int leftVal = left.toInt(), rightVal = right.toInt();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal * rightVal));
} else {
double leftVal = left.isInt() ? left.toInt() : left.toDouble();
double rightVal = right.isInt() ? right.toInt() : right.toDouble();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal * rightVal));
}
break;
case "/":
if (left.isInt() && right.isInt()) {
int leftVal = left.toInt(), rightVal = right.toInt();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal / rightVal));
} else {
double leftVal = left.isInt() ? left.toInt() : left.toDouble();
double rightVal = right.isInt() ? right.toInt() : right.toDouble();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal / rightVal));
}
break;
case "%":
if (left.isInt() && right.isInt()) {
int leftVal = left.toInt(), rightVal = right.toInt();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal % rightVal));
} else {
double leftVal = left.isInt() ? left.toInt() : left.toDouble();
double rightVal = right.isInt() ? right.toInt() : right.toDouble();
stack.push(new Token(left.isInt() && right.isInt() ? Type.INTEGER : Type.DECIMAL, leftVal % rightVal));
}
break;
default:
throw new InterpreterException("Cannot interpret the unknown operator " + node.getToken().value);
}
} else if (node.getToken().type == Type.UNARYMINUS) {
Token value = stack.pop();
if (isVariable(value)) {
value = unwrapVariable(value);
}
if (!value.isNumeric())
throw new InterpreterException("Cannot do unary minus operation for non-numeric value " + value);
stack.push(value.isInt() ? new Token(Type.INTEGER, -value.toInt(), value.row, value.col) : new Token(Type.DECIMAL, -value.toDouble(), value.row, value.col));
} else if (node.getToken().type == Type.OPERATOR_L) {
if ("!".equals(node.getToken().value)) {
Token boolval = stack.pop();
if (isVariable(boolval)) {
boolval = unwrapVariable(boolval);
}
if (boolval.type == Type.NULLVALUE) {
// treat null as false
stack.push(new Token(Type.BOOLEAN, true));
} else if (boolval.isBoolean()) {
stack.push(new Token(Type.BOOLEAN, !boolval.toBoolean()));
} else if (boolval.isDouble()) {
stack.push(new Token(Type.BOOLEAN, boolval.toDouble() == 0.0));
} else if (boolval.isInt()) {
stack.push(new Token(Type.BOOLEAN, boolval.toInt() == 0));
} else {
throw new InterpreterException("Cannot negate non-boolean value " + boolval);
}
} else {
Token right = stack.pop();
Token left = stack.pop();
if (isVariable(right)) {
right = unwrapVariable(right);
}
if (isVariable(left)) {
left = unwrapVariable(left);
}
switch((String) node.getToken().value) {
case "<":
if (!left.isNumeric() || !right.isNumeric())
throw new InterpreterException("Only numeric values can be compared!");
stack.push(new Token(Type.BOOLEAN, (left.isInt() ? left.toInt() : left.toDouble()) < (right.isInt() ? right.toInt() : right.toDouble())));
break;
case ">":
if (!left.isNumeric() || !right.isNumeric())
throw new InterpreterException("Only numeric values can be compared!");
stack.push(new Token(Type.BOOLEAN, (left.isInt() ? left.toInt() : left.toDouble()) > (right.isInt() ? right.toInt() : right.toDouble())));
break;
case "<=":
if (!left.isNumeric() || !right.isNumeric())
throw new InterpreterException("Only numeric values can be compared!");
stack.push(new Token(Type.BOOLEAN, (left.isInt() ? left.toInt() : left.toDouble()) <= (right.isInt() ? right.toInt() : right.toDouble())));
break;
case ">=":
if (!left.isNumeric() || !right.isNumeric())
throw new InterpreterException("Only numeric values can be compared!");
stack.push(new Token(Type.BOOLEAN, (left.isInt() ? left.toInt() : left.toDouble()) >= (right.isInt() ? right.toInt() : right.toDouble())));
break;
case "==":
if (right.type == Type.NULLVALUE) {
stack.push(new Token(Type.BOOLEAN, left.value == null));
} else {
stack.push(new Token(Type.BOOLEAN, left.value.equals(right.value)));
}
break;
case "!=":
if (right.type == Type.NULLVALUE) {
stack.push(new Token(Type.BOOLEAN, left.value != null));
} else {
stack.push(new Token(Type.BOOLEAN, !left.value.equals(right.value)));
}
break;
case "&&":
stack.push(new Token(Type.BOOLEAN, left.toBoolean() && right.toBoolean()));
break;
case "||":
stack.push(new Token(Type.BOOLEAN, left.toBoolean() || right.toBoolean()));
break;
}
}
} else if (node.getToken().type == Type.OPERATOR) {
Token right, left;
switch((String) node.getToken().value) {
case "=":
right = stack.pop();
left = stack.pop();
assignValue(left, right);
break;
case ".":
right = stack.pop();
// function call
if (right.type == Type.CALL) {
Object[] args = new Object[callArgsSize];
for (int i = callArgsSize - 1; i >= 0; i--) {
Token argument = stack.pop();
if (isVariable(argument)) {
argument = unwrapVariable(argument);
}
args[i] = argument.value;
}
callArgsSize = 0;
left = stack.pop();
if (left.type == Type.THIS) {
callFunction(new Token(Type.OBJECT, right.value), new Token(Type.OBJECT, selfReference), args);
} else {
Token temp = left;
if (isVariable(left)) {
left = unwrapVariable(left);
}
if (left.getType() == Type.NULLVALUE) {
throw new InterpreterException("Could not access " + temp + " because it doesn't exist!");
}
if (left.isObject()) {
callFunction(right, left, args);
} else {
Accessor accessor = (Accessor) left.value;
Object var;
try {
var = accessor.evaluateTarget();
} catch (NoSuchFieldException e) {
throw new InterpreterException("Unknown field " + accessor, e);
} catch (Exception e) {
throw new InterpreterException("Unknown error " + e.getMessage(), e);
}
callFunction(right, new Token(Type.EPS, var), args);
}
}
} else // field access
{
left = stack.pop();
if (left.type == Type.THIS) {
stack.push(right);
} else {
Token temp = left;
if (isVariable(left)) {
left = unwrapVariable(left);
}
if (left.getType() == Type.NULLVALUE) {
throw new InterpreterException("Could not access " + temp + " because it doesn't exist!");
}
if (left.isObject() || left.isArray()) {
stack.push(new Token(Type.ACCESS, new Accessor(left.value, (String) right.value)));
} else {
Accessor accessor = (Accessor) left.value;
Object var;
try {
var = accessor.evaluateTarget();
} catch (NoSuchFieldException e) {
throw new InterpreterException("Unknown field " + accessor, e);
} catch (Exception e) {
throw new InterpreterException("Unknown error " + e.getMessage(), e);
}
stack.push(new Token(Type.ACCESS, new Accessor(var, (String) right.value)));
}
}
}
break;
}
} else if (node.getToken().type == Type.ARRAYACCESS) {
Token right = stack.pop();
Token left = stack.pop();
if (isVariable(left)) {
left = unwrapVariable(left);
}
if (isVariable(right)) {
right = unwrapVariable(right);
}
if (!left.isArray())
throw new InterpreterException(left + " is not an array!");
if (!right.isInt())
throw new InterpreterException(right + " is not a valid index for array!");
stack.push(new Token(Type.ACCESS, new Accessor(left.value, (Integer) right.value)));
} else if (node.getToken().type == Type.THIS) {
stack.push(node.getToken());
} else if (node.getToken().type == Type.ID) {
stack.push(node.getToken());
} else if (node.getToken().type == Type.GID) {
Token keyToken = stack.pop();
if (isVariable(keyToken)) {
keyToken = unwrapVariable(keyToken);
}
if (keyToken.getType() != Type.STRING) {
throw new InterpreterException(keyToken + " is not a valid global variable id.");
}
stack.push(new Token(Type.GID, keyToken.value));
} else if (node.getToken().type == Type.CALL) {
stack.push(node.getToken());
callArgsSize = node.getChildren().size();
} else if (node.getToken().type == Type.STRING) {
stack.push(new Token(node.getToken().type, node.getToken().value));
} else if (node.getToken().type == Type.INTEGER) {
stack.push(new Token(node.getToken().type, Integer.parseInt((String) node.getToken().value)));
} else if (node.getToken().type == Type.DECIMAL) {
stack.push(new Token(node.getToken().type, Double.parseDouble((String) node.getToken().value)));
} else if (node.getToken().type == Type.BOOLEAN) {
stack.push(new Token(node.getToken().type, Boolean.parseBoolean((String) node.getToken().value)));
} else if (node.getToken().type == Type.EPS) {
stack.push(new Token(node.getToken().type, node.getToken().value));
} else if (node.getToken().type == Type.NULLVALUE) {
stack.push(new Token(node.getToken().type, null));
} else {
throw new InterpreterException("Cannot interpret the unknown node " + node.getToken().type.name());
}
} catch (Exception e) {
throw new InterpreterException("Error occured while processing Node " + node, e);
}
return null;
}
Aggregations