Skip to content

Commit

Permalink
[NF] Implement proper handling of subscripts.
Browse files Browse the repository at this point in the history
- Change typing of crefs so that subscripts aren't taken into account
  when typing each part, only for the whole cref expression.
- Implement/fix expansion of subscript slices.
- Fix type checking of array dimensions so that it actually gives an
  error message and fails on mismatched dimensions.

Belonging to [master]:
  - OpenModelica/OMCompiler#2160
  - OpenModelica/OpenModelica-testsuite#841
  • Loading branch information
perost authored and OpenModelica-Hudson committed Feb 5, 2018
1 parent 17ce08d commit 31c7f16
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 106 deletions.
121 changes: 55 additions & 66 deletions Compiler/NFFrontEnd/NFComponentRef.mo
Expand Up @@ -44,6 +44,7 @@ protected
import NFPrefixes.Variability;
import System;
import NFClass.Class;
import List;

import ComponentRef = NFComponentRef;

Expand All @@ -57,7 +58,7 @@ public
record CREF
InstNode node;
list<Subscript> subscripts;
Type ty;
Type ty "The type of the node, without taking subscripts into account.";
Origin origin;
ComponentRef restCref;
end CREF;
Expand Down Expand Up @@ -199,28 +200,47 @@ public
end match;
end append;

function getType
function getComponentType
"Returns the type of the component the given cref refers to, without taking
subscripts into account."
input ComponentRef cref;
output Type ty;
algorithm
ty := match cref
case CREF() then cref.ty;
else Type.UNKNOWN();
end match;
end getType;
end getComponentType;

function setType
input Type ty;
input output ComponentRef cref;
function getSubscriptedType
"Returns the type of a cref, with the subscripts taken into account."
input ComponentRef cref;
output Type ty;
algorithm
() := match cref
ty := match cref
case CREF()
then getSubscriptedType2(cref.restCref, Type.subscript(cref.ty, cref.subscripts));
case EMPTY() then Type.UNKNOWN();
case WILD() then Type.ANY();
end match;
end getSubscriptedType;

function getSubscriptedType2
input ComponentRef restCref;
input Type accumTy;
output Type ty;
algorithm
ty := match restCref
case CREF(origin = Origin.CREF)
algorithm
cref.ty := ty;
ty := Type.liftArrayLeftList(accumTy,
Type.arrayDims(Type.subscript(restCref.ty, restCref.subscripts)));
then
();
getSubscriptedType2(restCref.restCref, ty);

else accumTy;
end match;
end setType;
end getSubscriptedType2;

function getVariability
input ComponentRef cref;
Expand All @@ -243,12 +263,22 @@ public
end match;
end addSubscript;

function fillSubscripts
"This function takes a list of subscript lists and a cref, and adds the
first subscript list to the first part of the cref, the second list to the
second part, and so on. This function is meant to be used to fill in all
subscripts in a cref such that it becomes a scalar, so the type of each
cref part is set to the array element type for that part."
function setSubscripts
"Sets the subscripts of the first part of a cref."
input list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
() := match cref
case CREF()
algorithm
cref.subscripts := subscripts;
then
();
end match;
end setSubscripts;

function setSubscriptsList
"Sets the subscripts of each part of a cref to the corresponding list of subscripts."
input list<list<Subscript>> subscripts;
input output ComponentRef cref;
algorithm
Expand All @@ -260,37 +290,13 @@ public

case (subs :: rest_subs, CREF())
algorithm
rest_cref := fillSubscripts(rest_subs, cref.restCref);
rest_cref := setSubscriptsList(rest_subs, cref.restCref);
then
CREF(cref.node, listAppend(cref.subscripts, subs),
Type.arrayElementType(cref.ty), cref.origin, rest_cref);
CREF(cref.node, subs, Type.arrayElementType(cref.ty), cref.origin, rest_cref);

case ({}, _) then cref;
end match;
end fillSubscripts;

function setSubscripts
input list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
cref := match cref
case CREF()
then CREF(cref.node, subscripts, Type.arrayElementType(cref.ty), cref.origin, cref.restCref);
end match;
end setSubscripts;

