diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo index 860e0b1b711..99fe66dfdb5 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo @@ -92,6 +92,7 @@ import DAE; import Structural = NFStructural; import ArrayConnections = NFArrayConnections; import UnorderedMap; +import Inline = NFInline; public type FunctionTree = FunctionTreeImpl.Tree; @@ -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; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInline.mo b/OMCompiler/Compiler/NFFrontEnd/NFInline.mo index a9bf1191ea8..db630974e89 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInline.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInline.mo @@ -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; @@ -113,6 +119,42 @@ algorithm end match; end inlineCall; +function inlineRecordConstructorCall + input Expression exp; + output Expression outExp; +protected + Function fn; + Expression arg; + list args; + list 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; diff --git a/testsuite/flattening/modelica/scodeinst/Inline2.mo b/testsuite/flattening/modelica/scodeinst/Inline2.mo new file mode 100644 index 00000000000..7504a9f0fad --- /dev/null +++ b/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 diff --git a/testsuite/flattening/modelica/scodeinst/Makefile b/testsuite/flattening/modelica/scodeinst/Makefile index 50b75e9579d..8a97c2ff3e8 100644 --- a/testsuite/flattening/modelica/scodeinst/Makefile +++ b/testsuite/flattening/modelica/scodeinst/Makefile @@ -609,6 +609,7 @@ ImportUnqualified2.mo \ ImportUnqualified3.mo \ ImpureCall1.mo \ Inline1.mo \ +Inline2.mo \ InnerOuter1.mo \ InnerOuter2.mo \ InnerOuter3.mo \