From d44625d8835b0f76069fab3e0abfa12775071921 Mon Sep 17 00:00:00 2001 From: perost Date: Fri, 21 Jan 2022 14:47:46 +0100 Subject: [PATCH] Allow looking up functions in nested components (#8444) - Allow comp1..compN.class1..classN.function(), previously only comp.class1..classN.function() was allowed. Fixes #8428 --- .openmodelica.aspell | 1 + .../Compiler/NFFrontEnd/NFLookupState.mo | 49 +++++++++---------- OMCompiler/Compiler/Util/Error.mo | 4 +- .../modelica/scodeinst/FuncViaComp3.mo | 30 ++++++++++++ .../flattening/modelica/scodeinst/Makefile | 1 + .../flattening/modelica/scodeinst/const13.mo | 2 +- .../flattening/modelica/scodeinst/lookup4.mo | 2 +- 7 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 testsuite/flattening/modelica/scodeinst/FuncViaComp3.mo diff --git a/.openmodelica.aspell b/.openmodelica.aspell index 172c64eda17..d57861e3d49 100644 --- a/.openmodelica.aspell +++ b/.openmodelica.aspell @@ -31,6 +31,7 @@ redeclare Modelica lhs CN +cN classDirectory DAE FMU diff --git a/OMCompiler/Compiler/NFFrontEnd/NFLookupState.mo b/OMCompiler/Compiler/NFFrontEnd/NFLookupState.mo index 1b767fe2548..4f10c3b914e 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFLookupState.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFLookupState.mo @@ -91,7 +91,7 @@ uniontype LookupState the rules for composite name lookup can be enforced." record BEGIN "The start state." end BEGIN; record COMP "A component." end COMP; - record COMP_COMP "A component found in component." end COMP_COMP; + record CLASS_COMP "A component found in a class." end CLASS_COMP; record COMP_CLASS "A class found in component." end COMP_CLASS; record COMP_FUNC "A function found in component." end COMP_FUNC; record PACKAGE "A package." end PACKAGE; @@ -174,7 +174,6 @@ uniontype LookupState case COMP_FUNC() then true; case CLASS() then isCallableType(node); case COMP() then isCallableComponent(node); - case COMP_COMP() then isCallableComponent(node); else false; end match; end isFunction; @@ -207,7 +206,7 @@ uniontype LookupState // Found the expected kind of element. case (COMP(), COMP()) then (); - case (COMP_COMP(), COMP()) then (); + case (CLASS_COMP(), COMP()) then (); case (PREDEF_COMP(), COMP()) then (); case (FUNC(), COMP()) then (); case (COMP_FUNC(), COMP()) then (); @@ -220,7 +219,6 @@ uniontype LookupState case (CLASS(), FUNC()) guard isCallableType(node) then (); case (COMP(), FUNC()) guard isCallableComponent(node) then (); - case (COMP_COMP(), FUNC()) guard isCallableComponent(node) then (); // Found a class via a component, but expected a function. case (COMP_CLASS(), FUNC()) @@ -260,7 +258,7 @@ uniontype LookupState case (ERROR(errorState = COMP_FUNC()), COMP()) algorithm name_str := InstNode.name(node); - Error.addSourceMessage(Error.CLASS_IN_COMPOSITE_COMP_NAME, + Error.addSourceMessage(Error.UNEXPECTED_COMPONENT_IN_COMPOSITE_NAME, {name_str, LookupStateName.toString(name)}, info); then fail(); @@ -275,7 +273,7 @@ uniontype LookupState fail(); // Found class when looking up a composite component name. - case (ERROR(errorState = COMP_COMP()), COMP()) + case (ERROR(errorState = CLASS_COMP()), COMP()) algorithm name_str := InstNode.name(node); Error.addSourceMessage(Error.CLASS_IN_COMPOSITE_COMP_NAME, @@ -284,7 +282,7 @@ uniontype LookupState fail(); // Found class via composite component name when actually looking for a class. - case (ERROR(errorState = COMP_COMP()), _) + case (ERROR(errorState = CLASS_COMP()), _) algorithm name_str := InstNode.name(node); Error.addSourceMessage(Error.LOOKUP_CLASS_VIA_COMP_COMP, @@ -352,7 +350,7 @@ uniontype LookupState str := match(state) case BEGIN() then ""; case COMP() then System.gettext("component"); - case COMP_COMP() then System.gettext("component"); + case CLASS_COMP() then System.gettext("component"); case COMP_CLASS() then System.gettext("class"); case COMP_FUNC() then System.gettext("function"); case PACKAGE() then System.gettext("package"); @@ -467,14 +465,14 @@ uniontype LookupState element is. The state machine looks like this flow diagram (nodes in [brackets] are nodes with an edge to themselves): - BEGIN----------------+-----------------+-------------+ - |(COMP) |(PACKAGE) |(CLASS/FUNC) - v v v - +---------------COMP------+----[PACKAGE]<->[CLASS/FUNC] - |(CLASS|PACKAGE) |(FUNC) |(COMP) |(COMP) - | | | |only if - v | v |package-like - [COMP_CLASS] | [COMP_COMP]<----------------+ + BEGIN----------------+----------------+--------------+ + |(COMP) |(PACKAGE) |(CLASS/FUNC) + v v v + +--------------[COMP]----------[PACKAGE]<->[CLASS/FUNC] + |(CLASS|PACKAGE) |(FUNC) | |(COMP) + | | | |only if + v | | |package-like + [COMP_CLASS] | +>[CLASS_COMP]<+ ^(CLASS|PACKAGE) | | | v(FUNC) | @@ -497,23 +495,24 @@ uniontype LookupState case (_, BEGIN()) then elementState; // Transitions from COMP. - case (COMP(), COMP()) then COMP_COMP(); + case (COMP(), COMP()) then COMP(); case (FUNC(), COMP()) then COMP_FUNC(); case (_, COMP()) then COMP_CLASS(); - // Transitions from COMP_COMP. - case (COMP(), COMP_COMP()) then COMP_COMP(); + // Transitions from CLASS_COMP. + case (COMP(), CLASS_COMP()) then CLASS_COMP(); + case (CLASS_COMP(), CLASS_COMP()) then CLASS_COMP(); // Transitions from PACKAGE. - case (COMP(), PACKAGE()) then COMP_COMP(); + case (COMP(), PACKAGE()) then CLASS_COMP(); case (_, PACKAGE()) then elementState; // Transitions from CLASS/FUNC. // next has already checked that the found element is encapsulated or // the class/func looks like a package, so any transition is fine here. - case (COMP(), CLASS()) then COMP_COMP(); + case (COMP(), CLASS()) then CLASS_COMP(); case (_, CLASS()) then elementState; - case (COMP(), FUNC()) then COMP_COMP(); + case (COMP(), FUNC()) then CLASS_COMP(); case (_, FUNC()) then elementState; // Transitions from COMP_CLASS. @@ -533,8 +532,8 @@ uniontype LookupState // We found a class when only components are allowed, i.e. when not looking // for a function via a component. - case (_, COMP_COMP()) - then ERROR(COMP_COMP()); + case (_, CLASS_COMP()) + then ERROR(CLASS_COMP()); else algorithm @@ -562,7 +561,7 @@ uniontype LookupState // case (BEGIN(), _, _) then (); // case (PACKAGE(), _, _) then (); // case (COMP(), _, _) then (); - // case (COMP_COMP(), _, _) then (); + // case (CLASS_COMP(), _, _) then (); // // Check if the found element is encapsulated, then it's ok to look it up in // // a non-package. diff --git a/OMCompiler/Compiler/Util/Error.mo b/OMCompiler/Compiler/Util/Error.mo index 12b851d3dab..8af16968d6c 100644 --- a/OMCompiler/Compiler/Util/Error.mo +++ b/OMCompiler/Compiler/Util/Error.mo @@ -261,7 +261,7 @@ public constant ErrorTypes.Message RECURSIVE_DEFINITION = ErrorTypes.MESSAGE(92, public constant ErrorTypes.Message NOT_ARRAY_TYPE_IN_FOR_STATEMENT = ErrorTypes.MESSAGE(93, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(), Gettext.gettext("Expression %s in for-statement must be an array type.")); public constant ErrorTypes.Message NON_CLASS_IN_COMP_FUNC_NAME = ErrorTypes.MESSAGE(94, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(), - Gettext.gettext("Found non-class %s while looking for function via component. The only valid form is c.C1..CN.f where c is a scalar component and C1..CN are classes.")); + Gettext.gettext("Found non-class %s while looking for function via component. The only valid form is c1..cN.C1..CN.f where c1..cN are scalar components and C1..CN are classes.")); public constant ErrorTypes.Message DIFFERENT_VARIABLES_SOLVED_IN_ELSEWHEN = ErrorTypes.MESSAGE(95, ErrorTypes.SYMBOLIC(), ErrorTypes.ERROR(), Gettext.gettext("The same variables must be solved in elsewhen clause as in the when clause.")); public constant ErrorTypes.Message CLASS_IN_COMPOSITE_COMP_NAME = ErrorTypes.MESSAGE(96, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(), @@ -862,6 +862,8 @@ public constant ErrorTypes.Message CONVERSION_NO_COMPATIBLE_SCRIPT_FOUND = Error public constant Gettext.TranslatableContent FUNCTION_CALL_EXPRESSION = Gettext.gettext("a function call expression"); public constant ErrorTypes.Message FUNCTION_ARGUMENT_MUST_BE = ErrorTypes.MESSAGE(394, ErrorTypes.SCRIPTING(), ErrorTypes.ERROR(), Gettext.gettext("The argument to ‘%s‘ must be %s.")); +public constant ErrorTypes.Message UNEXPECTED_COMPONENT_IN_COMPOSITE_NAME = ErrorTypes.MESSAGE(395, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(), + Gettext.gettext("Found component ‘%s‘ in composite name ‘%s‘, expected class.")); public constant ErrorTypes.Message INITIALIZATION_NOT_FULLY_SPECIFIED = ErrorTypes.MESSAGE(496, ErrorTypes.TRANSLATION(), ErrorTypes.WARNING(), Gettext.gettext("The initial conditions are not fully specified. %s.")); diff --git a/testsuite/flattening/modelica/scodeinst/FuncViaComp3.mo b/testsuite/flattening/modelica/scodeinst/FuncViaComp3.mo new file mode 100644 index 00000000000..f7211305764 --- /dev/null +++ b/testsuite/flattening/modelica/scodeinst/FuncViaComp3.mo @@ -0,0 +1,30 @@ +// name: FuncViaComp3 +// keywords: +// status: correct +// cflags: -d=newInst +// +// Checks that functions can be called via components. +// + + +model A + function f + input Integer n; + output Real x = 2; + end f; +end A; + +model B + A a; +end B; + +model FuncViaComp3 + B b; + Real x = b.a.f(1); +end FuncViaComp3; + +// Result: +// class FuncViaComp3 +// Real x = 2.0; +// end FuncViaComp3; +// endResult diff --git a/testsuite/flattening/modelica/scodeinst/Makefile b/testsuite/flattening/modelica/scodeinst/Makefile index a85ccd59fa4..660291780d0 100644 --- a/testsuite/flattening/modelica/scodeinst/Makefile +++ b/testsuite/flattening/modelica/scodeinst/Makefile @@ -596,6 +596,7 @@ FuncUnknownDim3.mo \ FuncVariability.mo \ FuncViaComp.mo \ FuncViaComp2.mo \ +FuncViaComp3.mo \ FuncVectorization1.mo \ FuncVectorization2.mo \ FuncVectorization3.mo \ diff --git a/testsuite/flattening/modelica/scodeinst/const13.mo b/testsuite/flattening/modelica/scodeinst/const13.mo index eaa7979e117..a0c6dddec6e 100644 --- a/testsuite/flattening/modelica/scodeinst/const13.mo +++ b/testsuite/flattening/modelica/scodeinst/const13.mo @@ -22,7 +22,7 @@ end C; // Result: // Error processing file: const13.mo -// [flattening/modelica/scodeinst/const13.mo:20:3-20:17:writable] Error: Found class y during lookup of composite component name 'a.B.y', expected component. +// [flattening/modelica/scodeinst/const13.mo:20:3-20:17:writable] Error: Found component ‘y‘ in composite name ‘a.B.y‘, expected class. // // # Error encountered! Exiting... // # Please check the error message and the flags. diff --git a/testsuite/flattening/modelica/scodeinst/lookup4.mo b/testsuite/flattening/modelica/scodeinst/lookup4.mo index 6e85a4faa6c..e0cb148da14 100644 --- a/testsuite/flattening/modelica/scodeinst/lookup4.mo +++ b/testsuite/flattening/modelica/scodeinst/lookup4.mo @@ -25,7 +25,7 @@ end M; // Result: // Error processing file: lookup4.mo -// [flattening/modelica/scodeinst/lookup4.mo:23:3-23:21:writable] Error: Found class C during lookup of composite component name 'a.b.C.d.x', expected component. +// [flattening/modelica/scodeinst/lookup4.mo:23:3-23:21:writable] Error: Found component ‘d‘ in composite name ‘a.b.C.d.x‘, expected class. // // # Error encountered! Exiting... // # Please check the error message and the flags.