Skip to content

Commit

Permalink
[NF] Improve handling of if-equations.
Browse files Browse the repository at this point in the history
- Delay branch selection for if-equations to flattening (for
  if-equations containing connects) or model simplification (for other
  if-equations).

Belonging to [master]:
  - OpenModelica/OMCompiler#2725
  - OpenModelica/OpenModelica-testsuite#1051
  • Loading branch information
perost authored and OpenModelica-Hudson committed Oct 17, 2018
1 parent 9595dac commit e14b054
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 53 deletions.
2 changes: 1 addition & 1 deletion Compiler/NFFrontEnd/NFComponentRef.mo
Expand Up @@ -334,7 +334,7 @@ public
ComponentRef rest_cref;
list<Subscript> cref_subs;

case CREF(origin = Origin.CREF, subscripts = cref_subs)
case CREF(subscripts = cref_subs)
algorithm
(subscripts, rest_cref) := applySubscripts2(subscripts, cref.restCref);

Expand Down
10 changes: 9 additions & 1 deletion Compiler/NFFrontEnd/NFConvertDAE.mo
Expand Up @@ -548,6 +548,12 @@ algorithm
(conds, branches) := match branch
case Equation.Branch.BRANCH()
then (branch.condition :: conds, branch.body :: branches);

case Equation.Branch.INVALID_BRANCH()
algorithm
Equation.Branch.triggerErrors(branch);
then
fail();
end match;
end for;

Expand All @@ -564,6 +570,8 @@ algorithm
end if;

dconds := listReverse(Expression.toDAE(c) for c in conds);
dbranches := listReverseInPlace(dbranches);

ifEquation := if isInitial then
DAE.Element.INITIAL_IF_EQUATION(dconds, dbranches, else_branch, source) else
DAE.Element.IF_EQUATION(dconds, dbranches, else_branch, source);
Expand Down Expand Up @@ -596,7 +604,7 @@ function convertInitialEquations
input list<Equation> equations;
input output list<DAE.Element> elements = {};
algorithm
for eq in equations loop
for eq in listReverse(equations) loop
elements := convertInitialEquation(eq, elements);
end for;
end convertInitialEquations;
Expand Down
118 changes: 117 additions & 1 deletion Compiler/NFFrontEnd/NFEquation.mo
Expand Up @@ -37,6 +37,7 @@ encapsulated uniontype NFEquation
import DAE;
import ComponentRef = NFComponentRef;
import NFPrefixes.Variability;
import Error;

protected
import Equation = NFEquation;
Expand All @@ -52,12 +53,37 @@ public
list<Equation> body;
end BRANCH;

record INVALID_BRANCH
Branch branch;
list<Error.TotalMessage> errors;
end INVALID_BRANCH;

function toString
input Branch branch;
output String str;
algorithm
str := Expression.toString(branch.condition) + " then\n" + toStringList(branch.body);
str := match branch
case BRANCH()
then Expression.toString(branch.condition) + " then\n" + toStringList(branch.body);

case INVALID_BRANCH()
then toString(branch.branch);
end match;
end toString;

function triggerErrors
input Branch branch;
algorithm
() := match branch
case INVALID_BRANCH()
algorithm
Error.addTotalMessages(branch.errors);
then
fail();

else ();
end match;
end triggerErrors;
end Branch;

record EQUALITY
Expand Down Expand Up @@ -525,6 +551,96 @@ public
end match;
end foldExp;

function contains
input Equation eq;
input PredFn func;
output Boolean res;

partial function PredFn
input Equation eq;
output Boolean res;
end PredFn;
algorithm
if func(eq) then
res := true;
return;
end if;

res := match eq
case FOR() then containsList(eq.body, func);

case IF()
algorithm
for b in eq.branches loop
() := match b
case Branch.BRANCH()
algorithm
if containsList(b.body, func) then
res := true;
return;
end if;
then
();

else ();
end match;
end for;
then
false;

case WHEN()
algorithm
for b in eq.branches loop
() := match b
case Branch.BRANCH()
algorithm
if containsList(b.body, func) then
res := true;
return;
end if;
then
();

else ();
end match;
end for;
then
false;

else false;
end match;
end contains;

function containsList
input list<Equation> eql;
input PredFn func;
output Boolean res;

partial function PredFn
input Equation eq;
output Boolean res;
end PredFn;
algorithm
for eq in eql loop
if contains(eq, func) then
res := true;
return;
end if;
end for;

res := false;
end containsList;

function isConnect
input Equation eq;
output Boolean isConnect;
algorithm
isConnect := match eq
case CONNECT() then true;
else false;
end match;
end isConnect;

function toString
input Equation eq;
output String str;
Expand Down
10 changes: 10 additions & 0 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -3854,6 +3854,16 @@ public
end match;
end isInteger;

function isBoolean
input Expression exp;
output Boolean isBool;
algorithm
isBool := match exp
case BOOLEAN() then true;
else false;
end match;
end isBoolean;

function isRecord
input Expression exp;
output Boolean isRecord;
Expand Down
57 changes: 50 additions & 7 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -894,7 +894,7 @@ algorithm
Equation.CONNECT(e1, e2, eql, eq.source) :: equations;

case Equation.IF()
then flattenIfEquation(eq.branches, prefix, eq.source, equations);
then flattenIfEquation(eq, prefix, equations);

case Equation.WHEN()
algorithm
Expand Down Expand Up @@ -934,25 +934,40 @@ algorithm
end flattenEquation;

