Skip to content

Commit

Permalink
Improve error handling of inner/outer.
Browse files Browse the repository at this point in the history
- Give an error and fail if a simulation model contains a top-level
  outer, since the model should only be usable as part of another model
  in that case (unless doing checkModel).
- Give an error and fail if a simulation model has a missing inner
  component and also a top-level element with the same name, since the
  generated inner would then conflict with the existing element.
  • Loading branch information
perost committed Nov 27, 2020
1 parent b616440 commit 782d8ca
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 13 deletions.
37 changes: 35 additions & 2 deletions OMCompiler/Compiler/NFFrontEnd/NFInst.mo
Expand Up @@ -150,7 +150,7 @@ algorithm
inst_cls := instantiate(cls, context = context);
checkPartialClass(cls, context);

insertGeneratedInners(inst_cls, top);
insertGeneratedInners(inst_cls, top, context);
execStat("NFInst.instantiate(" + name + ")");

// Instantiate expressions (i.e. anything that can contains crefs, like
Expand Down Expand Up @@ -3306,15 +3306,17 @@ function insertGeneratedInners
the class we're instantiating, so that they are typed and flattened properly."
input InstNode node;
input InstNode topScope;
input InstContext.Type context;
protected
NodeTree.Tree inner_tree;
list<tuple<String, InstNode>> inner_nodes;
list<Mutable<InstNode>> inner_comps;
InstNode n;
InstNode n, on;
String name, str;
Class cls;
ClassTree cls_tree;
InstNode base_node;
Boolean name_defined;
algorithm
CachedData.TOP_SCOPE(addedInner = inner_tree) := InstNode.getInnerOuterCache(topScope);

Expand All @@ -3329,6 +3331,8 @@ algorithm
for e in inner_nodes loop
(name, n) := e;

checkTopLevelOuter(name, n, node, context);

// Always print a warning that an inner element was automatically generated.
Error.addSourceMessage(Error.MISSING_INNER_ADDED,
{InstNode.typeName(n), name}, InstNode.info(n));
Expand Down Expand Up @@ -3362,6 +3366,35 @@ algorithm
end if;
end insertGeneratedInners;

function checkTopLevelOuter
input String name;
input InstNode outerNode;
input InstNode scope;
input InstContext.Type context;
protected
InstNode node;
Boolean is_error;
algorithm
try
node := Lookup.lookupSimpleName(name, scope);

if InstNode.isInner(node) then
Error.addSourceMessage(Error.TOP_LEVEL_OUTER, {name}, InstNode.info(node));
is_error := not InstContext.inRelaxed(context);
else
Error.addMultiSourceMessage(Error.MISSING_INNER_NAME_CONFLICT,
{name}, {InstNode.info(node), InstNode.info(outerNode)});
is_error := true;
end if;
else
is_error := false;
end try;

if is_error then
fail();
end if;
end checkTopLevelOuter;

function updateImplicitVariability
input InstNode node;
input Boolean parentEval;
Expand Down
4 changes: 2 additions & 2 deletions OMCompiler/Compiler/Script/NFApi.mo
Expand Up @@ -631,7 +631,7 @@ algorithm
// Instantiate the class.
inst_cls := NFInst.instantiate(cls, context = NFInstContext.RELAXED);

NFInst.insertGeneratedInners(inst_cls, top);
NFInst.insertGeneratedInners(inst_cls, top, NFInstContext.RELAXED);

// Instantiate expressions (i.e. anything that can contains crefs, like
// bindings, dimensions, etc). This is done as a separate step after
Expand Down Expand Up @@ -772,7 +772,7 @@ algorithm

// Expand the class.
expanded_cls := NFInst.expand(cls);
NFInst.insertGeneratedInners(expanded_cls, top);
NFInst.insertGeneratedInners(expanded_cls, top, NFInstContext.RELAXED);

