Skip to content

Commit 7e091bb

Browse files
authored
Fix #7767 (#8046)
- Fix lookup so that it works also on iterators of complex type. - Improve Expression.replaceIterator so it handles qualified iterator names. - Improve construction of record array bindings in Ceval, evaluate each element instead of evaluating only one and filling an array. - Add simplification of record element expressions, to make sure mutable expressions are simplified away properly.
1 parent 6bba8a5 commit 7e091bb

File tree

9 files changed

+175
-31
lines changed

9 files changed

+175
-31
lines changed

OMCompiler/Compiler/NFFrontEnd/NFCall.mo

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import TypeCheck = NFTypeCheck;
7272
import Typing = NFTyping;
7373
import Util;
7474
import InstContext = NFInstContext;
75+
import ComplexType = NFComplexType;
7576

7677
import Call = NFCall;
7778

@@ -2049,7 +2050,8 @@ protected
20492050
output list<tuple<InstNode, Expression>> outIters = {};
20502051
protected
20512052
Expression range;
2052-
InstNode iter;
2053+
InstNode iter, range_node;
2054+
Type ty;
20532055
algorithm
20542056
for i in inIters loop
20552057
if isSome(i.range) then
@@ -2060,7 +2062,16 @@ protected
20602062
range := Expression.EMPTY(Type.UNKNOWN());
20612063
end if;
20622064

2063-
(outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info);
2065+
// If the range is a cref, use it as the iterator type to allow lookup in
2066+
// the iterator.
2067+
ty := match range
2068+
case Expression.CREF(cref = ComponentRef.CREF(node = range_node))
2069+
guard InstNode.isComponent(range_node)
2070+
then Type.COMPLEX(Component.classInstance(InstNode.component(range_node)), ComplexType.CLASS());
2071+
else Type.UNKNOWN();
2072+
end match;
2073+
2074+
(outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info, ty);
20642075
outIters := (iter, range) :: outIters;
20652076
end for;
20662077

OMCompiler/Compiler/NFFrontEnd/NFCeval.mo

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -639,25 +639,21 @@ function makeComponentBinding
639639
input EvalTarget target;
640640
output Binding binding;
641641
protected
642-
ClassTree tree;
643-
array<InstNode> comps;
644-
list<Expression> fields;
645-
Type ty, exp_ty;
642+
Type ty;
646643
InstNode rec_node;
647644
Expression exp;
648-
ComponentRef rest_cr;
649645
algorithm
650-
binding := matchcontinue (component, cref)
646+
binding := matchcontinue component
651647
// A record field without an explicit binding, evaluate the parent's binding
652648
// if it has one and fetch the binding from it instead.
653-
case (_, _)
649+
case _
654650
algorithm
655651
exp := makeRecordFieldBindingFromParent(cref, target);
656652
then
657653
Binding.CEVAL_BINDING(exp);
658654

659655
// A record component without an explicit binding, create one from its children.
660-
case (Component.TYPED_COMPONENT(ty = Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node))), _)
656+
case Component.TYPED_COMPONENT(ty = Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node)))
661657
algorithm
662658
exp := makeRecordBindingExp(component.classInst, rec_node, component.ty, cref);
663659
binding := Binding.CEVAL_BINDING(exp);
@@ -669,11 +665,13 @@ algorithm
669665
binding;
670666

671667
// A record array component without an explicit binding, create one from its children.
672-
case (Component.TYPED_COMPONENT(ty = ty as Type.ARRAY(elementType =
673-
Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node)))), _)
668+
case Component.TYPED_COMPONENT(ty = Type.ARRAY(elementType = ty as
669+
Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node))))
674670
algorithm
675-
exp := makeRecordBindingExp(component.classInst, rec_node, component.ty, cref);
676-
exp := splitRecordArrayExp(exp);
671+
exp := Expression.mapCrefScalars(Expression.fromCref(cref),
672+
function makeRecordBindingExp(typeNode = component.classInst,
673+
recordNode = rec_node, recordType = ty));
674+
677675
binding := Binding.CEVAL_BINDING(exp);
678676

679677
if not ComponentRef.hasSubscripts(cref) then
@@ -696,7 +694,6 @@ protected
696694
InstContext.Type exp_context;
697695
Binding binding;
698696
Component comp;
699-
list<Subscript> subs;
700697
algorithm
701698
parent_cr := ComponentRef.rest(cref);
702699
parent := ComponentRef.node(parent_cr);
@@ -732,7 +729,6 @@ protected
732729
ClassTree tree;
733730
array<InstNode> comps;
734731
list<Expression> args;
735-
list<Record.Field> fields;
736732
Type ty;
737733
InstNode c;
738734
ComponentRef cr;
@@ -758,18 +754,6 @@ algorithm
758754
exp := Expression.makeRecord(InstNode.scopePath(recordNode, includeRoot = true), recordType, args);
759755
end makeRecordBindingExp;
760756

