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

Commit

Permalink
[NF] Improve subscripting of expressions.
Browse files Browse the repository at this point in the history
- Handle typenames, ranges and reductions in
  Expression.applySubscriptIndex.
- Use Expression.applySubscriptIndex in Expression.expandGeneric,
  instead of just creating a subscripted expression.
- Fixed mistake in typing of Boolean ranges that resulted in them
  always getting a size of 1.
- Added case to Typing.typeIterator for when the iterator has already
  been typed (which can happen e.g. if the iterator is needed to
  determine the size of a dimension).

Belonging to [master]:
  - #2392
  - OpenModelica/OpenModelica-testsuite#931
  • Loading branch information
perost authored and OpenModelica-Hudson committed Apr 24, 2018
1 parent c51b823 commit 549896e
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 70 deletions.
180 changes: 141 additions & 39 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -53,6 +53,8 @@ public
import Type = NFType;
import ComponentRef = NFComponentRef;
import NFCall.Call;
import Binding = NFBinding;
import NFComponent.Component;

record INTEGER
Integer value;
Expand Down Expand Up @@ -612,60 +614,152 @@ public
input Expression indexExp;
input output Expression exp;
protected
Integer index;
Boolean is_scalar_const;
Expression texp;
Type exp_ty;
ComponentRef cref;
algorithm
is_scalar_const := Expression.isScalarConst(indexExp);
is_scalar_const := isScalarConst(indexExp);

// check exp has array type. Don't apply subs to scalar exp.
exp_ty := typeOf(exp);
if not Type.isArray(exp_ty) then
Error.assertion(false, getInstanceName() + ": Application of subs on non-array expressoin not allowed. "
+ "Exp: " + toString(exp)
+ ", Exp type: " + Type.toString(exp_ty)
+ ", Sub: " + toString(indexExp)
, sourceInfo());
Error.assertion(false, getInstanceName() + ": Application of subs on non-array expression not allowed. " +
"Exp: " + toString(exp) + ", Exp type: " + Type.toString(exp_ty) + ", Sub: " + toString(indexExp), sourceInfo());
fail();
end if;

exp := match exp
local
ComponentRef cref;

case CREF() algorithm
cref := ComponentRef.addSubscript(Subscript.INDEX(indexExp), exp.cref);
texp := CREF(Type.unliftArray(exp.ty), cref);
then texp;

// We should probably try to evaluate all SUBSCRIPTED_EXP at some point before BackEnd.
// It causes all kinds of trouble in code generation. (like the old FrontEnd ASUB() )
// Probably at flatten.
case ARRAY() algorithm
// Do we want to create SUBSCRIPTED_EXP and go through the ASUB hell of the old FrontEnd?
// k = {1,i,2}[j];
if is_scalar_const then
index := Expression.toInteger(indexExp);
texp := listGet(exp.elements, index);
else
texp := SUBSCRIPTED_EXP(exp, {indexExp}, Type.unliftArray(exp.ty));
// Error.assertion(false, getInstanceName() + " failed on " + Subscript.toString(sub), sourceInfo());
// fail();
end if;
then texp;

case SUBSCRIPTED_EXP() algorithm
texp := SUBSCRIPTED_EXP(exp.exp, listAppend(exp.subscripts,{indexExp}), Type.unliftArray(exp.ty));
then texp;

else algorithm
texp := SUBSCRIPTED_EXP(exp, {indexExp}, Type.unliftArray(exp_ty));
then texp;
case CREF()
algorithm
cref := ComponentRef.addSubscript(Subscript.INDEX(indexExp), exp.cref);
then
CREF(Type.unliftArray(exp.ty), cref);

case TYPENAME() guard is_scalar_const
then applyIndexSubscriptTypename(exp.ty, toInteger(indexExp));

case ARRAY()
algorithm
if is_scalar_const then
texp := listGet(exp.elements, toInteger(indexExp));
else
texp := SUBSCRIPTED_EXP(exp, {indexExp}, Type.unliftArray(exp.ty));
end if;
then
texp;

case RANGE() guard is_scalar_const
then applyIndexSubscriptRange(exp.start, exp.step, exp.stop, toInteger(indexExp));

case CALL(call = Call.TYPED_MAP_CALL())
then applyIndexSubscriptReduction(exp.call, indexExp);

case SUBSCRIPTED_EXP()
then SUBSCRIPTED_EXP(exp.exp, listAppend(exp.subscripts,{indexExp}), Type.unliftArray(exp.ty));

else SUBSCRIPTED_EXP(exp, {indexExp}, Type.unliftArray(exp_ty));
end match;
end applyIndexSubscript;

function applyIndexSubscriptTypename
input Type ty;
input Integer index;
output Expression subscriptedExp;
algorithm
subscriptedExp := match ty
case Type.BOOLEAN() guard index <= 2
then if index == 1 then Expression.BOOLEAN(false) else Expression.BOOLEAN(true);

case Type.ENUMERATION()
then Expression.ENUM_LITERAL(ty, Type.nthEnumLiteral(ty, index), index);
end match;
end applyIndexSubscriptTypename;

function applyIndexSubscriptRange
input Expression startExp;
input Option<Expression> stepExp;
input Expression stopExp;
input Integer index;
output Expression subscriptedExp;
protected
Integer iidx;
Real ridx;
algorithm
subscriptedExp := match (startExp, stepExp)
case (Expression.INTEGER(), SOME(Expression.INTEGER(iidx)))
then Expression.INTEGER(startExp.value + index * iidx - 1);

