156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/* 256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Copyright (C) 2010 Google Inc. 356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Licensed under the Apache License, Version 2.0 (the "License"); 556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * you may not use this file except in compliance with the License. 656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * You may obtain a copy of the License at 756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * http://www.apache.org/licenses/LICENSE-2.0 956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Unless required by applicable law or agreed to in writing, software 1156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * distributed under the License is distributed on an "AS IS" BASIS, 1256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * See the License for the specific language governing permissions and 1456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * limitations under the License. 1556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 1656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpackage com.google.clearsilver.jsilver.interpreter; 1856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.autoescape.EscapeMode; 2056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.data.DataContext; 2156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.functions.FunctionExecutor; 2256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter; 2356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AAddExpression; 2456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AAndExpression; 2556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADecimalExpression; 2656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADescendVariable; 2756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADivideExpression; 2856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AEqExpression; 2956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AExistsExpression; 3056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AFunctionExpression; 3156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AGtExpression; 3256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AGteExpression; 3356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AHexExpression; 3456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ALtExpression; 3556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ALteExpression; 3656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AModuloExpression; 3756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AMultiplyExpression; 3856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANameVariable; 3956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANeExpression; 4056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANegativeExpression; 4156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANotExpression; 4256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericAddExpression; 4356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericEqExpression; 4456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericExpression; 4556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericNeExpression; 4656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AOrExpression; 4756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AStringExpression; 4856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ASubtractExpression; 4956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AVariableExpression; 5056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.PExpression; 5156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.values.Value; 5256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.values.Value.literalValue; 5356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.LinkedList; 5556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/** 5756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Walks the tree of a PExpression node and evaluates the expression. 5856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @see #evaluate(PExpression) 5956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 6056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpublic class ExpressionEvaluator extends DepthFirstAdapter { 6156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private Value currentValue; 6356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private final DataContext context; 6556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private final FunctionExecutor functionExecutor; 6756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 6856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 6956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param context 7056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @param functionExecutor Used for executing functions in expressions. As well as looking up 7156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * named functions (e.g. html_escape), it also uses 7256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 7356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public ExpressionEvaluator(DataContext context, FunctionExecutor functionExecutor) { 7456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.context = context; 7556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.functionExecutor = functionExecutor; 7656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 7956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Evaluate an expression into a single value. 8056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 8156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public Value evaluate(PExpression expression) { 8256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert currentValue == null; 8356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson expression.apply(this); 8556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Value result = currentValue; 8656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson currentValue = null; 8756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert result != null : "No result set from " + expression.getClass(); 8956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return result; 9056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 9356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAVariableExpression(AVariableExpression node) { 9456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson VariableLocator variableLocator = new VariableLocator(this); 9556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String variableName = variableLocator.getVariableName(node.getVariable()); 9656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(Value.variableValue(variableName, context)); 9756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 10056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAStringExpression(AStringExpression node) { 10156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 10256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = value.substring(1, value.length() - 1); // Remove enclosing quotes. 10356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // The expression was a constant string literal. Does not 10456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // need to be autoescaped, as it was created by the template developer. 10556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Value result = literalValue(value, EscapeMode.ESCAPE_IS_CONSTANT, false); 10656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(result); 10756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 11056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADecimalExpression(ADecimalExpression node) { 11156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 11256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(literalValue(Integer.parseInt(value), EscapeMode.ESCAPE_IS_CONSTANT, false)); 11356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 11556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 11656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAHexExpression(AHexExpression node) { 11756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 11856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = value.substring(2); // Remove 0x prefix. 11956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(literalValue(Integer.parseInt(value, 16), EscapeMode.ESCAPE_IS_CONSTANT, false)); 12056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 12356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericExpression(ANumericExpression node) { 12456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("#", node.getExpression()); 12556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 12856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANotExpression(ANotExpression node) { 12956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("!", node.getExpression()); 13056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 13356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAExistsExpression(AExistsExpression node) { 13456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("?", node.getExpression()); 13556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 13856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAEqExpression(AEqExpression node) { 13956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("==", node.getLeft(), node.getRight()); 14056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 14356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericEqExpression(ANumericEqExpression node) { 14456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("#==", node.getLeft(), node.getRight()); 14556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 14856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANeExpression(ANeExpression node) { 14956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("!=", node.getLeft(), node.getRight()); 15056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 15356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericNeExpression(ANumericNeExpression node) { 15456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("#!=", node.getLeft(), node.getRight()); 15556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 15856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseALtExpression(ALtExpression node) { 15956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("<", node.getLeft(), node.getRight()); 16056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 16356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAGtExpression(AGtExpression node) { 16456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction(">", node.getLeft(), node.getRight()); 16556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 16856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseALteExpression(ALteExpression node) { 16956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("<=", node.getLeft(), node.getRight()); 17056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 17156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 17356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAGteExpression(AGteExpression node) { 17456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction(">=", node.getLeft(), node.getRight()); 17556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 17656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 17856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAAndExpression(AAndExpression node) { 17956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("&&", node.getLeft(), node.getRight()); 18056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 18156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 18356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAOrExpression(AOrExpression node) { 18456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("||", node.getLeft(), node.getRight()); 18556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 18656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 18756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 18856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAAddExpression(AAddExpression node) { 18956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("+", node.getLeft(), node.getRight()); 19056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 19356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericAddExpression(ANumericAddExpression node) { 19456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("#+", node.getLeft(), node.getRight()); 19556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 19856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseASubtractExpression(ASubtractExpression node) { 19956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("-", node.getLeft(), node.getRight()); 20056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 20356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAMultiplyExpression(AMultiplyExpression node) { 20456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("*", node.getLeft(), node.getRight()); 20556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 20856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADivideExpression(ADivideExpression node) { 20956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("/", node.getLeft(), node.getRight()); 21056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 21156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 21256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 21356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAModuloExpression(AModuloExpression node) { 21456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("%", node.getLeft(), node.getRight()); 21556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 21656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 21756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 21856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANegativeExpression(ANegativeExpression node) { 21956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction("-", node.getExpression()); 22056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 22356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAFunctionExpression(AFunctionExpression node) { 22456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LinkedList<PExpression> argsList = node.getArgs(); 22556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson PExpression[] args = argsList.toArray(new PExpression[argsList.size()]); 22656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson executeFunction(getFullFunctionName(node), args); 22856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private void executeFunction(String name, PExpression... expressions) { 23156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Value[] args = new Value[expressions.length]; 23256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (int i = 0; i < args.length; i++) { 23356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson args[i] = evaluate(expressions[i]); 23456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(functionExecutor.executeFunction(name, args)); 23756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 24056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Sets a result from inside an expression. 24156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 24256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private void setResult(Value value) { 24356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert value != null; 24456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson currentValue = value; 24656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 24756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private String getFullFunctionName(AFunctionExpression node) { 24956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson final StringBuilder result = new StringBuilder(); 25056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node.getName().apply(new DepthFirstAdapter() { 25156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 25356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANameVariable(ANameVariable node) { 25456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson result.append(node.getWord().getText()); 25556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 25856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADescendVariable(ADescendVariable node) { 25956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node.getParent().apply(this); 26056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson result.append('.'); 26156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node.getChild().apply(this); 26256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson }); 26456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return result.toString(); 26556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 26756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 268