Skip to content

Commit

Permalink
Fix #7156 (#7157)
Browse files Browse the repository at this point in the history
- Try to inline operator record constructors instead of evaluating them
  when trying to split them during flattening.
  • Loading branch information
perost committed Feb 15, 2021
1 parent 3de3ab4 commit a489e50
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 9 deletions.
25 changes: 18 additions & 7 deletions OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -92,6 +92,7 @@ import DAE;
import Structural = NFStructural;
import ArrayConnections = NFArrayConnections;
import UnorderedMap;
import Inline = NFInline;

public
type FunctionTree = FunctionTreeImpl.Tree;
Expand Down Expand Up @@ -591,16 +592,26 @@ algorithm
if comp_var <= Variability.STRUCTURAL_PARAMETER or binding_var <= Variability.STRUCTURAL_PARAMETER then
binding_exp := Expression.stripBindingInfo(Ceval.evalExp(binding_exp));
elseif binding_var == Variability.PARAMETER and Component.isFinal(comp) then
// Try to use inlining first.
try
binding_exp_eval := Expression.stripBindingInfo(Ceval.evalExp(binding_exp));
// Throw away the evaluated binding if the number of dimensions no
// longer match after evaluation, in case Ceval fails to apply the
// subscripts correctly.
// TODO: Fix this, it shouldn't be needed.
0 := Type.dimensionDiff(ty, Expression.typeOf(binding_exp_eval));
binding_exp := binding_exp_eval;
binding_exp := Inline.inlineRecordConstructorCall(binding_exp);
else
end try;

// If inlining fails, try to evaluate the binding instead.
if not Expression.isRecord(binding_exp) then
try
binding_exp_eval := Expression.stripBindingInfo(Ceval.evalExp(binding_exp));

// Throw away the evaluated binding if the number of dimensions no
// longer match after evaluation, in case Ceval fails to apply the
// subscripts correctly.
// TODO: Fix this, it shouldn't be needed.
0 := Type.dimensionDiff(ty, Expression.typeOf(binding_exp_eval));
binding_exp := binding_exp_eval;
else
end try;
end if;
else
binding_exp := SimplifyExp.simplify(binding_exp);
end if;
Expand Down
46 changes: 44 additions & 2 deletions OMCompiler/Compiler/NFFrontEnd/NFInline.mo
Expand Up @@ -31,18 +31,24 @@

encapsulated package NFInline

import Call = NFCall;
import Expression = NFExpression;

protected
import Binding = NFBinding;
import Class = NFClass;
import Component = NFComponent;
import ComponentRef = NFComponentRef;
import DAE.InlineType;
import Dimension = NFDimension;
import Expression = NFExpression;
import Flags;
import Call = NFCall;
import NFFunction.Function;
import NFInstNode.InstNode;
import Statement = NFStatement;
import Subscript = NFSubscript;
import Type = NFType;

public
function inlineCallExp
input Expression callExp;
output Expression result;
Expand Down Expand Up @@ -113,6 +119,42 @@ algorithm
end match;
end inlineCall;

function inlineRecordConstructorCall
input Expression exp;
output Expression outExp;
protected
Function fn;
Expression arg;
list<Expression> args;
list<Statement> body;
Binding binding;
algorithm
outExp := match exp
case Expression.CALL(call = Call.TYPED_CALL(fn = fn, arguments = args))
guard InstNode.name(InstNode.parentScope(fn.node)) == "'constructor'"
algorithm
body := Function.getBody(fn);
true := listEmpty(body);
true := listEmpty(fn.locals);

binding := Component.getBinding(InstNode.component(listHead(fn.outputs)));

if Binding.hasExp(binding) then
outExp := Binding.getExp(binding);
true := Expression.isRecord(outExp);
else
outExp := Class.makeRecordExp(listHead(fn.outputs));
end if;

for i in fn.inputs loop
arg :: args := args;
outExp := Expression.map(outExp, func = function replaceCrefNode(node = i, value = arg));
end for;
then
outExp;
end match;
end inlineRecordConstructorCall;

protected
function replaceCrefNode
input output Expression exp;
Expand Down
34 changes: 34 additions & 0 deletions testsuite/flattening/modelica/scodeinst/Inline2.mo
@@ -0,0 +1,34 @@
// name: Inline2
// keywords:
// status: correct
// cflags: -d=newInst
//

operator record Complex
Real re, im;

encapsulated operator 'constructor'
function fromReal
import Complex;
input Real re;
input Real im = 0.0;
output Complex result(re = re, im = im);
algorithm
end fromReal;
end 'constructor';
end Complex;

model Inline2
parameter Real a = 1;
parameter Real b = 2;
final parameter Complex c = Complex(a, b);
end Inline2;

// Result:
// class Inline2
// parameter Real a = 1.0;
// parameter Real b = 2.0;
// final parameter Real c.re = a;
// final parameter Real c.im = b;
// end Inline2;
// endResult
1 change: 1 addition & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -609,6 +609,7 @@ ImportUnqualified2.mo \
ImportUnqualified3.mo \
ImpureCall1.mo \
Inline1.mo \
Inline2.mo \
InnerOuter1.mo \
InnerOuter2.mo \
InnerOuter3.mo \
Expand Down

0 comments on commit a489e50

Please sign in to comment.