761-
function splitRecordArrayExp
762-
input output Expression exp;
763-
protected
764-
Absyn.Path path;
765-
Type ty;
766-
list<Expression> expl;
767-
algorithm
768-
Expression.RECORD(path, ty, expl) := exp;
769-
exp := Expression.makeRecord(path, Type.arrayElementType(ty), expl);
770-
exp := Expression.fillType(ty, exp);
771-
end splitRecordArrayExp;
772-
773757
function evalTypename
774758
input Type ty;
775759
input Expression originExp;

OMCompiler/Compiler/NFFrontEnd/NFComponent.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ public
280280
classInst := match component
281281
case UNTYPED_COMPONENT() then component.classInst;
282282
case TYPED_COMPONENT() then component.classInst;
283+
case ITERATOR(ty = Type.COMPLEX(cls = classInst)) then classInst;
283284
end match;
284285
end classInstance;
285286

OMCompiler/Compiler/NFFrontEnd/NFExpandExp.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ public
407407
algorithm
408408
for i in iterators loop
409409
(node, range) := i;
410-
iter := Mutable.create(Expression.INTEGER(0));
410+
iter := Mutable.create(Expression.EMPTY(InstNode.getType(node)));
411411
e := Expression.replaceIterator(e, node, Expression.MUTABLE(iter));
412412
iters := iter :: iters;
413413
(range, true) := expand(range);

OMCompiler/Compiler/NFFrontEnd/NFExpression.mo

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,7 @@ public
14441444
end makeSubscriptedExp;
14451445

14461446
function replaceIterator
1447+
"Replaces the given iterator with the given value in an expression."
14471448
input output Expression exp;
14481449
input InstNode iterator;
14491450
input Expression iteratorValue;
@@ -1452,17 +1453,44 @@ public
14521453
end replaceIterator;
14531454

14541455
function replaceIterator2
1455-
input output Expression exp;
1456+
input Expression exp;
14561457
input InstNode iterator;
14571458
input Expression iteratorValue;
1459+
output Expression outExp;
14581460
algorithm
1459-
exp := match exp
1461+
outExp := match exp
14601462
local
14611463
InstNode node;
1464+
ComponentRef cref;
1465+
list<String> fields;
14621466

1467+
// Cref is simple identifier, i
14631468
case CREF(cref = ComponentRef.CREF(node = node))
1469+
guard ComponentRef.isSimple(exp.cref)
14641470
then if InstNode.refEqual(iterator, node) then iteratorValue else exp;
14651471

1472+
// Cref is qualified identifier, i.x
1473+
case CREF(cref = ComponentRef.CREF())
1474+
algorithm
1475+
// Only the first (last in stored order) part of a cref can be an iterator.
1476+
node := ComponentRef.node(ComponentRef.last(exp.cref));
1477+
1478+
if InstNode.refEqual(iterator, node) then
1479+
// Start with the given value.
1480+
outExp := iteratorValue;
1481+
1482+
// Go down into the record fields using the rest of the cref.
1483+
fields := list(InstNode.name(n) for n in listRest(ComponentRef.nodes(exp.cref)));
1484+
1485+
for f in fields loop
1486+
outExp := recordElement(f, outExp);
1487+
end for;
1488+
else
1489+
outExp := exp;
1490+
end if;
1491+
then
1492+
outExp;
1493+
14661494
else exp;
14671495
end match;
14681496
end replaceIterator2;
@@ -4958,5 +4986,53 @@ public
49584986
end match;
49594987
end hasNonArrayIteratorSubscript;
49604988

