diff --git a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo index e679458456b..43695f94479 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo @@ -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; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFConvertDAE.mo b/OMCompiler/Compiler/NFFrontEnd/NFConvertDAE.mo index b18bb6eeb1b..16959991c2e 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFConvertDAE.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFConvertDAE.mo @@ -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); diff --git a/OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.mo b/OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.mo index a44f424475e..4528465a861 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.mo @@ -56,6 +56,7 @@ import NFPrefixes.Variability; import Ceval = NFCeval; import Package = NFPackage; import SimplifyExp = NFSimplifyExp; +import ErrorExt; public function evaluate @@ -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. @@ -591,12 +598,26 @@ function isLocalFunctionVariable output Boolean res; protected InstNode node; + list 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; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFunction.mo b/OMCompiler/Compiler/NFFrontEnd/NFFunction.mo index 35c40e7135c..33cb93427cc 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFunction.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFunction.mo @@ -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; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo b/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo index ff1b82ff9e5..f72d32eef4c 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo @@ -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; @@ -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; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo index f00287e12f1..37f5bf7d36f 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo @@ -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))}, diff --git a/OMCompiler/Compiler/Template/DAEDumpTV.mo b/OMCompiler/Compiler/Template/DAEDumpTV.mo index 7bdcbbba880..d90ccc131bc 100644 --- a/OMCompiler/Compiler/Template/DAEDumpTV.mo +++ b/OMCompiler/Compiler/Template/DAEDumpTV.mo @@ -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 diff --git a/OMCompiler/Compiler/Template/DAEDumpTpl.tpl b/OMCompiler/Compiler/Template/DAEDumpTpl.tpl index 4195490f261..ec9004eab92 100644 --- a/OMCompiler/Compiler/Template/DAEDumpTpl.tpl +++ b/OMCompiler/Compiler/Template/DAEDumpTpl.tpl @@ -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 ' diff --git a/testsuite/flattening/modelica/scodeinst/FunctionRecordArg3.mo b/testsuite/flattening/modelica/scodeinst/FunctionRecordArg3.mo index 8046dce1267..0a402bb9706 100644 --- a/testsuite/flattening/modelica/scodeinst/FunctionRecordArg3.mo +++ b/testsuite/flattening/modelica/scodeinst/FunctionRecordArg3.mo @@ -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; diff --git a/testsuite/flattening/modelica/scodeinst/FunctionRecordArg4.mo b/testsuite/flattening/modelica/scodeinst/FunctionRecordArg4.mo new file mode 100644 index 00000000000..0e2a0304516 --- /dev/null +++ b/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 diff --git a/testsuite/flattening/modelica/scodeinst/Makefile b/testsuite/flattening/modelica/scodeinst/Makefile index ed6b5f9a2de..9dab51efe35 100644 --- a/testsuite/flattening/modelica/scodeinst/Makefile +++ b/testsuite/flattening/modelica/scodeinst/Makefile @@ -577,6 +577,7 @@ FunctionNonInputOutputParameter.mo \ FunctionRecordArg1.mo \ FunctionRecordArg2.mo \ FunctionRecordArg3.mo \ +FunctionRecordArg4.mo \ FunctionRecursive1.mo \ FunctionRecursive2.mo \ FunctionSections1.mo \