From bab1c38e1597fff75ac428078f2e6a80fe5b5dc4 Mon Sep 17 00:00:00 2001 From: jkauttio Date: Wed, 22 Apr 2015 13:18:01 +0000 Subject: [PATCH] Implement support for else-if statements in internal solver fixes #5777 git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@31195 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../fi/semantum/sysdyn/solver/IfThenElse.java | 63 +++++++++++++------ .../src/fi/semantum/sysdyn/solver/Parser.java | 30 +++++++-- 2 files changed, 68 insertions(+), 25 deletions(-) diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/IfThenElse.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/IfThenElse.java index d8511d72..c18027b6 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/IfThenElse.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/IfThenElse.java @@ -14,33 +14,50 @@ import java.util.Map; public class IfThenElse implements IExpression { - public IExpression exp; - public IExpression t; - public IExpression e; + public IExpression[] condExpr; + public IExpression[] thenExpr; + public IExpression elseExpr; - public IfThenElse(IExpression exp, IExpression t, IExpression e) { - this.exp = exp; - this.t = t; - this.e = e; + public IfThenElse(IExpression condExpr, IExpression thenExpr, IExpression elseExpr) { + this(new IExpression[] { condExpr }, new IExpression[] { thenExpr }, elseExpr); + } + + public IfThenElse(IExpression[] condExpr, IExpression[] thenExpr, IExpression elseExpr) { + this.condExpr = condExpr; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; } @Override public String toString() { - return "if " + exp + " then " + t + " else "+ e; + StringBuilder str = new StringBuilder(); + str.append("if ").append(condExpr[0]).append(" then ").append(thenExpr[0]); + for (int i = 1; i < condExpr.length; i++) { + str.append(" else if ").append(condExpr[i]).append(" then ").append(thenExpr[i]); + } + str.append(" else ").append(elseExpr); + return str.toString(); } @Override public Object evaluate(IEnvironment environment) { - if((Boolean)exp.evaluate(environment)) { - return t.evaluate(environment); - } else { - return e.evaluate(environment); + for (int i = 0; i < condExpr.length; i++) { + if ((Boolean)condExpr[i].evaluate(environment)) { + return thenExpr[i].evaluate(environment); + } } + return elseExpr.evaluate(environment); } @Override public IExpression withBase(IFrame frame, String prefix) { - return new IfThenElse(exp.withBase(frame, prefix), t.withBase(frame, prefix), e.withBase(frame, prefix)); + IExpression[] newConds = new IExpression[condExpr.length]; + IExpression[] newThens = new IExpression[thenExpr.length]; + for (int i = 0; i < condExpr.length; i++) { + newConds[i] = condExpr[i].withBase(frame, prefix); + newThens[i] = thenExpr[i].withBase(frame, prefix); + } + return new IfThenElse(newConds, newThens, elseExpr.withBase(frame, prefix)); } @Override @@ -50,18 +67,26 @@ public class IfThenElse implements IExpression { @Override public IExpression rewrite(IFrame frame, Map copies) { - exp = exp.rewrite(frame, copies); - t = t.rewrite(frame, copies); - e = e.rewrite(frame, copies); + IExpression[] newConds = new IExpression[condExpr.length]; + IExpression[] newThens = new IExpression[thenExpr.length]; + for (int i = 0; i < condExpr.length; i++) { + newConds[i] = condExpr[i].rewrite(frame, copies); + newThens[i] = thenExpr[i].rewrite(frame, copies); + } + condExpr = newConds; + thenExpr = newThens; + elseExpr = elseExpr.rewrite(frame, copies); return this; } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); - exp.accept(visitor); - t.accept(visitor); - e.accept(visitor); + for (int i = 0; i < condExpr.length; i++) { + condExpr[i].accept(visitor); + thenExpr[i].accept(visitor); + } + elseExpr.accept(visitor); } } diff --git a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java index 3fe43ba4..fff4923a 100644 --- a/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java +++ b/fi.semantum.sysdyn.solver/src/fi/semantum/sysdyn/solver/Parser.java @@ -52,7 +52,7 @@ public class Parser { } public Object walk_(SimpleNode n, int indent, IFrame frame) { - + Model model = frame instanceof Model ? (Model)frame : null; // TODO: most of this should probably be implemented in the parser @@ -588,11 +588,29 @@ public class Parser { return walk((SimpleNode)n.jjtGetChild(0), indent+2, frame); } case if_expression: - if(n.jjtGetNumChildren() == 3) { - IExpression exp1 = (IExpression)walk((SimpleNode)n.jjtGetChild(0), indent+2, frame); - IExpression exp2 = (IExpression)walk((SimpleNode)n.jjtGetChild(1), indent+2, frame); - IExpression exp3 = (IExpression)walk((SimpleNode)n.jjtGetChild(2), indent+2, frame); - return new IfThenElse(exp1, exp2, exp3); + int children = n.jjtGetNumChildren(); + if (children >= 3 && children % 2 == 1) { + // a Modelica if-expression contains at least three clauses: + // a condition, a then-expression and an else-expression. The + // expression can also contain one or more elseif-expressions + // which contain a condition and a then-expression of their own. + int branches = (children - 1) / 2; + + IExpression[] condExpr = new IExpression[branches]; + IExpression[] thenExpr = new IExpression[branches]; + + for (int i = 0; i < branches; i++) { + condExpr[i] = (IExpression)walk((SimpleNode)n.jjtGetChild(2*i), indent+2, frame); + thenExpr[i] = (IExpression)walk((SimpleNode)n.jjtGetChild(2*i+1), indent+2, frame); + } + + IExpression elseExpr = (IExpression)walk((SimpleNode)n.jjtGetChild(children-1), indent+2, frame); + + return new IfThenElse(condExpr, thenExpr, elseExpr); + } + else { + // should definitely return something here as well, an error at the very least + throw new UnsupportedOperationException(); } case add_op: return n.op; -- 2.47.1