4989+
function mapCrefScalars
4990+
"Takes a cref expression and applies a function to each scalar cref,
4991+
creating a new expression with the same dimensions as the given cref.
4992+
Ex: mapCrefScalars(/*Real[2, 2]*/ x, ComponentRef.toString) =>
4993+
{{'x[1, 1]', 'x[1, 2]'}, {'x[2, 1]', 'x[2, 2]'}}"
4994+
input Expression crefExp;
4995+
input MapFn mapFn;
4996+
output Expression outExp;
4997+
4998+
partial function MapFn
4999+
input ComponentRef cref;
5000+
output Expression exp;
5001+
end MapFn;
5002+
algorithm
5003+
outExp := ExpandExp.expand(crefExp);
5004+
outExp := mapCrefScalars2(outExp, mapFn);
5005+
end mapCrefScalars;
5006+
5007+
function mapCrefScalars2
5008+
input Expression exp;
5009+
input MapFn mapFn;
5010+
output Expression outExp;
5011+
5012+
partial function MapFn
5013+
input ComponentRef cref;
5014+
output Expression exp;
5015+
end MapFn;
5016+
protected
5017+
list<Expression> expl;
5018+
Type ty;
5019+
Boolean literal;
5020+
ComponentRef cref;
5021+
algorithm
5022+
outExp := match exp
5023+
case Expression.ARRAY()
5024+
guard not listEmpty(exp.elements)
5025+
algorithm
5026+
expl := list(mapCrefScalars2(e, mapFn) for e in exp.elements);
5027+
ty := typeOf(listHead(expl));
5028+
literal := List.all(expl, isLiteral);
5029+
then
5030+
makeExpArray(expl, ty, literal);
5031+
5032+
case Expression.CREF() then mapFn(exp.cref);
5033+
else exp;
5034+
end match;
5035+
end mapCrefScalars2;
5036+
49615037
annotation(__OpenModelica_Interface="frontend");
49625038
end NFExpression;

OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ algorithm
9696
case Expression.UNBOX() then Expression.UNBOX(simplify(exp.exp), exp.ty);
9797
case Expression.SUBSCRIPTED_EXP() then simplifySubscriptedExp(exp);
9898
case Expression.TUPLE_ELEMENT() then simplifyTupleElement(exp);
99+
case Expression.RECORD_ELEMENT() then simplifyRecordElement(exp);
99100
case Expression.BOX() then Expression.BOX(simplify(exp.exp));
100101
case Expression.MUTABLE() then simplify(Mutable.access(exp.exp));
101102
else exp;
@@ -920,5 +921,20 @@ algorithm
920921
tupleExp := Expression.tupleElement(e, ty, index);
921922
end simplifyTupleElement;
922923

924+
function simplifyRecordElement
925+
input output Expression exp;
926+
protected
927+
Expression e, e2;
928+
Integer idx;
929+
Type ty;
930+
algorithm
931+
Expression.RECORD_ELEMENT(e, idx, _, ty) := exp;
932+
e2 := simplify(e);
933+
934+
if not referenceEq(e, e2) then
935+
exp := Expression.nthRecordElement(idx, e2);
936+
end if;
937+
end simplifyRecordElement;
938+
923939
annotation(__OpenModelica_Interface="frontend");
924940
end NFSimplifyExp;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// name: ArrayConstructorRecord1
2+
// keywords:
3+
// status: correct
4+
// cflags: -d=newInst
5+
//
6+
7+
record R
8+
Real x;
9+
end R;
10+
11+
model ArrayConstructorRecord1
12+
parameter R r[3](x = {1, 2, 3});
13+
Real x[:] = {i.x for i in r};
14+
end ArrayConstructorRecord1;
15+
16+
// Result:
17+
// class ArrayConstructorRecord1
18+
// parameter Real r[1].x = 1.0;
19+
// parameter Real r[2].x = 2.0;
20+
// parameter Real r[3].x = 3.0;
21+
// Real x[1];
22+
// Real x[2];
23+
// Real x[3];
24+
// equation
25+
// x = {1.0, 2.0, 3.0};
26+
// end ArrayConstructorRecord1;
27+
// endResult
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// name: ArrayConstructorRecord2
2+
// keywords:
3+
// status: correct
4+
// cflags: -d=newInst
5+
//
6+
7+
record R
8+
Real x = 1;
9+
end R;
10+
11+
model ArrayConstructorRecord2
12+
parameter R r[3];
13+
Real x[:] = {i.x for i in r};
14+
end ArrayConstructorRecord2;
15+
16+
// Result:
17+
// class ArrayConstructorRecord2
18+
// parameter Real r[1].x = 1.0;
19+
// parameter Real r[2].x = 1.0;
20+
// parameter Real r[3].x = 1.0;
21+
// Real x[1];
22+
// Real x[2];
23+
// Real x[3];
24+
// equation
25+
// x = {1.0, 1.0, 1.0};
26+
// end ArrayConstructorRecord2;
27+
// endResult

testsuite/flattening/modelica/scodeinst/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ ArrayConnect1.mo \
1919
ArrayConnect2.mo \
2020
ArrayConnect3.mo \
2121
ArrayConstructorComplex1.mo \
22+
ArrayConstructorRecord1.mo \
23+
ArrayConstructorRecord2.mo \
2224
arrfunc.mo \
2325
Assert1.mo \
2426
Assert2.mo \

0 commit comments

Comments
 (0)