function flattenIfEquation
input list<Equation.Branch> branches;
input Equation eq;
input ComponentRef prefix;
input DAE.ElementSource source;
input output list<Equation> equations;
protected
list<Equation.Branch> bl = {};
list<Equation.Branch> branches, bl = {};
Expression cond;
list<Equation> eql;
Variability var;
Boolean has_connect;
DAE.ElementSource src;
algorithm
Equation.IF(branches = branches, source = src) := eq;
has_connect := Equation.contains(eq, isConnectEq);

for b in branches loop
bl := match b
case Equation.Branch.BRANCH(cond, var, eql)
algorithm
// flatten the condition first
// Flatten the condition and body of the branch.
cond := flattenExp(cond, prefix);
// flatten the equations
eql := flattenEquations(eql, prefix);

// Force branch selection if the if-equation contains connects.
if has_connect then
cond := Ceval.evalExp(cond);

if not Expression.isBoolean(cond) then
Error.addInternalError(
"Failed to evaluate branch condition in if equation containing connect equations: `" +
Expression.toString(cond) + "`", Equation.info(eq));
fail();
end if;
end if;

if Expression.isTrue(cond) and listEmpty(bl) then
// If the condition is literal true and we haven't collected any other
// branches yet, replace the if equation with this branch.
Expand All @@ -966,17 +981,45 @@ algorithm
then
bl;

// An invalid branch must have a false condition if the if-equation
// contains connects, anything else is an error.
case Equation.Branch.INVALID_BRANCH(branch = Equation.Branch.BRANCH(condition = cond))
guard has_connect
algorithm
cond := Ceval.evalExp(cond);

if not Expression.isFalse(cond) then
Equation.Branch.triggerErrors(b);
end if;
then
bl;

else b :: bl;
end match;
end for;

// Add the flattened if equation to the list of equations if we got this far,
// and there are any branches still remaining.
if not listEmpty(bl) then
equations := Equation.IF(listReverseInPlace(bl), source) :: equations;
equations := Equation.IF(listReverseInPlace(bl), src) :: equations;
end if;
end flattenIfEquation;

function isConnectEq
input Equation eq;
output Boolean isConnect;
algorithm
isConnect := match eq
local
Function fn;

case Equation.CONNECT() then true;
case Equation.NORETCALL(exp = Expression.CALL(call = Call.TYPED_CALL(fn = fn)))
then Absyn.pathFirstIdent(Function.name(fn)) == "Connections";
else false;
end match;
end isConnectEq;

function flattenEqBranch
input output Equation.Branch branch;
input ComponentRef prefix;
Expand Down
3 changes: 2 additions & 1 deletion Compiler/NFFrontEnd/NFInst.mo
Expand Up @@ -2994,14 +2994,15 @@ end markStructuralParamsExp;

function markStructuralParamsExp_traverser
input Expression exp;
import NFComponentRef.Origin;
algorithm
() := match exp
local
InstNode node;
Component comp;
Option<Expression> binding;

case Expression.CREF(cref = ComponentRef.CREF(node = node))
case Expression.CREF(cref = ComponentRef.CREF(node = node, origin = Origin.CREF))
algorithm
if InstNode.isComponent(node) then
comp := InstNode.component(node);
Expand Down
12 changes: 7 additions & 5 deletions Compiler/NFFrontEnd/NFOCConnectionGraph.mo
Expand Up @@ -1250,9 +1250,9 @@ algorithm
rooted = setRootDistance(inRoots,table,0,{},NFHashTable.emptyHashTable());
// BaseHashTable.dumpHashTable(rooted);
outEquations =
list(Equation.mapExp(eq,
function evaluateOperators(inRoots = (rooted,inRoots,graph)))
for eq in inEquations);
list(Equation.mapExp(eq,
function evaluateOperators(inRoots = (rooted,inRoots,graph), info = Equation.info(eq)))
for eq in inEquations);
then outEquations;

end matchcontinue;
Expand All @@ -1261,15 +1261,17 @@ end evalConnectionsOperators;
function evaluateOperators
input output Expression exp;
input tuple<NFHashTable.HashTable,list<ComponentRef>, NFOCConnectionGraph> inRoots;
input SourceInfo info;
algorithm
exp := Expression.map(exp,
function evalConnectionsOperatorsHelper(inRoots = inRoots));
function evalConnectionsOperatorsHelper(inRoots = inRoots, info = info));
end evaluateOperators;

protected function evalConnectionsOperatorsHelper
"Helper function for evaluation of Connections.rooted, Connections.isRoot, Connections.uniqueRootIndices"
input Expression inExp;
input tuple<NFHashTable.HashTable,list<ComponentRef>, NFOCConnectionGraph> inRoots;
input SourceInfo info;
output Expression outExp;
algorithm
outExp := matchcontinue (inExp,inRoots)
Expand Down Expand Up @@ -1321,7 +1323,7 @@ algorithm
end if;
else // add an error message:
str := ComponentRef.toString(cref);
Error.addMessage(Error.OCG_MISSING_BRANCH, {str, str, str});
Error.addSourceMessage(Error.OCG_MISSING_BRANCH, {str, str, str}, info);
result := false;
end try;
then
Expand Down
15 changes: 15 additions & 0 deletions Compiler/NFFrontEnd/NFSimplifyModel.mo
Expand Up @@ -381,6 +381,21 @@ algorithm
then
accum;

case Equation.INVALID_BRANCH(branch =
Equation.Branch.BRANCH(condition = cond, conditionVar = var))
algorithm
if var <= Variability.STRUCTURAL_PARAMETER then
cond := Ceval.evalExp(cond);
end if;

// An invalid branch that can't be removed will trigger the errors
// stored in it.
if not Expression.isFalse(cond) then
Equation.Branch.triggerErrors(branch);
end if;
then
accum;

else branch :: accum;
end match;
end for;
Expand Down

0 comments on commit e14b054

Please sign in to comment.