case (Expression.INTEGER(), _)
then Expression.INTEGER(startExp.value + index - 1);

case (Expression.REAL(), SOME(Expression.REAL(ridx)))
then Expression.REAL(startExp.value + index * ridx - 1);

case (Expression.REAL(), _)
then Expression.REAL(startExp.value + index - 1.0);

case (Expression.BOOLEAN(), _)
then if index == 1 then startExp else stopExp;

case (Expression.ENUM_LITERAL(index = iidx), _)
algorithm
iidx := iidx + index - 1;
then
ENUM_LITERAL(startExp.ty, Type.nthEnumLiteral(startExp.ty, iidx), iidx);

end match;
end applyIndexSubscriptRange;

function applyIndexSubscriptReduction
input Call call;
input Expression indexExp;
output Expression subscriptedExp;
protected
Type ty;
Variability var;
Expression exp, iter_exp;
list<InstNode> iters;
InstNode iter;
algorithm
Call.TYPED_MAP_CALL(ty, var, exp, iters) := call;
iter :: iters := iters;
iter_exp := Binding.getTypedExp(Component.getBinding(InstNode.component(iter)));
iter_exp := applyIndexSubscript(indexExp, iter_exp);
subscriptedExp := replaceIterator(exp, InstNode.name(iter), iter_exp);

if not listEmpty(iters) then
subscriptedExp := CALL(Call.TYPED_MAP_CALL(Type.unliftArray(ty), var, subscriptedExp, iters));
end if;
end applyIndexSubscriptReduction;

function replaceIterator
input output Expression exp;
input String iteratorName;
input Expression iteratorValue;
algorithm
exp := map(exp, function replaceIterator2(iteratorName = iteratorName, iteratorValue = iteratorValue));
end replaceIterator;

function replaceIterator2
input output Expression exp;
input String iteratorName;
input Expression iteratorValue;

import Origin = NFComponentRef.Origin;
algorithm
exp := match exp
local
String name;

case CREF(cref = ComponentRef.CREF(
node = InstNode.COMPONENT_NODE(name = name), origin = Origin.ITERATOR))
then if name == iteratorName then iteratorValue else exp;

else exp;
end match;
end replaceIterator2;

function applySliceSubscript
input Expression slice;
input Expression exp;
Expand Down Expand Up @@ -2557,7 +2651,15 @@ public
then
ARRAY(ty, expl);

case {} then SUBSCRIPTED_EXP(exp, listReverse(accum), ty);
case {}
algorithm
outExp := exp;
for s in listReverse(accum) loop
outExp := applyIndexSubscript(s, outExp);
end for;
then
outExp;

end match;
end expandGeneric2;

Expand Down
30 changes: 1 addition & 29 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -658,39 +658,11 @@ algorithm
while RangeIterator.hasNext(range_iter) loop
(range_iter, val) := RangeIterator.next(range_iter);
unrolled_body := list(Equation.mapExp(eq,
function replaceForIterator(iteratorName = iter_name, iteratorValue = val)) for eq in body);
function Expression.replaceIterator(iteratorName = iter_name, iteratorValue = val)) for eq in body);
equations := listAppend(unrolled_body, equations);
end while;
end unrollForLoop;

function replaceForIterator
input output Expression exp;
input String iteratorName;
input Expression iteratorValue;
algorithm
exp := Expression.map(exp,
function replaceForIterator2(iteratorName = iteratorName, iteratorValue = iteratorValue));
end replaceForIterator;

function replaceForIterator2
input output Expression exp;
input String iteratorName;
input Expression iteratorValue;

import Origin = NFComponentRef.Origin;
algorithm
exp := match exp
local
String name;

case Expression.CREF(cref = ComponentRef.CREF(
node = InstNode.COMPONENT_NODE(name = name), origin = Origin.ITERATOR))
then if name == iteratorName then iteratorValue else exp;

else exp;
end match;
end replaceForIterator2;

function flattenAlgorithms
input output list<list<Statement>> algorithms;
input ComponentRef prefix;
Expand Down
11 changes: 11 additions & 0 deletions Compiler/NFFrontEnd/NFType.mo
Expand Up @@ -485,6 +485,17 @@ public
end match;
end dimensionCount;

function nthEnumLiteral
input Type ty;
input Integer index;
output String literal;
protected
list<String> literals;
algorithm
ENUMERATION(literals = literals) := ty;
literal := listGet(literals, index);
end nthEnumLiteral;

function toString
input Type ty;
output String str;
Expand Down
4 changes: 2 additions & 2 deletions Compiler/NFFrontEnd/NFTypeCheck.mo
Expand Up @@ -2034,8 +2034,8 @@ algorithm

case (Expression.BOOLEAN(), Expression.BOOLEAN())
algorithm
sz := if startExp.value == startExp.value then 1
elseif startExp.value < startExp.value then 2
sz := if startExp.value == stopExp.value then 1
elseif startExp.value < stopExp.value then 2
else 0;
then
Dimension.fromInteger(sz);
Expand Down
3 changes: 3 additions & 0 deletions Compiler/NFFrontEnd/NFTyping.mo
Expand Up @@ -439,6 +439,9 @@ algorithm
then
();

case Component.ITERATOR(binding = Binding.TYPED_BINDING())
then ();

case Component.ITERATOR(binding = Binding.UNBOUND())
algorithm
Error.assertion(false, getInstanceName() + ": Implicit iteration ranges not yet implement", sourceInfo());
Expand Down

0 comments on commit 549896e

Please sign in to comment.