Fixed InvertBasicExpressionVisitor bugs with subtractions and divisions
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / InvertBasicExpressionVisitorBase.java
1 /*******************************************************************************
2  * Copyright (c) 2020 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling;
13
14 import java.util.Stack;
15
16 import org.simantics.basicexpression.analysis.DepthFirstAdapter;
17 import org.simantics.basicexpression.node.AConstantValue;
18 import org.simantics.basicexpression.node.ADivMultiplicative;
19 import org.simantics.basicexpression.node.AMinusExpression;
20 import org.simantics.basicexpression.node.AMultMultiplicative;
21 import org.simantics.basicexpression.node.APlusExpression;
22 import org.simantics.basicexpression.node.AVariablePrimary;
23 import org.simantics.utils.datastructures.Triple;
24
25 /**
26  * @author Tuukka Lehtonen
27  */
28 public class InvertBasicExpressionVisitorBase extends DepthFirstAdapter {
29
30         protected Stack<Object> stack = new Stack<>();
31
32         public InvertBasicExpressionVisitorBase() {
33                 super();
34         }
35
36         public Object getResult() {
37                 if(stack.size() != 1) return null; 
38                 return stack.pop();
39         }
40
41         @Override
42         public void outAConstantValue(AConstantValue node) {
43                 stack.push(Double.valueOf(node.toString()));
44         }
45
46         @Override
47         public void outAVariablePrimary(AVariablePrimary node) {
48                 String value = node.toString().trim();
49                 stack.push(Triple.make(1.0, 0.0, value));
50         }
51
52         @SuppressWarnings("unchecked")
53         @Override
54         public void outAPlusExpression(APlusExpression node) {
55
56                 final Object o1 = stack.pop();
57                 final Object o2 = stack.pop();
58
59                 if(o1 instanceof Double && o2 instanceof Triple) {
60                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
61                         stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
62                 } else if (o2 instanceof Double && o1 instanceof Triple) {
63                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
64                         stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
65                 } else if (o2 instanceof Double && o1 instanceof Double) {
66                         stack.push((Double)o1 + (Double)o2);
67                 } else {
68                         stack.push(Double.NaN);
69                 }
70
71         }
72
73         @SuppressWarnings("unchecked")
74         @Override
75         public void outAMinusExpression(AMinusExpression node) {
76
77                 final Object o1 = stack.pop();
78                 final Object o2 = stack.pop();
79
80                 // o2 - o1
81                 if(o1 instanceof Double && o2 instanceof Triple) {
82                         // <triple> o2 - double o1
83                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
84                         stack.push(Triple.make(p.first, p.second - (Double)o1, p.third));
85                 } else if (o2 instanceof Double && o1 instanceof Triple) {
86                         // double o2 - <triple> o1
87                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
88                         stack.push(Triple.make(-p.first, (Double)o2 - p.second, p.third));
89                 } else if (o2 instanceof Double && o1 instanceof Double) {
90                         stack.push((Double)o2 - (Double)o1);
91                 } else {
92                         stack.push(Double.NaN);
93                 }
94
95         }
96
97         @SuppressWarnings("unchecked")
98         @Override
99         public void outAMultMultiplicative(AMultMultiplicative node) {
100
101                 final Object o1 = stack.pop();
102                 final Object o2 = stack.pop();
103
104                 if(o1 instanceof Double && o2 instanceof Triple) {
105                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
106                         stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
107                 } else if (o2 instanceof Double && o1 instanceof Triple) {
108                         Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
109                         stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
110                 } else if (o2 instanceof Double && o1 instanceof Double) {
111                         stack.push((Double)o1 * (Double)o2);
112                 } else {
113                         stack.push(Double.NaN);
114                 }
115
116         }
117
118         @SuppressWarnings("unchecked")
119         @Override
120         public void outADivMultiplicative(ADivMultiplicative node) {
121
122                 final Object o1 = stack.pop();
123                 final Object o2 = stack.pop();
124
125                 // o2 / o1
126                 if(o1 instanceof Double && o2 instanceof Triple) {
127                         // <triple> o2 / double o1 
128                         Triple<Double, Double, String> p = (Triple<Double,Double, String>)o2;
129                         stack.push(Triple.make(p.first / (Double)o1, p.second / (Double)o1, p.third));
130                 } else if (o2 instanceof Double && o1 instanceof Triple) {
131                         // double o2 / <triple> o1 
132                         stack.push(Double.NaN);
133                 } else if (o2 instanceof Double && o1 instanceof Double) {
134                         stack.push((Double)o2 / (Double)o1);
135                 } else {
136                         stack.push(Double.NaN);
137                 }
138
139         }
140
141 }