Skip to content

Commit

Permalink
Improve handling of records (#7417)
Browse files Browse the repository at this point in the history
- Make final components protected in record constructors.
- Improve detection of package constants to avoid misdetection in record
  constructors.
- Various minor fixes.
  • Loading branch information
perost committed Apr 27, 2021
1 parent a7afb17 commit 6f87df7
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 19 deletions.
7 changes: 7 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFComponent.mo
Expand Up @@ -1089,5 +1089,12 @@ public
end match;
end isTypeAttribute;

function isModifiable
input Component component;
output Boolean isModifiable;
algorithm
isModifiable := not isFinal(component) and not (isConst(component) and hasBinding(component));
end isModifiable;

annotation(__OpenModelica_Interface="frontend");
end NFComponent;
6 changes: 3 additions & 3 deletions OMCompiler/Compiler/NFFrontEnd/NFConvertDAE.mo
Expand Up @@ -1218,10 +1218,10 @@ algorithm
comp := InstNode.component(component);
attr := Component.getAttributes(comp);

if Component.isConst(comp) and Component.hasBinding(comp) then
vis := Visibility.PROTECTED;
else
if Component.isModifiable(comp) then
vis := InstNode.visibility(component);
else
vis := Visibility.PROTECTED;
end if;

binding := Component.getBinding(comp);
Expand Down
29 changes: 25 additions & 4 deletions OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.mo
Expand Up @@ -56,6 +56,7 @@ import NFPrefixes.Variability;
import Ceval = NFCeval;
import Package = NFPackage;
import SimplifyExp = NFSimplifyExp;
import ErrorExt;

public
function evaluate
Expand Down Expand Up @@ -568,7 +569,13 @@ algorithm
case Expression.CREF()
algorithm
if not isLocalFunctionVariable(e.cref, fnNode) then
outExp := Ceval.evalCref(e.cref, e, Ceval.EvalTarget.IGNORE_ERRORS(), evalSubscripts = false);
ErrorExt.setCheckpoint(getInstanceName());
try
outExp := Ceval.evalCref(e.cref, e, Ceval.EvalTarget.IGNORE_ERRORS(), evalSubscripts = false);
else
outExp := e;
end try;
ErrorExt.rollBack(getInstanceName());
outChanged := true;
elseif outChanged then
// If the cref's subscripts changed, recalculate its type.
Expand All @@ -591,12 +598,26 @@ function isLocalFunctionVariable
output Boolean res;
protected
InstNode node;
list<Function> fnl;
Function fn;
algorithm
if ComponentRef.isPackageConstant(cref) then
res := false;
elseif ComponentRef.nodeVariability(cref) <= Variability.PARAMETER then
node := InstNode.derivedParent(ComponentRef.node(ComponentRef.firstNonScope(cref)));
res := InstNode.refEqual(fnNode, node);
elseif ComponentRef.nodeVariability(cref) <= Variability.PARAMETER and ComponentRef.isCref(cref) then
node := InstNode.derivedParent(ComponentRef.node(ComponentRef.last(cref)));

if InstNode.isClass(node) then
fnl := Function.getCachedFuncs(node);

if listEmpty(fnl) then
res := false;
else
fn := listHead(fnl);
res := InstNode.refEqual(fnNode, fn.node);
end if;
else
res := false;
end if;
else
res := true;
end if;
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFFunction.mo
Expand Up @@ -505,7 +505,7 @@ uniontype Function
cache := InstNode.getFuncCache(InstNode.classScope(inNode));
outFuncs := match cache
case CachedData.FUNCTION() then cache.funcs;
else fail();
else {};
end match;
end getCachedFuncs;

Expand Down
18 changes: 10 additions & 8 deletions OMCompiler/Compiler/NFFrontEnd/NFRecord.mo
Expand Up @@ -250,27 +250,29 @@ algorithm
return;
end if;

stripConstructorAttributes(comp_node);
comp := InstNode.component(comp_node);

if Component.isConst(comp) and Component.hasBinding(comp) then
locals := comp_node :: locals;
else
if Component.isModifiable(comp) then
setFieldDirection(comp_node, Direction.INPUT);
inputs := comp_node :: inputs;
else
setFieldDirection(comp_node, Direction.NONE);
locals := comp_node :: locals;
end if;
end collectRecordParam;

function stripConstructorAttributes
function setFieldDirection
input InstNode field;
input Direction direction;
protected
Component comp = InstNode.component(field);
Component.Attributes attr;
algorithm
attr := Component.getAttributes(comp);
attr.direction := Direction.NONE;
attr.direction := direction;
comp := Component.setAttributes(attr, comp);
InstNode.updateComponent(comp, field);
end stripConstructorAttributes;
end setFieldDirection;

function collectRecordFields
input InstNode recNode;
Expand All @@ -295,7 +297,7 @@ algorithm
else
comp := InstNode.component(comp_node);

if Component.isConst(comp) and Component.hasBinding(comp) then
if not Component.isModifiable(comp) then
fields := Field.LOCAL(InstNode.name(comp_node)) :: fields;
elseif not Component.isOutput(comp) then
fields := Field.INPUT(InstNode.name(comp_node)) :: fields;
Expand Down
5 changes: 3 additions & 2 deletions OMCompiler/Compiler/NFFrontEnd/NFTyping.mo
Expand Up @@ -1099,8 +1099,9 @@ algorithm
parent := InstNode.parent(component);
binding := TypeCheck.matchBinding(binding, attrType, name, parent);

// Check the variability. All builtin attributes have parameter variability.
if Binding.variability(binding) > Variability.PARAMETER then
// Check the variability. All builtin attributes have parameter variability,
// unless we're in a function in which case we don't care.
if Binding.variability(binding) > Variability.PARAMETER and not InstContext.inFunction(context) then
Error.addSourceMessage(Error.HIGHER_VARIABILITY_BINDING,
{name, Prefixes.variabilityString(Variability.PARAMETER),
"'" + Binding.toString(binding) + "'", Prefixes.variabilityString(Binding.variability(binding))},
Expand Down
6 changes: 6 additions & 0 deletions OMCompiler/Compiler/Template/DAEDumpTV.mo
Expand Up @@ -158,6 +158,12 @@ package Absyn
end FULLYQUALIFIED;
end Path;

uniontype Direction
record INPUT end INPUT;
record OUTPUT end OUTPUT;
record BIDIR end BIDIR;
record INPUT_OUTPUT end INPUT_OUTPUT;
end Direction;
end Absyn;

package SCode
Expand Down
1 change: 1 addition & 0 deletions OMCompiler/Compiler/Template/DAEDumpTpl.tpl
Expand Up @@ -161,6 +161,7 @@ end dumpRecordVar;
template dumpRecordConstructorInputAttr(DAE.Attributes attr)
::=
match attr
case DAE.ATTR(direction = Absyn.INPUT()) then 'input '
case DAE.ATTR(visibility = SCode.PROTECTED()) then 'protected '
case DAE.ATTR(variability = SCode.CONST()) then 'constant '
else 'input '
Expand Down
Expand Up @@ -25,7 +25,7 @@ end FunctionRecordArg3;

// Result:
// function BaseR "Automatically generated record constructor for BaseR"
// constant Integer n;
// input Integer n;
// input Real[n] x;
// output BaseR res;
// end BaseR;
Expand Down
52 changes: 52 additions & 0 deletions testsuite/flattening/modelica/scodeinst/FunctionRecordArg4.mo
@@ -0,0 +1,52 @@
// name: FunctionRecordArg4
// keywords:
// status: correct
// cflags: -d=newInst
//

record BaseR
constant Integer n;
final parameter Real x[n] = ones(n);
end BaseR;

function f
input BaseR r;
output Real x;
algorithm
x := r.x * r.x;
end f;

record R = BaseR(final n = 2);

model FunctionRecordArg4
R r;
Real x = f(r);
end FunctionRecordArg4;

// Result:
// function BaseR "Automatically generated record constructor for BaseR"
// input Integer n;
// protected Real[n] x = fill(1.0, n);
// output BaseR res;
// end BaseR;
//
// function R "Automatically generated record constructor for R"
// protected Integer n = 2;
// protected Real[2] x = fill(1.0, n);
// output R res;
// end R;
//
// function f
// input BaseR r;
// output Real x;
// algorithm
// x := r.x * r.x;
// end f;
//
// class FunctionRecordArg4
// final constant Integer r.n = 2;
// final parameter Real r.x[1] = 1.0;
// final parameter Real r.x[2] = 1.0;
// Real x = f(r);
// end FunctionRecordArg4;
// endResult
1 change: 1 addition & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -577,6 +577,7 @@ FunctionNonInputOutputParameter.mo \
FunctionRecordArg1.mo \
FunctionRecordArg2.mo \
FunctionRecordArg3.mo \
FunctionRecordArg4.mo \
FunctionRecursive1.mo \
FunctionRecursive2.mo \
FunctionSections1.mo \
Expand Down

0 comments on commit 6f87df7

Please sign in to comment.