Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit a1911e7

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Function evaluation improvements for records.
- Build a record expression from the child nodes if a record output doesn't have an explicit binding. - Evaluate expressions in function outputs and local variables too (currently in order of declaration, needs to be dependency sorted). - Added check that the outputs are assigned a value when evaluation a function (by adding Expression.EMPTY() and using it as the initial value if an output has no binding). - Always evaluate complex bindings on parameters, even if they aren't structural, since they need to be split into their component values. Belonging to [master]: - #2414 - OpenModelica/OpenModelica-testsuite#940
1 parent 60e8e0a commit a1911e7

File tree

5 files changed

+83
-9
lines changed

5 files changed

+83
-9
lines changed

Compiler/NFFrontEnd/NFBinding.mo

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ public
156156
binding.bindingExp := exp;
157157
then
158158
();
159+
160+
case FLAT_BINDING()
161+
algorithm
162+
binding.bindingExp := exp;
163+
then
164+
();
159165
end match;
160166
end setTypedExp;
161167

Compiler/NFFrontEnd/NFEvalFunction.mo

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import Binding = NFBinding;
4242
import NFComponent.Component;
4343
import Type = NFType;
4444
import Dimension = NFDimension;
45+
import NFClassTree.ClassTree;
4546

4647
protected
4748
import Ceval = NFCeval;
@@ -191,20 +192,54 @@ function addMutableReplacement
191192
protected
192193
Binding binding;
193194
Expression repl_exp;
195+
algorithm
196+
repl_exp := getBindingExp(node);
197+
repl_exp := Expression.map(repl_exp, function applyReplacements2(repl = repl));
198+
repl_exp := Expression.makeMutable(repl_exp);
199+
repl := ReplTree.add(repl, prefix + InstNode.name(node), repl_exp);
200+
end addMutableReplacement;
201+
202+
function getBindingExp
203+
input InstNode node;
204+
output Expression bindingExp;
205+
protected
206+
Binding binding;
194207
algorithm
195208
binding := Component.getBinding(InstNode.component(node));
196209

197-
// TODO: Handle records.
198210
if Binding.isBound(binding) then
199-
repl_exp := Binding.getExp(binding);
211+
bindingExp := Binding.getExp(binding);
200212
else
201-
// TODO: Replace with something more suitable, Expression.EMPTY?
202-
repl_exp := Expression.INTEGER(0);
213+
bindingExp := buildRecordBinding(node);
203214
end if;
215+
end getBindingExp;
204216

205-
repl_exp := Expression.makeMutable(repl_exp);
206-
repl := ReplTree.add(repl, prefix + InstNode.name(node), repl_exp);
207-
end addMutableReplacement;
217+
function buildRecordBinding
218+
input InstNode node;
219+
output Expression result;
220+
protected
221+
InstNode cls_node = InstNode.classScope(node);
222+
Class cls = InstNode.getClass(cls_node);
223+
array<InstNode> comps;
224+
list<Expression> bindings;
225+
Component comp;
226+
Expression exp;
227+
algorithm
228+
result := match cls
229+
case Class.INSTANCED_CLASS(elements = ClassTree.FLAT_TREE(components = comps))
230+
algorithm
231+
bindings := {};
232+
233+
for i in arrayLength(comps):-1:1 loop
234+
bindings := getBindingExp(comps[i]) :: bindings;
235+
end for;
236+
then
237+
Expression.RECORD(InstNode.scopePath(cls_node), cls.ty, bindings);
238+
239+
case Class.TYPED_DERIVED() then buildRecordBinding(cls.baseClass);
240+
else Expression.EMPTY();
241+
end match;
242+
end buildRecordBinding;
208243

209244
function addInputReplacement
210245
input InstNode node;
@@ -255,15 +290,19 @@ function createResult
255290
protected
256291
list<Expression> expl;
257292
list<Type> types;
293+
Expression e;
258294
algorithm
259295
if listLength(outputs) == 1 then
260296
exp := Expression.makeImmutable(ReplTree.get(repl, InstNode.name(listHead(outputs))));
297+
assertAssignedOutput(listHead(outputs), exp);
261298
else
262299
expl := {};
263300
types := {};
264301

