Skip to content

Commit

Permalink
Allow looking up functions in nested components (#8444)
Browse files Browse the repository at this point in the history
- Allow comp1..compN.class1..classN.function(), previously only
  comp.class1..classN.function() was allowed.

Fixes #8428
  • Loading branch information
perost committed Jan 21, 2022
1 parent ebaac9b commit d44625d
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 28 deletions.
1 change: 1 addition & 0 deletions .openmodelica.aspell
Expand Up @@ -31,6 +31,7 @@ redeclare
Modelica
lhs
CN
cN
classDirectory
DAE
FMU
Expand Down
49 changes: 24 additions & 25 deletions OMCompiler/Compiler/NFFrontEnd/NFLookupState.mo
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 ();
Expand All @@ -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())
Expand Down Expand Up @@ -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();
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -352,7 +350,7 @@ uniontype LookupState
str := match(state)
case BEGIN() then "<begin>";
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");
Expand Down Expand Up @@ -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) |
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 3 additions & 1 deletion OMCompiler/Compiler/Util/Error.mo
Expand Up @@ -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(),
Expand Down Expand Up @@ -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."));
Expand Down
30 changes: 30 additions & 0 deletions 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
1 change: 1 addition & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -596,6 +596,7 @@ FuncUnknownDim3.mo \
FuncVariability.mo \
FuncViaComp.mo \
FuncViaComp2.mo \
FuncViaComp3.mo \
FuncVectorization1.mo \
FuncVectorization2.mo \
FuncVectorization3.mo \
Expand Down
2 changes: 1 addition & 1 deletion testsuite/flattening/modelica/scodeinst/const13.mo
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion testsuite/flattening/modelica/scodeinst/lookup4.mo
Expand Up @@ -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.
Expand Down

0 comments on commit d44625d

Please sign in to comment.