function replaceSubscripts
input list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
() := match cref
case CREF()
algorithm
cref.subscripts := subscripts;
then
();
end match;
end replaceSubscripts;
end setSubscriptsList;

function subscriptsAll
"Returns all subscripts of a cref in reverse order.
Expand Down Expand Up @@ -322,6 +328,8 @@ public
end subscriptsN;

function transferSubscripts
"Copies subscripts from one cref to another, overwriting any subscripts on
the destination cref."
input ComponentRef srcCref;
input ComponentRef dstCref;
output ComponentRef cref;
Expand All @@ -341,7 +349,7 @@ public
algorithm
cref := transferSubscripts(srcCref.restCref, dstCref.restCref);
then
CREF(dstCref.node, srcCref.subscripts, srcCref.ty, dstCref.origin, cref);
CREF(dstCref.node, srcCref.subscripts, dstCref.ty, dstCref.origin, cref);

else
algorithm
Expand Down Expand Up @@ -497,34 +505,15 @@ public
crefs := match cref
local
list<Dimension> dims;
RangeIterator iter;
Expression exp;
list<list<Subscript>> subs;
list<list<Subscript>> new_subs;
Subscript sub;
ComponentRef scalar_cref;

case CREF()
algorithm
dims := Type.arrayDims(cref.ty);
subs := {cref.subscripts};

for dim in listReverse(dims) loop
iter := RangeIterator.fromDim(dim);
new_subs := {};

while RangeIterator.hasNext(iter) loop
(iter, exp) := RangeIterator.next(iter);
sub := Subscript.INDEX(exp);
new_subs := listAppend(list(sub :: s for s in subs), new_subs);
end while;

subs := new_subs;
end for;

scalar_cref := setType(Type.arrayElementType(cref.ty), cref);
subs := Subscript.expandList(cref.subscripts, dims);
subs := List.combination(subs);
then
listReverse(replaceSubscripts(s, scalar_cref) for s in subs);
list(setSubscripts(s, cref) for s in subs);

else {cref};
end match;
Expand Down
2 changes: 1 addition & 1 deletion Compiler/NFFrontEnd/NFConnectEquations.mo
Expand Up @@ -198,7 +198,7 @@ algorithm
source := ElementSource.mergeSources(lhsSource, rhsSource);
//source := ElementSource.addElementSourceConnect(source, (lhsCref, rhsCref));

ty := ComponentRef.getType(lhsCref);
ty := ComponentRef.getComponentType(lhsCref);
lhs_exp := Expression.fromCref(lhsCref);
rhs_exp := Expression.fromCref(rhsCref);

Expand Down
14 changes: 8 additions & 6 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -2081,13 +2081,15 @@ public
input output list<list<list<Subscript>>> subs = {};
protected
list<list<Subscript>> cr_subs = {};
list<Dimension> dims;

import NFComponentRef.Origin;
algorithm
subs := match cref
case ComponentRef.CREF()
case ComponentRef.CREF(origin = Origin.CREF)
algorithm
for dim in listReverse(Type.arrayDims(cref.ty)) loop
cr_subs := RangeIterator.map(RangeIterator.fromDim(dim), Subscript.makeIndex) :: cr_subs;
end for;
dims := Type.arrayDims(cref.ty);
cr_subs := Subscript.expandList(cref.subscripts, dims);
then
expandCref2(cref.restCref, cr_subs :: subs);

Expand All @@ -2103,7 +2105,7 @@ public
output Expression arrayExp;
algorithm
arrayExp := match subs
case {} then CREF(crefType, ComponentRef.fillSubscripts(accum, cref));
case {} then CREF(crefType, ComponentRef.setSubscriptsList(accum, cref));
else expandCref4(listHead(subs), {}, accum, listRest(subs), cref, crefType);
end match;
end expandCref3;
Expand Down Expand Up @@ -2555,7 +2557,7 @@ public
input ComponentRef cref;
output Expression exp;
algorithm
exp := Expression.CREF(ComponentRef.getType(cref), cref);
exp := Expression.CREF(ComponentRef.getSubscriptedType(cref), cref);
end fromCref;

