EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.stoex.analyser.visitors]

COVERAGE SUMMARY FOR SOURCE FILE [ExpressionInferTypeVisitor.java]

nameclass, %method, %block, %line, %
ExpressionInferTypeVisitor.java0%   (0/1)0%   (0/28)0%   (0/867)0%   (0/170)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ExpressionInferTypeVisitor0%   (0/1)0%   (0/28)0%   (0/867)0%   (0/170)
<static initializer> 0%   (0/1)0%   (0/5)0%   (0/3)
ExpressionInferTypeVisitor (): void 0%   (0/1)0%   (0/8)0%   (0/3)
caseBoolLiteral (BoolLiteral): Object 0%   (0/1)0%   (0/8)0%   (0/2)
caseBooleanOperatorExpression (BooleanOperatorExpression): Object 0%   (0/1)0%   (0/18)0%   (0/4)
caseCompareExpression (CompareExpression): Object 0%   (0/1)0%   (0/18)0%   (0/4)
caseDoubleLiteral (DoubleLiteral): Object 0%   (0/1)0%   (0/8)0%   (0/2)
caseFunctionLiteral (FunctionLiteral): Object 0%   (0/1)0%   (0/247)0%   (0/36)
caseIfElseExpression (IfElseExpression): Object 0%   (0/1)0%   (0/23)0%   (0/5)
caseIntLiteral (IntLiteral): Object 0%   (0/1)0%   (0/8)0%   (0/2)
caseNegativeExpression (NegativeExpression): Object 0%   (0/1)0%   (0/18)0%   (0/3)
caseNotExpression (NotExpression): Object 0%   (0/1)0%   (0/13)0%   (0/3)
caseParenthesis (Parenthesis): Object 0%   (0/1)0%   (0/13)0%   (0/3)
casePowerExpression (PowerExpression): Object 0%   (0/1)0%   (0/42)0%   (0/8)
caseProbabilityFunctionLiteral (ProbabilityFunctionLiteral): Object 0%   (0/1)0%   (0/77)0%   (0/18)
caseProductExpression (ProductExpression): Object 0%   (0/1)0%   (0/47)0%   (0/9)
caseStringLiteral (StringLiteral): Object 0%   (0/1)0%   (0/8)0%   (0/2)
caseTermExpression (TermExpression): Object 0%   (0/1)0%   (0/40)0%   (0/8)
caseVariable (Variable): Object 0%   (0/1)0%   (0/39)0%   (0/12)
getType (Expression): TypeEnum 0%   (0/1)0%   (0/15)0%   (0/3)
getTypeAnnotation (): HashMap 0%   (0/1)0%   (0/3)0%   (0/1)
getTypeOfChild (Expression): TypeEnum 0%   (0/1)0%   (0/20)0%   (0/5)
inferIntAndDouble (Expression, TypeEnum, TypeEnum): void 0%   (0/1)0%   (0/108)0%   (0/14)
isDoubleIntAnyPMF (TypeEnum): boolean 0%   (0/1)0%   (0/22)0%   (0/6)
isDoubleIntPDF (TypeEnum): boolean 0%   (0/1)0%   (0/19)0%   (0/5)
isDoubleIntPMF (TypeEnum): boolean 0%   (0/1)0%   (0/16)0%   (0/4)
isIntPMF (TypeEnum): boolean 0%   (0/1)0%   (0/10)0%   (0/2)
isNumeric (TypeEnum): boolean 0%   (0/1)0%   (0/10)0%   (0/2)
setTypeAnnotation (HashMap): void 0%   (0/1)0%   (0/4)0%   (0/2)

