Skip to content

Commit

Permalink
Fix #7767 (#8046)
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
perost committed Oct 25, 2021
1 parent 6bba8a5 commit 7e091bb
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 31 deletions.
15 changes: 13 additions & 2 deletions OMCompiler/Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -72,6 +72,7 @@ import TypeCheck = NFTypeCheck;
import Typing = NFTyping;
import Util;
import InstContext = NFInstContext;
import ComplexType = NFComplexType;

import Call = NFCall;

Expand Down Expand Up @@ -2049,7 +2050,8 @@ protected
output list<tuple<InstNode, Expression>> outIters = {};
protected
Expression range;
InstNode iter;
InstNode iter, range_node;
Type ty;
algorithm
for i in inIters loop
if isSome(i.range) then
Expand All @@ -2060,7 +2062,16 @@ protected
range := Expression.EMPTY(Type.UNKNOWN());
end if;

(outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info);
// If the range is a cref, use it as the iterator type to allow lookup in
// the iterator.
ty := match range
case Expression.CREF(cref = ComponentRef.CREF(node = range_node))
guard InstNode.isComponent(range_node)
then Type.COMPLEX(Component.classInstance(InstNode.component(range_node)), ComplexType.CLASS());
else Type.UNKNOWN();
end match;

(outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info, ty);
outIters := (iter, range) :: outIters;
end for;

Expand Down
36 changes: 10 additions & 26 deletions OMCompiler/Compiler/NFFrontEnd/NFCeval.mo
Expand Up @@ -639,25 +639,21 @@ function makeComponentBinding
input EvalTarget target;
output Binding binding;
protected
ClassTree tree;
array<InstNode> comps;
list<Expression> fields;
Type ty, exp_ty;
Type ty;
InstNode rec_node;
Expression exp;
ComponentRef rest_cr;
algorithm
binding := matchcontinue (component, cref)
binding := matchcontinue component
// A record field without an explicit binding, evaluate the parent's binding
// if it has one and fetch the binding from it instead.
case (_, _)
case _
algorithm
exp := makeRecordFieldBindingFromParent(cref, target);
then
Binding.CEVAL_BINDING(exp);

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

// A record array component without an explicit binding, create one from its children.
case (Component.TYPED_COMPONENT(ty = ty as Type.ARRAY(elementType =
Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node)))), _)
case Component.TYPED_COMPONENT(ty = Type.ARRAY(elementType = ty as
Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node))))
algorithm
exp := makeRecordBindingExp(component.classInst, rec_node, component.ty, cref);
exp := splitRecordArrayExp(exp);
exp := Expression.mapCrefScalars(Expression.fromCref(cref),
function makeRecordBindingExp(typeNode = component.classInst,
recordNode = rec_node, recordType = ty));

binding := Binding.CEVAL_BINDING(exp);

if not ComponentRef.hasSubscripts(cref) then
Expand All @@ -696,7 +694,6 @@ protected
InstContext.Type exp_context;
Binding binding;
Component comp;
list<Subscript> subs;
algorithm
parent_cr := ComponentRef.rest(cref);
parent := ComponentRef.node(parent_cr);
Expand Down Expand Up @@ -732,7 +729,6 @@ protected
ClassTree tree;
array<InstNode> comps;
list<Expression> args;
list<Record.Field> fields;
Type ty;
InstNode c;
ComponentRef cr;
Expand All @@ -758,18 +754,6 @@ algorithm
exp := Expression.makeRecord(InstNode.scopePath(recordNode, includeRoot = true), recordType, args);
end makeRecordBindingExp;

function splitRecordArrayExp
input output Expression exp;
protected
Absyn.Path path;
Type ty;
list<Expression> expl;
algorithm
Expression.RECORD(path, ty, expl) := exp;
exp := Expression.makeRecord(path, Type.arrayElementType(ty), expl);
exp := Expression.fillType(ty, exp);
end splitRecordArrayExp;

function evalTypename
input Type ty;
input Expression originExp;
Expand Down
1 change: 1 addition & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFComponent.mo
Expand Up @@ -280,6 +280,7 @@ public
classInst := match component
case UNTYPED_COMPONENT() then component.classInst;
case TYPED_COMPONENT() then component.classInst;
case ITERATOR(ty = Type.COMPLEX(cls = classInst)) then classInst;
end match;
end classInstance;

Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFExpandExp.mo
Expand Up @@ -407,7 +407,7 @@ public
algorithm
for i in iterators loop
(node, range) := i;
iter := Mutable.create(Expression.INTEGER(0));
iter := Mutable.create(Expression.EMPTY(InstNode.getType(node)));
e := Expression.replaceIterator(e, node, Expression.MUTABLE(iter));
iters := iter :: iters;
(range, true) := expand(range);
Expand Down
80 changes: 78 additions & 2 deletions OMCompiler/Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -1444,6 +1444,7 @@ public
end makeSubscriptedExp;

function replaceIterator
"Replaces the given iterator with the given value in an expression."
input output Expression exp;
input InstNode iterator;
input Expression iteratorValue;
Expand All @@ -1452,17 +1453,44 @@ public
end replaceIterator;

function replaceIterator2
input output Expression exp;
input Expression exp;
input InstNode iterator;
input Expression iteratorValue;
output Expression outExp;
algorithm
exp := match exp
outExp := match exp
local
InstNode node;
ComponentRef cref;
list<String> fields;

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

// Cref is qualified identifier, i.x
case CREF(cref = ComponentRef.CREF())
algorithm
// Only the first (last in stored order) part of a cref can be an iterator.
node := ComponentRef.node(ComponentRef.last(exp.cref));