function toCref
Expand Down
3 changes: 2 additions & 1 deletion Compiler/NFFrontEnd/NFScalarize.mo
Expand Up @@ -65,7 +65,8 @@ algorithm
end for;

for eq in flatModel.equations loop
eql := scalarizeEquation(eq, eql); end for;
eql := scalarizeEquation(eq, eql);
end for;

for eq in flatModel.initialEquations loop
ieql := scalarizeEquation(eq, ieql);
Expand Down
51 changes: 51 additions & 0 deletions Compiler/NFFrontEnd/NFSubscript.mo
Expand Up @@ -36,10 +36,13 @@ protected
import DAE;
import List;
import SimplifyExp = NFSimplifyExp;
import Type = NFType;
import RangeIterator = NFRangeIterator;

public
import Expression = NFExpression;
import Absyn;
import Dimension = NFDimension;

record RAW_SUBSCRIPT
Absyn.Subscript subscript;
Expand All @@ -65,6 +68,8 @@ public
algorithm
subscript := match exp
case Expression.INTEGER() then INDEX(exp);
case Expression.BOOLEAN() then INDEX(exp);
case Expression.ENUM_LITERAL() then INDEX(exp);
else UNTYPED(exp);
end match;
end fromExp;
Expand Down Expand Up @@ -265,5 +270,51 @@ public
end match;
end simplify;

function toDimension
"Returns a dimension representing the size of the given subscript."
input Subscript subscript;
output Dimension dimension;
algorithm
dimension := match subscript
case INDEX() then Dimension.INTEGER(1);
case SLICE() then listHead(Type.arrayDims(Expression.typeOf(subscript.slice)));
case WHOLE() then Dimension.UNKNOWN();
end match;
end toDimension;

function expand
input Subscript subscript;
input Dimension dimension;
output list<Subscript> subscripts;
algorithm
subscripts := match subscript
case INDEX() then {subscript};
case SLICE()
then list(INDEX(e) for e in Expression.arrayElements(Expression.expand(subscript.slice)));
case WHOLE()
then RangeIterator.map(RangeIterator.fromDim(dimension), makeIndex);
end match;
end expand;

function expandList
input list<Subscript> subscripts;
input list<Dimension> dimensions;
output list<list<Subscript>> outSubscripts = {};
protected
Dimension dim;
list<Dimension> rest_dims = dimensions;
algorithm
for s in subscripts loop
dim :: rest_dims := rest_dims;
outSubscripts := expand(s, dim) :: outSubscripts;
end for;

for d in rest_dims loop
outSubscripts := RangeIterator.map(RangeIterator.fromDim(d), makeIndex) :: outSubscripts;
end for;

outSubscripts := listReverse(outSubscripts);
end expandList;

annotation(__OpenModelica_Interface="frontend");
end NFSubscript;
26 changes: 23 additions & 3 deletions Compiler/NFFrontEnd/NFType.mo
Expand Up @@ -511,14 +511,34 @@ public
end toDAE;

function subscript
"Reduces a type's dimensions based on the given list of subscripts."
input output Type ty;
input list<Subscript> subs;
protected
Dimension dim;
list<Dimension> dims, subbed_dims = {};
algorithm
if listEmpty(subs) then
return;
end if;

dims := arrayDims(ty);

for sub in subs loop
if Subscript.isIndex(sub) then
ty := unliftArray(ty);
end if;
dim :: dims := dims;

subbed_dims := match sub
case Subscript.INDEX() then subbed_dims;
case Subscript.SLICE() then Subscript.toDimension(sub) :: subbed_dims;
case Subscript.WHOLE() then dim :: subbed_dims;
end match;
end for;

ty := arrayElementType(ty);

if not (listEmpty(subbed_dims) and listEmpty(dims)) then
ty := ARRAY(ty, listAppend(listReverse(subbed_dims), dims));
end if;
end subscript;

function isEqual
Expand Down

0 comments on commit 31c7f16

Please sign in to comment.