265302
for o in outputs loop
266-
expl := Expression.makeImmutable(ReplTree.get(repl, InstNode.name(o))) :: expl;
303+
e := Expression.makeImmutable(ReplTree.get(repl, InstNode.name(o)));
304+
assertAssignedOutput(o, e);
305+
expl := e :: expl;
267306
end for;
268307

269308
expl := listReverseInPlace(expl);
@@ -272,6 +311,22 @@ algorithm
272311
end if;
273312
end createResult;
274313

314+
function assertAssignedOutput
315+
input InstNode outputNode;
316+
input Expression value;
317+
algorithm
318+
() := match value
319+
case Expression.EMPTY()
320+
algorithm
321+
Error.addSourceMessage(Error.UNASSIGNED_FUNCTION_OUTPUT,
322+
{InstNode.name(outputNode)}, InstNode.info(outputNode));
323+
then
324+
fail();
325+
326+
else ();
327+
end match;
328+
end assertAssignedOutput;
329+
275330
function evaluateStatements
276331
input list<Statement> stmts;
277332
output FlowControl ctrl = FlowControl.NEXT;

Compiler/NFFrontEnd/NFExpression.mo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ public
192192
Mutable<Expression> exp;
193193
end MUTABLE;
194194

195+
record EMPTY
196+
end EMPTY;
197+
195198
function isCref
196199
input Expression exp;
197200
output Boolean isTrue;
@@ -976,6 +979,7 @@ public
976979
case SUBSCRIPTED_EXP() then toString(exp.exp) + "[" + stringDelimitList(list(toString(e) for e in exp.subscripts), ", ") + "]";
977980
case TUPLE_ELEMENT() then toString(exp.tupleExp) + "[" + intString(exp.index) + "]";
978981
case MUTABLE() then toString(Mutable.access(exp.exp));
982+
case EMPTY() then "#EMPTY#";
979983

980984
else anyString(exp);
981985
end match;

Compiler/NFFrontEnd/NFFlatten.mo

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import NFPrefixes.Variability;
7979
import Variable = NFVariable;
8080
import BindingOrigin = NFBindingOrigin;
8181
import ElementSource;
82+
import Ceval = NFCeval;
8283

8384
public
8485
type FunctionTree = FunctionTreeImpl.Tree;
@@ -378,15 +379,21 @@ algorithm
378379

379380
// Create an equation if there's a binding on a complex component.
380381
if Binding.isBound(binding) then
382+
binding := flattenBinding(binding, prefix, node);
381383
binding_exp := Binding.getTypedExp(binding);
382384

385+
if Component.variability(comp) <= Variability.PARAMETER then
386+
binding_exp := Ceval.evalExp(binding_exp);
387+
end if;
388+
383389
if not Expression.isRecord(binding_exp) then
384390
eq := Equation.EQUALITY(Expression.CREF(ty, name), binding_exp, ty,
385391
ElementSource.createElementSource(InstNode.info(node)));
386392
sections := Sections.prependEquation(eq, sections);
387393
opt_binding := SOME(Binding.UNBOUND(NONE()));
388394
else
389-
opt_binding := SOME(flattenBinding(binding, prefix, node));
395+
binding := Binding.setTypedExp(binding_exp, binding);
396+
opt_binding := SOME(binding);
390397
end if;
391398
else
392399
opt_binding := NONE();

Compiler/Util/Error.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,8 @@ public constant Message TERMINATE_TRIGGERED = MESSAGE(333, TRANSLATION(), ERROR(
795795
Util.gettext("terminate triggered: %s"));
796796
public constant Message EVAL_RECURSION_LIMIT_REACHED = MESSAGE(334, TRANSLATION(), ERROR(),
797797
Util.gettext("The recursion limit (--evalRecursionLimit=%s) was exceeded during evaluation of %s."));
798+
public constant Message UNASSIGNED_FUNCTION_OUTPUT = MESSAGE(335, TRANSLATION(), ERROR(),
799+
Util.gettext("Output parameter %s was not assigned a value"));
798800
public constant Message INITIALIZATION_NOT_FULLY_SPECIFIED = MESSAGE(496, TRANSLATION(), WARNING(),
799801
Util.gettext("The initial conditions are not fully specified. %s."));
800802
public constant Message INITIALIZATION_OVER_SPECIFIED = MESSAGE(497, TRANSLATION(), WARNING(),

0 commit comments

Comments
 (0)