Skip to content

Commit

Permalink
Fix handling of function parameter variability (#10836)
Browse files Browse the repository at this point in the history
- Remove variability prefixes from function parameters since they have
  no semantic meaning, to avoid e.g. function inputs being constant
  evaluated.
- Add some debug output from EvalFunction using the existing
  evalFuncDump debug flag.

Fixes #10828
  • Loading branch information
perost committed Jun 14, 2023
1 parent 1b1f969 commit b2f623e
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 55 deletions.
9 changes: 9 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo
Expand Up @@ -509,13 +509,22 @@ public
input output Attributes attr;
input Class cls;
input InstNode clsNode;
input InstNode compNode;
input InstContext.Type context;
protected
Variability var = attr.variability;
algorithm
if referenceEq(attr, NFAttributes.DEFAULT_ATTR) and InstNode.isDiscreteClass(clsNode) then
attr := NFAttributes.IMPL_DISCRETE_ATTR;
elseif var == Variability.CONTINUOUS and InstNode.isDiscreteClass(clsNode) then
attr.variability := Variability.IMPLICITLY_DISCRETE;
elseif var < Variability.CONTINUOUS and InstContext.inFunction(context) and
attr.direction <> Direction.NONE and
isNone(InstNode.getAnnotation("__OpenModelica_functionVariability", compNode)) then
// Variability prefixes on function parameters has no semantic meaning,
// remove them so we don't have to worry about accidentally evaluating
// e.g. an input declared as constant/parameter.
attr.variability := Variability.CONTINUOUS;
end if;
end updateVariability;

Expand Down
8 changes: 8 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo
Expand Up @@ -139,6 +139,14 @@ algorithm
fail();
end try;

if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print(AbsynUtil.pathString(Function.name(fn)) + " => ");
print(Expression.toString(result));
print("\nArguments:\n");
print(UnorderedMap.toString(arg_map, InstNode.name, Expression.toString));
print("\n");
end if;

Pointer.update(call_counter, call_count - 1);
end evaluateNormal;

Expand Down
23 changes: 15 additions & 8 deletions OMCompiler/Compiler/NFFrontEnd/NFFunction.mo
Expand Up @@ -496,9 +496,10 @@ uniontype Function
protected
SCode.Element def;
Integer numError = Error.getNumErrorMessages();
InstContext.Type fn_context = InstContext.set(context, NFInstContext.FUNCTION);
algorithm
try
fnNode := Inst.instantiate(fnNode, context = context, instPartial = true);
fnNode := Inst.instantiate(fnNode, context = fn_context, instPartial = true);
else
true := Error.getNumErrorMessages() == numError;
def := InstNode.definition(fnNode);
Expand Down Expand Up @@ -1534,11 +1535,14 @@ uniontype Function
protected
DAE.FunctionAttributes attr;
InstNode node = fn.node;
InstContext.Type fn_context;
algorithm
if not isTyped(fn) then
fn_context := InstContext.set(context, NFInstContext.FUNCTION);
// Type all the components in the function.
Typing.typeClassType(node, NFBinding.EMPTY_BINDING, context, node);
Typing.typeComponents(node, context, preserveDerived = isPartialDerivative(fn));
Typing.typeClassType(node, NFBinding.EMPTY_BINDING, fn_context, node);
Typing.typeComponents(node, fn_context, preserveDerived = isPartialDerivative(fn));
if InstNode.isPartial(node) then
ClassTree.applyComponents(Class.classTree(InstNode.getClass(node)), boxFunctionParameter);
Expand All @@ -1559,22 +1563,25 @@ uniontype Function
protected
Boolean pure;
DAE.FunctionAttributes attr;
InstContext.Type fn_context;
algorithm
fn_context := InstContext.set(context, NFInstContext.FUNCTION);
// Type the bindings of components in the function.
for c in fn.inputs loop
Typing.typeComponentBinding(c, context);
Typing.typeComponentBinding(c, fn_context);
end for;
for c in fn.outputs loop
Typing.typeComponentBinding(c, context);
Typing.typeComponentBinding(c, fn_context);
end for;
for c in fn.locals loop
Typing.typeComponentBinding(c, context);
Typing.typeComponentBinding(c, fn_context);
end for;
// Type the algorithm section of the function, if it has one.
Typing.typeFunctionSections(fn.node, context);
Typing.typeFunctionSections(fn.node, fn_context);
// Type any derivatives of the function.
for fn_der in fn.derivatives loop
Expand All @@ -1596,7 +1603,7 @@ uniontype Function
end if;
end if;
if not InstContext.inRelaxed(context) then
if not InstContext.inRelaxed(fn_context) then
checkUseBeforeAssign(fn);
end if;
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFInst.mo
Expand Up @@ -1833,7 +1833,7 @@ algorithm
checkBindingRestriction(res, binding, node, info);

// Update some of the attributes now that we now the type of the component.
ty_attr := Attributes.updateVariability(ty_attr, ty, ty_node);
ty_attr := Attributes.updateVariability(ty_attr, ty, ty_node, node, context);
ty_attr := Attributes.updateComponentConnectorType(ty_attr, res, context, node);

if not referenceEq(attr, ty_attr) then
Expand Down
34 changes: 17 additions & 17 deletions OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo
Expand Up @@ -436,7 +436,7 @@ function symmetric<T> "Returns a symmetric matrix"
end symmetric;

function smooth<RealArrayOrRecord> "Indicate smoothness of expression"
parameter input Integer p;
parameter input Integer p annotation(__OpenModelica_functionVariability=true);
input RealArrayOrRecord expr;
output RealArrayOrRecord s;
external "builtin";
Expand Down Expand Up @@ -535,8 +535,8 @@ function sample = $overload(OMC_NO_CLOCK.sample, OMC_CLOCK.sample)

package OMC_NO_CLOCK
impure function sample "Overloaded operator to either trigger time events or to convert between continuous-time and clocked-time representation"
parameter input Real start;
parameter input Real interval;
parameter input Real start annotation(__OpenModelica_functionVariability=true);
parameter input Real interval annotation(__OpenModelica_functionVariability=true);
output Boolean b;
external "builtin";
annotation(Documentation(info="<html>
Expand All @@ -559,8 +559,8 @@ end OMC_CLOCK;

function shiftSample<__Any> "First activation of clock is shifted in time"
input __Any u;
parameter input Integer shiftCounter(min = 0);
parameter input Integer resolution(min = 1) = 1;
parameter input Integer shiftCounter(min = 0) annotation(__OpenModelica_functionVariability=true);
parameter input Integer resolution(min = 1) = 1 annotation(__OpenModelica_functionVariability=true);
output __Any c;
external "builtin";
annotation(__OpenModelica_builtin=true, version="Modelica 3.3", Documentation(info="<html>
Expand All @@ -570,8 +570,8 @@ end shiftSample;

function backSample<__Any> "First activation of clock is shifted in time before activation of u"
input __Any u;
parameter input Integer backCounter(min = 0);
parameter input Integer resolution(min = 1) = 1;
parameter input Integer backCounter(min = 0) annotation(__OpenModelica_functionVariability=true);
parameter input Integer resolution(min = 1) = 1 annotation(__OpenModelica_functionVariability=true);
output __Any c;
external "builtin";
annotation(__OpenModelica_builtin=true, version="Modelica 3.3", Documentation(info="<html>
Expand Down Expand Up @@ -729,7 +729,7 @@ encapsulated package Connections

function potentialRoot
input VariableName node;
parameter input Integer priority = 0;
parameter input Integer priority = 0 annotation(__OpenModelica_functionVariability=true);
external "builtin";
annotation(__OpenModelica_builtin=true);
end potentialRoot;
Expand Down Expand Up @@ -859,8 +859,8 @@ function spatialDistribution "Not yet implemented"
input Real in1;
input Real x;
input Boolean positiveVelocity;
parameter input Real initialPoints[:](each min = 0, each max = 1) = {0.0, 1.0};
parameter input Real initialValues[size(initialPoints, 1)] = {0.0, 0.0};
parameter input Real initialPoints[:](each min = 0, each max = 1) = {0.0, 1.0} annotation(__OpenModelica_functionVariability=true);
parameter input Real initialValues[size(initialPoints, 1)] = {0.0, 0.0} annotation(__OpenModelica_functionVariability=true);
output Real out0;
output Real out1;
external "builtin";
Expand Down Expand Up @@ -1043,7 +1043,7 @@ package Internal "Contains internal implementations, e.g. overloaded builtin fun

function rationalClock
input Integer intervalCounter(min=0);
parameter input Integer resolution(min = 1) = 1;
parameter input Integer resolution(min = 1) = 1 annotation(__OpenModelica_functionVariability=true);
output Clock c;
external "builtin";
end rationalClock;
Expand All @@ -1070,35 +1070,35 @@ package Internal "Contains internal implementations, e.g. overloaded builtin fun

impure function subSampleExpression<__Any>
input __Any u;
parameter input Integer factor(min=0)=0;
parameter input Integer factor(min=0)=0 annotation(__OpenModelica_functionVariability=true);
output __Any y;
external "builtin" y=subSample(u,factor);
end subSampleExpression;

impure function subSampleClock
input Clock u;
parameter input Integer factor(min=0)=0;
parameter input Integer factor(min=0)=0 annotation(__OpenModelica_functionVariability=true);
output Clock y;
external "builtin" y=subSample(u,factor);
end subSampleClock;

impure function superSampleExpression<__Any>
input __Any u;
parameter input Integer factor(min=0)=0;
parameter input Integer factor(min=0)=0 annotation(__OpenModelica_functionVariability=true);
output __Any y;
external "builtin" y=superSample(u,factor);
end superSampleExpression;

impure function superSampleClock
input Clock u;
parameter input Integer factor(min=0)=0;
parameter input Integer factor(min=0)=0 annotation(__OpenModelica_functionVariability=true);
output Clock y;
external "builtin" y=superSample(u,factor);
end superSampleClock;

impure function delay2
input Real expr;
parameter input Real delayTime;
parameter input Real delayTime annotation(__OpenModelica_functionVariability=true);
output Real value;
algorithm
value := delay3(expr, delayTime, delayTime);
Expand All @@ -1107,7 +1107,7 @@ package Internal "Contains internal implementations, e.g. overloaded builtin fun

impure function delay3
input Real expr, delayTime;
parameter input Real delayMax;
parameter input Real delayMax annotation(__OpenModelica_functionVariability=true);
output Real value;
external "builtin" value=delay(expr, delayTime, delayMax);
end delay3;
Expand Down
26 changes: 0 additions & 26 deletions testsuite/flattening/modelica/scodeinst/FuncVariability.mo

This file was deleted.

@@ -0,0 +1,29 @@
// name: FunctionParamVariability
// keywords:
// status: correct
// cflags: -d=newInst
//
// Checks that declaring a function parameter constant/parameter has no impact
// on the function, since variability prefixes have no semantic meaning for
// function parameters.
//

function f
constant input Real x = 1.0;
parameter output Real y = x + x;
end f;

model FunctionParamVariability
Real x = f(time);
end FunctionParamVariability;

// Result:
// function f
// input Real x = 1.0;
// output Real y = x + x;
// end f;
//
// class FunctionParamVariability
// Real x = f(time);
// end FunctionParamVariability;
// endResult
2 changes: 1 addition & 1 deletion testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -624,7 +624,6 @@ FuncStringInvalid2.mo \
FuncUnknownDim1.mo \
FuncUnknownDim2.mo \
FuncUnknownDim3.mo \
FuncVariability.mo \
FuncViaComp.mo \
FuncViaComp2.mo \
FuncViaComp3.mo \
Expand Down Expand Up @@ -667,6 +666,7 @@ FunctionMultiOutput4.mo \
FunctionMultiOutput5.mo \
FunctionNoOutput1.mo \
FunctionNonInputOutputParameter.mo \
FunctionParamVariability.mo \
FunctionPartialDerivative1.mo \
FunctionPartialDerivative2.mo \
FunctionPartialDerivative3.mo \
Expand Down
4 changes: 2 additions & 2 deletions testsuite/flattening/modelica/scodeinst/Ticket5821.mo
Expand Up @@ -2169,8 +2169,8 @@ end Test_total;
// input Modelica.Blocks.Types.ExternalCombiTimeTable tableID;
// input Integer icol;
// input Real timeIn;
// discrete input Real nextTimeEvent;
// discrete input Real pre_nextTimeEvent;
// input Real nextTimeEvent;
// input Real pre_nextTimeEvent;
// output Real y;
//
// external "C" y = ModelicaStandardTables_CombiTimeTable_getValue(tableID, icol, timeIn, nextTimeEvent, pre_nextTimeEvent);
Expand Down

0 comments on commit b2f623e

Please sign in to comment.