if Flags.isSet(Flags.EXEC_STAT) then
execStat("NFApi.frontEndLookup_dispatch("+ name +")");
Expand Down
4 changes: 4 additions & 0 deletions OMCompiler/Compiler/Util/Error.mo
Expand Up @@ -828,6 +828,10 @@ public constant ErrorTypes.Message TOO_MANY_TYPE_VARS_IN_CALL = ErrorTypes.MESSA
Gettext.gettext("Too many type variables given in call to ‘%s‘."));
public constant ErrorTypes.Message BREAK_OUTSIDE_LOOP = ErrorTypes.MESSAGE(378, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(),
Gettext.gettext("‘break' may only be used in a while- or for-loop."));
public constant ErrorTypes.Message TOP_LEVEL_OUTER = ErrorTypes.MESSAGE(379, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(),
Gettext.gettext("The model can't be instantiated due to top-level outer component ‘%s‘, it may only be used as part of a simulation model."));
public constant ErrorTypes.Message MISSING_INNER_NAME_CONFLICT = ErrorTypes.MESSAGE(380, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(),
Gettext.gettext("An inner declaration for outer component ‘%s‘ could not be found, and could not be automatically generated due to a existing declaration of that name."));

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
12 changes: 7 additions & 5 deletions testsuite/flattening/modelica/scodeinst/InnerOuterMissing1.mo
@@ -1,6 +1,6 @@
// name: InnerOuterMissing1
// keywords:
// status: correct
// status: incorrect
// cflags: -d=newInst
//

Expand All @@ -9,9 +9,11 @@ model InnerOuterMissing1
end InnerOuterMissing1;

// Result:
// class InnerOuterMissing1
// Real x;
// end InnerOuterMissing1;
// [flattening/modelica/scodeinst/InnerOuterMissing1.mo:8:3-8:15:writable] Warning: An inner declaration for outer component x could not be found and was automatically generated.
// Error processing file: InnerOuterMissing1.mo
// [flattening/modelica/scodeinst/InnerOuterMissing1.mo:8:3-8:15:writable] Error: The model can't be instantiated due to top-level outer component ‘x‘, it may only be used as part of a simulation model.
//
// # Error encountered! Exiting...
// # Please check the error message and the flags.
//
// Execution failed!
// endResult
Expand Up @@ -9,8 +9,12 @@ model A
annotation(missingInnerMessage = "Missing outer A");
end A;

model InnerOuterMissing2
model B
outer A a;
end B;

model InnerOuterMissing2
B b;
end InnerOuterMissing2;

// Result:
Expand Down
8 changes: 6 additions & 2 deletions testsuite/flattening/modelica/scodeinst/InnerOuterMissing5.mo
Expand Up @@ -8,14 +8,18 @@ model A
Real x = 1.0;
end A;

model InnerOuterMissing5
model B
outer model M = A;
M m;
end B;

model InnerOuterMissing5
B b;
end InnerOuterMissing5;

// Result:
// class InnerOuterMissing5
// Real m.x = 1.0;
// Real b.m.x = 1.0;
// end InnerOuterMissing5;
// [flattening/modelica/scodeinst/InnerOuterMissing5.mo:12:9-12:20:writable] Warning: An inner declaration for outer class M could not be found and was automatically generated.
//
Expand Down
Expand Up @@ -8,7 +8,11 @@ model A
outer Real x;
end A;

model InnerOuterMissing6 = A;
model B = A;

model InnerOuterMissing6
B b;
end InnerOuterMissing6;

// Result:
// class InnerOuterMissing6
Expand Down
25 changes: 25 additions & 0 deletions testsuite/flattening/modelica/scodeinst/InnerOuterMissing7.mo
@@ -0,0 +1,25 @@
// name: InnerOuterMissing7
// keywords:
// status: incorrect
// cflags: -d=newInst
//

model A
outer Real x;
end A;

model InnerOuterMissing7
A a;
Real x;
end InnerOuterMissing7;

// Result:
// Error processing file: InnerOuterMissing7.mo
// [flattening/modelica/scodeinst/InnerOuterMissing7.mo:13:3-13:9:writable] Notification: From here:
// [flattening/modelica/scodeinst/InnerOuterMissing7.mo:8:3-8:15:writable] Error: An inner declaration for outer component ‘x‘ could not be found, and could not be automatically generated due to a existing declaration of that name.
//
// # Error encountered! Exiting...
// # Please check the error message and the flags.
//
// Execution failed!
// endResult
1 change: 1 addition & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -630,6 +630,7 @@ InnerOuterMissing3.mo \
InnerOuterMissing4.mo \
InnerOuterMissing5.mo \
InnerOuterMissing6.mo \
InnerOuterMissing7.mo \
InnerOuterNotInner1.mo \
InStreamArray.mo \
InStreamFlowThreshold.mo \
Expand Down

0 comments on commit 782d8ca

Please sign in to comment.