1package de.uka.ipd.sdq.stoex.analyser.visitors;
2 
3import java.util.HashMap;
4 
5import org.apache.log4j.Logger;
6 
7import de.uka.ipd.sdq.pcm.parameter.CharacterisedVariable;
8import de.uka.ipd.sdq.pcm.parameter.VariableCharacterisationType;
9import de.uka.ipd.sdq.probfunction.ProbabilityDensityFunction;
10import de.uka.ipd.sdq.probfunction.ProbabilityFunction;
11import de.uka.ipd.sdq.probfunction.ProbabilityMassFunction;
12import de.uka.ipd.sdq.probfunction.Sample;
13import de.uka.ipd.sdq.stoex.BoolLiteral;
14import de.uka.ipd.sdq.stoex.BooleanOperatorExpression;
15import de.uka.ipd.sdq.stoex.CompareExpression;
16import de.uka.ipd.sdq.stoex.DoubleLiteral;
17import de.uka.ipd.sdq.stoex.Expression;
18import de.uka.ipd.sdq.stoex.FunctionLiteral;
19import de.uka.ipd.sdq.stoex.IfElse;
20import de.uka.ipd.sdq.stoex.IfElseExpression;
21import de.uka.ipd.sdq.stoex.IntLiteral;
22import de.uka.ipd.sdq.stoex.NegativeExpression;
23import de.uka.ipd.sdq.stoex.NotExpression;
24import de.uka.ipd.sdq.stoex.Parenthesis;
25import de.uka.ipd.sdq.stoex.PowerExpression;
26import de.uka.ipd.sdq.stoex.ProbabilityFunctionLiteral;
27import de.uka.ipd.sdq.stoex.ProductExpression;
28import de.uka.ipd.sdq.stoex.ProductOperations;
29import de.uka.ipd.sdq.stoex.StringLiteral;
30import de.uka.ipd.sdq.stoex.TermExpression;
31import de.uka.ipd.sdq.stoex.TermOperations;
32import de.uka.ipd.sdq.stoex.Variable;
33import de.uka.ipd.sdq.stoex.analyser.probfunction.ProbfunctionHelper;
34import de.uka.ipd.sdq.stoex.util.StoexSwitch;
35 
36/**
37 * A visitor for stochastic expression, which infers
38 * the types before evaluating these expressions.
39 *
40 * For example, it infers the result type of an operation add
41 * on a INT and a INT_PMF to a INT_PMF, as the add operation with
42 * a constant shifts the INT_PMF.
43 *
44 * It stores the inferred types for each expression in a hashmap,
45 * which can be retrieved via getTypeAnnotation().
46 *
47 * @author koziolek
48 */
49public class ExpressionInferTypeVisitor extends StoexSwitch<Object> {
50 
51        private static Logger logger = Logger
52                        .getLogger(ExpressionInferTypeVisitor.class.getName());
53 
54        private HashMap<Expression, TypeEnum> typeAnnotation =
55                new HashMap<Expression, TypeEnum>();
56 
57 
58 
59        /**
60         * Result of a compare expression is always of type BOOL_PMF.
61         */
62        public Object caseCompareExpression(CompareExpression expr){
63                doSwitch(expr.getLeft());
64                doSwitch(expr.getRight());
65 
66                typeAnnotation.put(expr, TypeEnum.BOOL_PMF);
67                return expr;
68        }
69 
70        /**
71         * Result of a product expression can be of type INT, DOUBLE, INT_PMF,
72         * DOUBLE_PMF, ANY_PMF, DOUBLE_PDF depending on the operands.
73         */
74        public Object caseProductExpression(ProductExpression expr){
75                TypeEnum leftType = getTypeOfChild((Expression)expr.getLeft());
76                TypeEnum rightType = getTypeOfChild((Expression)expr.getRight());
77 
78                ProductOperations op = expr.getOperation();
79                if (op.getName().equals("MULT") || op.getName().equals("DIV")){
80                        // may result in ints or doubles
81                        inferIntAndDouble(expr, leftType, rightType);
82                } else if (op.getName().equals("MOD")){
83                        this.typeAnnotation.put(expr, TypeEnum.INT_PMF);
84                } else
85                        throw new UnsupportedOperationException();
86                //logger.debug(expr.getOperation().toString());
87 
88                return expr;
89        }
90 
91        /**
92         * Result of a power expression so far only be of type DOUBLE,
93         * as the power operation is only allowed on NUMBERs, not PMFs.
94         */
95        public Object casePowerExpression(PowerExpression expr) {
96                doSwitch(expr.getBase());
97                doSwitch(expr.getExponent());
98 
99                TypeEnum baseType = getType(expr.getBase());
100                TypeEnum exponentType = getType(expr.getExponent());
101 
102                if (isNumeric(baseType) && isNumeric(exponentType)){
103                        typeAnnotation.put(expr, TypeEnum.DOUBLE);
104                } else
105                        throw new UnsupportedOperationException("Power expression is not supported fo non-numeric base or exponent");
106 
107                return expr;
108        }
109        
110        
111 
112        @Override
113        public Object caseNegativeExpression(NegativeExpression object) {
114                this.doSwitch(object.getInner());
115                typeAnnotation.put(object,typeAnnotation.get(object.getInner()));
116                return object;
117        }
118 
119        @Override
120        public Object caseBooleanOperatorExpression(BooleanOperatorExpression object) {
121                doSwitch(object.getLeft());
122                doSwitch(object.getRight());
123 
124                typeAnnotation.put(object,TypeEnum.BOOL);
125                return object;
126        }
127 
128        @Override
129        public Object caseNotExpression(NotExpression object) {
130                this.doSwitch(object.getInner());
131                typeAnnotation.put(object,TypeEnum.BOOL);
132                return object;
133        }
134 
135        /**
136         * Result of a term expression can be of type INT, DOUBLE, INT_PMF,
137         * DOUBLE_PMF, ANY_PMF, DOUBLE_PDF depending on the operands.
138         */
139        public Object caseTermExpression(TermExpression expr){
140                TypeEnum leftType = getTypeOfChild((Expression)expr.getLeft());
141                TypeEnum rightType = getTypeOfChild((Expression)expr.getRight());
142 
143                TermOperations op = expr.getOperation();
144                if (op.getName().equals("ADD") || op.getName().equals("SUB")) {
145                        // may result in ints or doubles
146                        inferIntAndDouble(expr, leftType, rightType);
147                } else
148                        throw new UnsupportedOperationException();
149                logger.debug(expr.getOperation().toString());
150 
151                return expr;
152        }
153 
154        /**
155         * Infers the type of a probability function literal.
156         */
157        public Object caseProbabilityFunctionLiteral(ProbabilityFunctionLiteral pfl){
158                ProbabilityFunction pf = pfl.getFunction_ProbabilityFunctionLiteral();
159                if (pf instanceof ProbabilityMassFunction){
160                        ProbabilityMassFunction pmf = (ProbabilityMassFunction)pf;
161                        Sample firstSample = (Sample)pmf.getSamples().get(0);
162                        Object value = firstSample.getValue();
163                        if (value instanceof Integer){
164                                typeAnnotation.put(pfl, TypeEnum.INT_PMF);
165                        } else if (value instanceof Double){
166                                typeAnnotation.put(pfl, TypeEnum.DOUBLE_PMF);
167                        } else if (value instanceof String){
168                                typeAnnotation.put(pfl, TypeEnum.ENUM_PMF);
169                        } else if (value instanceof Boolean){
170                                typeAnnotation.put(pfl, TypeEnum.BOOL_PMF);
171                        } else {
172                                logger.error("Could not determine type of PMF!");
173                        }
174                } else if (pf instanceof ProbabilityDensityFunction){
175                        typeAnnotation.put(pfl, TypeEnum.DOUBLE_PDF);
176                } else {
177                        logger.error("Could not determine type of ProbabilityFunctionLiteral!");
178                }
179                return pfl;
180        }
181 
182        /**
183         * Infers the type of an int literal to INT.
184         */
185        public Object caseIntLiteral(IntLiteral il){
186                typeAnnotation.put(il, TypeEnum.INT);
187                return il;
188        }
189 
190        /**
191         * Infers the type of an double literal to DOUBLE.
192         */
193        public Object caseDoubleLiteral(DoubleLiteral dl){
194                typeAnnotation.put(dl, TypeEnum.DOUBLE);
195                return dl;
196        }
197 
198        /**
199         * Infers the type of a variable depending on its characterisation
200         * type. Infers VALUE, DATATYPE, STRUCUTURE to ANY_PMF, while
201         * NUMBER_OF_ELEMENTS and BYTESIZE to INT_PMF.
202         *
203         * If later in the {@link ExpressionSolveVisitor} the result is solved and
204         * the supposed INT_PMF turns out to be something else, an exception is thrown.
205         * If the behaviour is changed here, the exception handling in
206         * {@link ExpressionSolveVisitor#extractIPMFFromLiteral} needs to be adjusted, too.
207         */
208        public Object caseVariable(Variable var){
209                //logger.debug("Found variable: " + var.getId_Variable());
210                if (var instanceof CharacterisedVariable) {
211                        CharacterisedVariable chVar = (CharacterisedVariable) var;
212                        VariableCharacterisationType chType = chVar
213                                        .getCharacterisationType();
214                        if (chType == VariableCharacterisationType.VALUE
215                         || chType == VariableCharacterisationType.TYPE
216                         || chType == VariableCharacterisationType.STRUCTURE) {
217                                typeAnnotation.put(var, TypeEnum.ANY_PMF);
218                                //logger.debug("Inferred to ENUM_PMF");
219                        } else if (chType == VariableCharacterisationType.NUMBER_OF_ELEMENTS
220                                         || chType == VariableCharacterisationType.BYTESIZE) {
221                                typeAnnotation.put(var, TypeEnum.INT_PMF);
222                                //logger.debug("Inferred to INT_PMF");
223                        }
224                }
225                return var;
226        }
227 
228        /**
229         * Infers the type of an bool literal to BOOL.
230         */
231        public Object caseBoolLiteral(BoolLiteral bl) {
232                typeAnnotation.put(bl, TypeEnum.BOOL);
233                return bl;
234        }
235 
236        /**
237         * Infers the type of an parenthesis to its inner encapsulated expression.
238         */
239        public Object caseParenthesis(Parenthesis parenthesis) {
240                TypeEnum type = getTypeOfChild(parenthesis.getInnerExpression());
241                typeAnnotation.put(parenthesis, type);
242                return parenthesis;
243        }
244 
245        /**
246         * @param expr
247         * @param leftType
248         * @param rightType
249         */
250        private void inferIntAndDouble(Expression expr, TypeEnum leftType, TypeEnum rightType) {
251                if (leftType == TypeEnum.INT && rightType == TypeEnum.INT){
252                        typeAnnotation.put(expr, TypeEnum.INT);
253                } else if (isIntPMF(leftType) && isIntPMF(rightType)){
254                        typeAnnotation.put(expr, TypeEnum.INT_PMF);
255                } else if (isNumeric(leftType) && isNumeric(rightType)){
256                        typeAnnotation.put(expr, TypeEnum.DOUBLE);
257                } else if (isDoubleIntPMF(leftType) && isDoubleIntPMF(rightType)){
258                        typeAnnotation.put(expr, TypeEnum.DOUBLE_PMF);
259                } else if (isDoubleIntAnyPMF(leftType) && isDoubleIntAnyPMF(rightType)) {
260                        typeAnnotation.put(expr, TypeEnum.ANY_PMF);
261                } else if (isDoubleIntPDF(leftType) && isDoubleIntPDF(rightType)){
262                        typeAnnotation.put(expr, TypeEnum.DOUBLE_PDF);
263                } else {
264                        throw new UnsupportedOperationException("Type inference of "+leftType.name()+" and "+rightType.name()+" failed. Incompatible types for operation.");
265                }
266        }
267 
268 
269        /**
270         * @param expr
271         * @return
272         */
273        private TypeEnum getTypeOfChild(Expression expr) {
274                Expression childExpr = (Expression)doSwitch(expr);
275                TypeEnum type = typeAnnotation.get(childExpr);
276                if (type == null)
277                        throw new TypeInferenceFailedException(expr);
278                return type;
279        }
280 
281        private boolean isIntPMF(TypeEnum type) {
282                return (type == TypeEnum.INT
283                         || type == TypeEnum.INT_PMF);
284        }
285 
286        protected boolean isNumeric(TypeEnum type) {
287                return (type == TypeEnum.INT
288                         || type == TypeEnum.DOUBLE);
289        }
290 
291        private boolean isDoubleIntPMF(TypeEnum type) {
292                return (type == TypeEnum.DOUBLE
293                         || type == TypeEnum.INT
294                         || type == TypeEnum.INT_PMF
295                         || type == TypeEnum.DOUBLE_PMF);
296 
297        }
298 
299        private boolean isDoubleIntAnyPMF(TypeEnum type) {
300                return (type == TypeEnum.DOUBLE
301                                 || type == TypeEnum.INT
302                                 || type == TypeEnum.ANY
303                                 || type == TypeEnum.INT_PMF
304                                 || type == TypeEnum.DOUBLE_PMF
305                                 || type == TypeEnum.ANY_PMF);
306        }
307 
308 
309        private boolean isDoubleIntPDF(TypeEnum type) {
310                return (type == TypeEnum.DOUBLE
311                          || type == TypeEnum.INT
312                         || type == TypeEnum.INT_PMF
313                         || type == TypeEnum.DOUBLE_PMF
314                         || type == TypeEnum.DOUBLE_PDF);
315        }
316 
317        /**
318         * Getter for the type annotation hashmap.
319         * @return
320         */
321        public HashMap<Expression, TypeEnum> getTypeAnnotation() {
322                return typeAnnotation;
323        }
324 
325        /**
326         * Setter for the type annotation hashmap.
327         * @param typeAnnotation
328         */
329        public void setTypeAnnotation(HashMap<Expression, TypeEnum> typeAnnotation) {
330                this.typeAnnotation = typeAnnotation;
331        }
332 
333        /**Return the inferred type of the passed expression node.
334         * The type annotation is automatically stored in the Map if it has not been inferred before.
335         * @param e The node whose type should be returned.
336         * @return The inferred type of the expression.
337         */
338        public TypeEnum getType(Expression e)
339        {
340                if (!typeAnnotation.containsKey(e)) {
341                        doSwitch(e);
342                }
343                return typeAnnotation.get(e);
344        }
345 
346        @Override
347        public Object caseFunctionLiteral(FunctionLiteral object) {
348                for (Expression e : object.getParameters_FunctionLiteral())
349                        doSwitch(e);
350 
351                if (object.getId().equals(ProbfunctionHelper.UNIDOUBLE)) {
352                        typeAnnotation.put(object, TypeEnum.DOUBLE_PDF);
353                } else if (ProbfunctionHelper.isFunctionWithTwoParameterID(object.getId())) {
354                        typeAnnotation.put(object, TypeEnum.DOUBLE_PDF);
355                } else if (object.getId().equals(ProbfunctionHelper.EXP)) {
356                        typeAnnotation.put(object, TypeEnum.DOUBLE_PDF);
357                } else if (object.getId().equals(ProbfunctionHelper.POIS)) {
358                        typeAnnotation.put(object, TypeEnum.INT_PMF);
359                } else if (object.getId().equals(ProbfunctionHelper.UNIINT)) {
360                        typeAnnotation.put(object, TypeEnum.INT_PMF);
361                } else if (object.getId().equals("Trunc")) {
362                        typeAnnotation.put(object, TypeEnum.INT_PMF);
363                } else if (object.getId().equals("Round")) {
364                        typeAnnotation.put(object, TypeEnum.INT_PMF);
365                } else if (object.getId().equals("Min")) {
366                        if (object.getParameters_FunctionLiteral().size() > 0) {
367                                typeAnnotation.put(object, typeAnnotation.get(object.getParameters_FunctionLiteral().get(0)));
368                        } else {
369                                typeAnnotation.put(object, TypeEnum.ANY);
370                        }
371                } else if (object.getId().equals("Max")) {
372                        if (object.getParameters_FunctionLiteral().size() > 0) {
373                                typeAnnotation.put(object, typeAnnotation.get(object.getParameters_FunctionLiteral().get(0)));
374                        } else {
375                                typeAnnotation.put(object, TypeEnum.ANY);
376                        }
377                } else if (object.getId().equals("MinDeviation")) {
378                        if (object.getParameters_FunctionLiteral().size() > 0) {
379                                typeAnnotation.put(object, typeAnnotation.get(object.getParameters_FunctionLiteral().get(0)));
380                        } else {
381                                typeAnnotation.put(object, TypeEnum.ANY);
382                        }
383                } else if (object.getId().equals("MaxDeviation")) {
384                        if (object.getParameters_FunctionLiteral().size() > 0) {
385                                typeAnnotation.put(object, typeAnnotation.get(object.getParameters_FunctionLiteral().get(0)));
386                        } else {
387                                typeAnnotation.put(object, TypeEnum.ANY);
388                        }
389                } else if (object.getId().equals(ProbfunctionHelper.BINOM)) {
390                        typeAnnotation.put(object, TypeEnum.INT_PMF);
391                }  else
392                        throw new UnsupportedOperationException("Function "+object.getId()+" not supported!");
393                return object;
394        }
395 
396        @Override
397        public Object caseIfElseExpression(IfElseExpression object) {
398                doSwitch(object.getConditionExpression());
399                doSwitch(object.getElseExpression());
400                doSwitch(object.getIfExpression());
401 
402                typeAnnotation.put(object, TypeEnum.ANY);
403                return object;
404        }
405 
406        @Override
407        public Object caseStringLiteral(StringLiteral object) {
408                typeAnnotation.put(object,TypeEnum.ENUM);
409                return object;
410        }
411 
412}

[all classes][de.uka.ipd.sdq.stoex.analyser.visitors]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov