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.compiler; 1856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.compiler.JavaExpression.Type; 2056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.bool; 2156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.call; 2256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.callFindVariable; 2356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.callOn; 2456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.declare; 2556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.integer; 2656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport static com.google.clearsilver.jsilver.compiler.JavaExpression.string; 2756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter; 2856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AAddExpression; 2956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AAndExpression; 3056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADecimalExpression; 3156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADescendVariable; 3256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ADivideExpression; 3356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AEqExpression; 3456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AExistsExpression; 3556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AFunctionExpression; 3656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AGtExpression; 3756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AGteExpression; 3856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AHexExpression; 3956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ALtExpression; 4056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ALteExpression; 4156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AModuloExpression; 4256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AMultiplyExpression; 4356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANameVariable; 4456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANeExpression; 4556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANegativeExpression; 4656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANotExpression; 4756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericAddExpression; 4856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericEqExpression; 4956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericExpression; 5056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ANumericNeExpression; 5156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AOrExpression; 5256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AStringExpression; 5356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.ASubtractExpression; 5456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.AVariableExpression; 5556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport com.google.clearsilver.jsilver.syntax.node.PExpression; 5656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.LinkedList; 5856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/** 6056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translates a CS expression (from the AST) into an equivalent Java expression. 6156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 6256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * In order to optimize the expressions nicely this class emits code using a series of wrapper 6356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * functions for casting to/from various types. Rather than the old style of saying: 6456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 6556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * <pre>ValueX.asFoo()</pre> 6656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 6756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * we now write: 6856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 6956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * <pre>asFoo(ValueX)</pre> 7056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 7156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * This is actually very important because it means that as we optimize the expressions to return 7256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * fundamental types, we just have different versions of the {@code asFoo()} methods that take the 7356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * appropriate types. The user of the expression is responsible for casting it and the producer of 7456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * the expression is now free to produce optimized expressions. 7556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 7656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpublic class ExpressionTranslator extends DepthFirstAdapter { 7756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 7856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private JavaExpression currentJavaExpression; 7956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 8156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java String expression. 8256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 8356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToString(PExpression csExpression) { 8456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.STRING); 8556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 8656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 8856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java boolean expression. 8956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 9056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToBoolean(PExpression csExpression) { 9156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.BOOLEAN); 9256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 9456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 9556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java integer expression. 9656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 9756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToNumber(PExpression csExpression) { 9856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.INT); 9956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 10256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java Data expression. 10356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 10456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToData(PExpression csExpression) { 10556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.DATA); 10656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 10956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java Data expression. 11056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 11156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToVarName(PExpression csExpression) { 11256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.VAR_NAME); 11356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 11556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 11656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into a Java Value expression. 11756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 11856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateToValue(PExpression csExpression) { 11956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return translateUntyped(csExpression).cast(Type.VALUE); 12056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 12256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 12356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Declares the (typed) expression as a variable with the given name. (e.g. "int foo = 5" or 12456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * "Data foo = Data.getChild("a.b")" 12556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 12656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression declareAsVariable(String name, PExpression csExpression) { 12756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression expression = translateUntyped(csExpression); 12856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Type type = expression.getType(); 12956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert type != null : "all subexpressions should be typed"; 13056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return declare(type, name, expression); 13156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 13256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 13356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 13456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Translate a template AST expression into an untyped expression. 13556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 13656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public JavaExpression translateUntyped(PExpression csExpression) { 13756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 13856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert currentJavaExpression == null : "Not reentrant"; 13956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson csExpression.apply(this); 14056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson assert currentJavaExpression != null : "No expression created"; 14156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return currentJavaExpression; 14256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } finally { 14356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson currentJavaExpression = null; 14456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 14656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 14756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private void setResult(JavaExpression javaExpression) { 14856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson this.currentJavaExpression = javaExpression; 14956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 15156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 15256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Process AST node for a variable (e.g. a.b.c). 15356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 15456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 15556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAVariableExpression(AVariableExpression node) { 15656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression varName = new VariableTranslator(this).translate(node.getVariable()); 15756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(varName); 15856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 15956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 16056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 16156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Process AST node for a string (e.g. "hello"). 16256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 16356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 16456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAStringExpression(AStringExpression node) { 16556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 16656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson value = value.substring(1, value.length() - 1); // Remove enclosing quotes. 16756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(string(value)); 16856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 16956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 17156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Process AST node for a decimal integer (e.g. 123). 17256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 17356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 17456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADecimalExpression(ADecimalExpression node) { 17556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 17656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(integer(value)); 17756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 17856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 17956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 18056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Process AST node for a hex integer (e.g. 0x1AB). 18156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 18256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 18356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAHexExpression(AHexExpression node) { 18456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String value = node.getValue().getText(); 18556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Luckily ClearSilver hex representation is a subset of the Java hex 18656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // representation so we can just use the literal directly. 18756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // TODO: add well-formedness checks whenever literals are used 18856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(integer(value)); 18956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /* 19256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * The next block of functions all convert CS operators into dynamically looked up functions. 19356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 19456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 19556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 19656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericExpression(ANumericExpression node) { 19756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(cast(Type.INT, node.getExpression())); 19856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 19956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 20156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANotExpression(ANotExpression node) { 20256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(prefix(Type.BOOLEAN, Type.BOOLEAN, "!", node.getExpression())); 20356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 20456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 20556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 20656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAExistsExpression(AExistsExpression node) { 20756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Special case. Exists is only ever an issue for variables, all 20856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // other expressions unconditionally exist. 20956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson PExpression expression = node.getExpression(); 21056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (expression instanceof AVariableExpression) { 21156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson expression.apply(this); 21256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (currentJavaExpression.getType() == Type.VAR_NAME) { 21356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson currentJavaExpression = callFindVariable(currentJavaExpression, false); 21456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 21556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(call(Type.BOOLEAN, "exists", currentJavaExpression)); 21656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } else { 21756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // If it's not a variable, it always exists 21856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // NOTE: It's not clear if we must evaluate the sub-expression 21956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // here (is there anything that can have side effects??) 22056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(bool(true)); 22156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 22356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 22456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 22556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAEqExpression(AEqExpression node) { 22656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression left = cast(Type.STRING, node.getLeft()); 22756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression right = cast(Type.STRING, node.getRight()); 22856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(callOn(Type.BOOLEAN, left, "equals", right)); 22956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 23256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericEqExpression(ANumericEqExpression node) { 23356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, "==", node.getLeft(), node.getRight())); 23456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 23556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 23656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 23756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANeExpression(ANeExpression node) { 23856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression left = cast(Type.STRING, node.getLeft()); 23956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression right = cast(Type.STRING, node.getRight()); 24056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(JavaExpression.prefix(Type.BOOLEAN, "!", callOn(Type.BOOLEAN, left, "equals", right))); 24156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 24256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 24456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericNeExpression(ANumericNeExpression node) { 24556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, "!=", node.getLeft(), node.getRight())); 24656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 24756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 24856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 24956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseALtExpression(ALtExpression node) { 25056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, "<", node.getLeft(), node.getRight())); 25156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 25456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAGtExpression(AGtExpression node) { 25556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, ">", node.getLeft(), node.getRight())); 25656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 25756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 25856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 25956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseALteExpression(ALteExpression node) { 26056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, "<=", node.getLeft(), node.getRight())); 26156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 26356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 26456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAGteExpression(AGteExpression node) { 26556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.INT, ">=", node.getLeft(), node.getRight())); 26656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 26756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 26856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 26956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAAndExpression(AAndExpression node) { 27056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.BOOLEAN, "&&", node.getLeft(), node.getRight())); 27156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 27256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 27356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 27456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAOrExpression(AOrExpression node) { 27556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.BOOLEAN, Type.BOOLEAN, "||", node.getLeft(), node.getRight())); 27656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 27756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 27856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 27956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAAddExpression(AAddExpression node) { 28056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.STRING, Type.STRING, "+", node.getLeft(), node.getRight())); 28156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 28256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 28456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANumericAddExpression(ANumericAddExpression node) { 28556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.INT, Type.INT, "+", node.getLeft(), node.getRight())); 28656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 28756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 28856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 28956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseASubtractExpression(ASubtractExpression node) { 29056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.INT, Type.INT, "-", node.getLeft(), node.getRight())); 29156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 29256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 29356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 29456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAMultiplyExpression(AMultiplyExpression node) { 29556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.INT, Type.INT, "*", node.getLeft(), node.getRight())); 29656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 29756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 29856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 29956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADivideExpression(ADivideExpression node) { 30056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.INT, Type.INT, "/", node.getLeft(), node.getRight())); 30156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 30256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 30356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 30456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAModuloExpression(AModuloExpression node) { 30556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(infix(Type.INT, Type.INT, "%", node.getLeft(), node.getRight())); 30656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 30756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 30856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 30956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANegativeExpression(ANegativeExpression node) { 31056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(prefix(Type.INT, Type.INT, "-", node.getExpression())); 31156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 31256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 31356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 31456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Process AST node for a function (e.g. dosomething(...)). 31556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 31656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 31756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseAFunctionExpression(AFunctionExpression node) { 31856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson LinkedList<PExpression> argsList = node.getArgs(); 31956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson PExpression[] args = argsList.toArray(new PExpression[argsList.size()]); 32056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Because the function name may have dots in, the parser would have broken 32256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // it into a little node tree which we need to walk to reconstruct the 32356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // full name. 32456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson final StringBuilder fullFunctionName = new StringBuilder(); 32556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node.getName().apply(new DepthFirstAdapter() { 32656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 32756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 32856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseANameVariable(ANameVariable node11) { 32956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson fullFunctionName.append(node11.getWord().getText()); 33056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 33156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 33256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson @Override 33356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public void caseADescendVariable(ADescendVariable node12) { 33456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node12.getParent().apply(this); 33556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson fullFunctionName.append('.'); 33656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node12.getChild().apply(this); 33756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 33856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson }); 33956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 34056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson setResult(function(fullFunctionName.toString(), args)); 34156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 34256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 34356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 34456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Generate a JavaExpression for calling a function. 34556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 34656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private JavaExpression function(String name, PExpression... csExpressions) { 34756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Outputs: context.executeFunction("myfunc", args...); 34856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression[] args = new JavaExpression[1 + csExpressions.length]; 34956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson args[0] = string(name); 35056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson for (int i = 0; i < csExpressions.length; i++) { 35156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson args[i + 1] = cast(Type.VALUE, csExpressions[i]); 35256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return callOn(Type.VALUE, TemplateTranslator.CONTEXT, "executeFunction", args); 35456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 35556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 35656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private JavaExpression infix(Type destType, Type srcType, String infix, PExpression leftNode, 35756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson PExpression rightNode) { 35856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression left = cast(srcType, leftNode); 35956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson JavaExpression right = cast(srcType, rightNode); 36056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return JavaExpression.infix(destType, infix, left, right); 36156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 36256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 36356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private JavaExpression prefix(Type destType, Type srcType, String prefix, PExpression node) { 36456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return JavaExpression.prefix(destType, prefix, cast(srcType, node)); 36556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 36656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 36756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private JavaExpression cast(Type type, PExpression node) { 36856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson node.apply(this); 36956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return currentJavaExpression.cast(type); 37056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 37156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 372