+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.modeling;
+
+import java.util.Stack;
+
+import org.simantics.basicexpression.analysis.DepthFirstAdapter;
+import org.simantics.basicexpression.node.AConstantValue;
+import org.simantics.basicexpression.node.ADivMultiplicative;
+import org.simantics.basicexpression.node.AMinusExpression;
+import org.simantics.basicexpression.node.AMultMultiplicative;
+import org.simantics.basicexpression.node.APlusExpression;
+import org.simantics.basicexpression.node.AVariablePrimary;
+import org.simantics.utils.datastructures.Triple;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class InvertBasicExpressionVisitorBase extends DepthFirstAdapter {
+
+ protected Stack<Object> stack = new Stack<>();
+
+ public InvertBasicExpressionVisitorBase() {
+ super();
+ }
+
+ public Object getResult() {
+ if(stack.size() != 1) return null;
+ return stack.pop();
+ }
+
+ @Override
+ public void outAConstantValue(AConstantValue node) {
+ stack.push(Double.valueOf(node.toString()));
+ }
+
+ @Override
+ public void outAVariablePrimary(AVariablePrimary node) {
+ String value = node.toString().trim();
+ stack.push(Triple.make(1.0, 0.0, value));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void outAPlusExpression(APlusExpression node) {
+
+ final Object o1 = stack.pop();
+ final Object o2 = stack.pop();
+
+ if(o1 instanceof Double && o2 instanceof Triple) {
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+ stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Triple) {
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+ stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Double) {
+ stack.push((Double)o1 + (Double)o2);
+ } else {
+ stack.push(Double.NaN);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void outAMinusExpression(AMinusExpression node) {
+
+ final Object o1 = stack.pop();
+ final Object o2 = stack.pop();
+
+ // o2 - o1
+ if(o1 instanceof Double && o2 instanceof Triple) {
+ // <triple> o2 - double o1
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+ stack.push(Triple.make(p.first, p.second - (Double)o1, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Triple) {
+ // double o2 - <triple> o1
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+ stack.push(Triple.make(-p.first, (Double)o2 - p.second, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Double) {
+ stack.push((Double)o2 - (Double)o1);
+ } else {
+ stack.push(Double.NaN);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void outAMultMultiplicative(AMultMultiplicative node) {
+
+ final Object o1 = stack.pop();
+ final Object o2 = stack.pop();
+
+ if(o1 instanceof Double && o2 instanceof Triple) {
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+ stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Triple) {
+ Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+ stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Double) {
+ stack.push((Double)o1 * (Double)o2);
+ } else {
+ stack.push(Double.NaN);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void outADivMultiplicative(ADivMultiplicative node) {
+
+ final Object o1 = stack.pop();
+ final Object o2 = stack.pop();
+
+ // o2 / o1
+ if(o1 instanceof Double && o2 instanceof Triple) {
+ // <triple> o2 / double o1
+ Triple<Double, Double, String> p = (Triple<Double,Double, String>)o2;
+ stack.push(Triple.make(p.first / (Double)o1, p.second / (Double)o1, p.third));
+ } else if (o2 instanceof Double && o1 instanceof Triple) {
+ // double o2 / <triple> o1
+ stack.push(Double.NaN);
+ } else if (o2 instanceof Double && o1 instanceof Double) {
+ stack.push((Double)o2 / (Double)o1);
+ } else {
+ stack.push(Double.NaN);
+ }
+
+ }
+
+}
\ No newline at end of file