if InstNode.refEqual(iterator, node) then
// Start with the given value.
outExp := iteratorValue;

// Go down into the record fields using the rest of the cref.
fields := list(InstNode.name(n) for n in listRest(ComponentRef.nodes(exp.cref)));

for f in fields loop
outExp := recordElement(f, outExp);
end for;
else
outExp := exp;
end if;
then
outExp;

else exp;
end match;
end replaceIterator2;
Expand Down Expand Up @@ -4958,5 +4986,53 @@ public
end match;
end hasNonArrayIteratorSubscript;

function mapCrefScalars
"Takes a cref expression and applies a function to each scalar cref,
creating a new expression with the same dimensions as the given cref.
Ex: mapCrefScalars(/*Real[2, 2]*/ x, ComponentRef.toString) =>
{{'x[1, 1]', 'x[1, 2]'}, {'x[2, 1]', 'x[2, 2]'}}"
input Expression crefExp;
input MapFn mapFn;
output Expression outExp;

partial function MapFn
input ComponentRef cref;
output Expression exp;
end MapFn;
algorithm
outExp := ExpandExp.expand(crefExp);
outExp := mapCrefScalars2(outExp, mapFn);
end mapCrefScalars;

function mapCrefScalars2
input Expression exp;
input MapFn mapFn;
output Expression outExp;

partial function MapFn
input ComponentRef cref;
output Expression exp;
end MapFn;
protected
list<Expression> expl;
Type ty;
Boolean literal;
ComponentRef cref;
algorithm
outExp := match exp
case Expression.ARRAY()
guard not listEmpty(exp.elements)
algorithm
expl := list(mapCrefScalars2(e, mapFn) for e in exp.elements);
ty := typeOf(listHead(expl));
literal := List.all(expl, isLiteral);
then
makeExpArray(expl, ty, literal);

case Expression.CREF() then mapFn(exp.cref);
else exp;
end match;
end mapCrefScalars2;

annotation(__OpenModelica_Interface="frontend");
end NFExpression;
16 changes: 16 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo
Expand Up @@ -96,6 +96,7 @@ algorithm
case Expression.UNBOX() then Expression.UNBOX(simplify(exp.exp), exp.ty);
case Expression.SUBSCRIPTED_EXP() then simplifySubscriptedExp(exp);
case Expression.TUPLE_ELEMENT() then simplifyTupleElement(exp);
case Expression.RECORD_ELEMENT() then simplifyRecordElement(exp);
case Expression.BOX() then Expression.BOX(simplify(exp.exp));
case Expression.MUTABLE() then simplify(Mutable.access(exp.exp));
else exp;
Expand Down Expand Up @@ -920,5 +921,20 @@ algorithm
tupleExp := Expression.tupleElement(e, ty, index);
end simplifyTupleElement;

function simplifyRecordElement
input output Expression exp;
protected
Expression e, e2;
Integer idx;
Type ty;
algorithm
Expression.RECORD_ELEMENT(e, idx, _, ty) := exp;
e2 := simplify(e);

if not referenceEq(e, e2) then
exp := Expression.nthRecordElement(idx, e2);
end if;
end simplifyRecordElement;

annotation(__OpenModelica_Interface="frontend");
end NFSimplifyExp;
27 changes: 27 additions & 0 deletions testsuite/flattening/modelica/scodeinst/ArrayConstructorRecord1.mo
@@ -0,0 +1,27 @@
// name: ArrayConstructorRecord1
// keywords:
// status: correct
// cflags: -d=newInst
//

record R
Real x;
end R;

model ArrayConstructorRecord1
parameter R r[3](x = {1, 2, 3});
Real x[:] = {i.x for i in r};
end ArrayConstructorRecord1;

// Result:
// class ArrayConstructorRecord1
// parameter Real r[1].x = 1.0;
// parameter Real r[2].x = 2.0;
// parameter Real r[3].x = 3.0;
// Real x[1];
// Real x[2];
// Real x[3];
// equation
// x = {1.0, 2.0, 3.0};
// end ArrayConstructorRecord1;
// endResult
27 changes: 27 additions & 0 deletions testsuite/flattening/modelica/scodeinst/ArrayConstructorRecord2.mo
@@ -0,0 +1,27 @@
// name: ArrayConstructorRecord2
// keywords:
// status: correct
// cflags: -d=newInst
//

record R
Real x = 1;
end R;

model ArrayConstructorRecord2
parameter R r[3];
Real x[:] = {i.x for i in r};
end ArrayConstructorRecord2;

// Result:
// class ArrayConstructorRecord2
// parameter Real r[1].x = 1.0;
// parameter Real r[2].x = 1.0;
// parameter Real r[3].x = 1.0;
// Real x[1];
// Real x[2];
// Real x[3];
// equation
// x = {1.0, 1.0, 1.0};
// end ArrayConstructorRecord2;
// endResult
2 changes: 2 additions & 0 deletions testsuite/flattening/modelica/scodeinst/Makefile
Expand Up @@ -19,6 +19,8 @@ ArrayConnect1.mo \
ArrayConnect2.mo \
ArrayConnect3.mo \
ArrayConstructorComplex1.mo \
ArrayConstructorRecord1.mo \
ArrayConstructorRecord2.mo \
arrfunc.mo \
Assert1.mo \
Assert2.mo \
Expand Down

0 comments on commit 7e091bb

Please sign in to comment.