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

Commit

Permalink
[NF] Add support for array concatenation
Browse files Browse the repository at this point in the history
- [NF] `cat(k, A, ..., C)` now works
- [NF] `[A,B ; C,D]` is now implemented
- simplify of cat now handles more cases (also for the old frontend)

Previously, support for `cat` did not exist in the new frontend and
`[A,B ; C,D]` pretended it was the array constructor.

This fixes ticket:4778.

Belonging to [master]:
  - #2240
  - OpenModelica/OpenModelica-testsuite#863
  • Loading branch information
sjoelund authored and OpenModelica-Hudson committed Feb 27, 2018
1 parent 878318e commit 6c9726f
Show file tree
Hide file tree
Showing 15 changed files with 492 additions and 18 deletions.
14 changes: 10 additions & 4 deletions Compiler/FrontEnd/Ceval.mo
Expand Up @@ -1819,12 +1819,13 @@ algorithm
Boolean impl;
Absyn.Msg msg;
FCore.Cache cache;
list<Integer> dims;

case (cache,env,{arr,dim},impl,msg,_)
equation
(cache,arr_val) = ceval(cache,env, arr, impl, msg,numIter+1);
(cache,arr_val as Values.ARRAY(dimLst=dims)) = ceval(cache,env, arr, impl, msg,numIter+1);
(cache,Values.INTEGER(dim_val)) = ceval(cache,env, dim, impl, msg,numIter+1);
res = cevalBuiltinPromote2(arr_val, dim_val);
res = cevalBuiltinPromote2(arr_val, dim_val - listLength(dims));
then
(cache,res);
end match;
Expand All @@ -1847,8 +1848,13 @@ algorithm
equation
n_1 = n - 1;
(vs_1 as (Values.ARRAY(dimLst = il)::_)) = List.map1(vs, cevalBuiltinPromote2, n_1);
then
Values.ARRAY(vs_1,i::il);
then Values.ARRAY(vs_1,i::il);
case (v,n)
equation
failure(Values.ARRAY() = v);
n_1 = n - 1;
(v as Values.ARRAY(dimLst = il)) = cevalBuiltinPromote2(v, n_1);
then Values.ARRAY({v},1::il);
else
equation
true = Flags.isSet(Flags.FAILTRACE);
Expand Down
2 changes: 1 addition & 1 deletion Compiler/FrontEnd/Expression.mo
Expand Up @@ -10778,7 +10778,7 @@ algorithm

// Use the constructed types to promote the expression.
is_array_ty = Types.isArray(inType);
exp = promoteExp2(inExp, is_array_ty, dims_to_add, tys);
exp = promoteExp2(inExp, is_array_ty, inDims, tys);
then
(exp, res_ty);

Expand Down
113 changes: 111 additions & 2 deletions Compiler/FrontEnd/ExpressionSimplify.mo
Expand Up @@ -1373,12 +1373,21 @@ algorithm
case DAE.CALL(path=Absyn.IDENT("cat"),expLst=DAE.ICONST(i)::es,attr=DAE.CALL_ATTR(ty=tp))
equation
es = simplifyCat(i,es);
i = listLength(es);
e = Expression.makePureBuiltinCall("cat",DAE.ICONST(i)::es,tp);
then e;

case DAE.CALL(path=Absyn.IDENT("cat"),expLst=DAE.ICONST(i)::es,attr=DAE.CALL_ATTR(ty=tp))
algorithm
e := evalCat(i,es);
then e;

// promote n-dim to n-dim
case DAE.CALL(path=Absyn.IDENT("promote"),expLst=e1::DAE.ICONST(i)::{})
guard Types.numberOfDimensions(Expression.typeof(e1))==i
then e1;

// promote 1-dim to 2-dim
case DAE.CALL(path=Absyn.IDENT("promote"),expLst=(DAE.ARRAY(tp1 as DAE.T_ARRAY(dims={_}),sc,es))::DAE.ICONST(1)::{})
case DAE.CALL(path=Absyn.IDENT("promote"),expLst=(DAE.ARRAY(tp1 as DAE.T_ARRAY(dims={_}),sc,es))::DAE.ICONST(2)::{})
equation
tp = Types.liftArray(Types.unliftArray(tp1), DAE.DIM_INTEGER(1));
es = List.map2(List.map(es,List.create), Expression.makeArray, tp, sc);
Expand All @@ -1387,6 +1396,18 @@ algorithm
then
DAE.ARRAY(tp,false,es);

// scalar to n-dim
case DAE.CALL(path=Absyn.IDENT("promote"),expLst=e1::DAE.ICONST(i)::{})
guard not Types.isArray(Expression.typeof(e1))
algorithm
tp := Expression.typeof(e1);
for j in 1:i loop
tp1 := Types.liftArray(tp, DAE.DIM_INTEGER(1));
e1 := Expression.makeArray({e1}, tp1, not Types.isArray(tp));
tp := tp1;
end for;
then e1;

case DAE.CALL(path=Absyn.IDENT("transpose"),expLst=e::{},attr=DAE.CALL_ATTR())
equation
(e, true) = Expression.transposeArray(e);
Expand Down Expand Up @@ -1583,6 +1604,94 @@ algorithm
end matchcontinue;
end simplifyCat2;

protected function evalCat
input Integer dim;
input list<DAE.Exp> exps;
output DAE.Exp outExp;
protected
list<DAE.Exp> arr;
list<list<DAE.Exp>> arrs={};
list<Integer> dims, firstDims={}, lastDims, reverseDims;
list<list<Integer>> dimsLst={};
DAE.Type tp;
Integer j, k, l, thisDim, lastDim;
array<DAE.Exp> expArr;
algorithm
true := dim >= 1;
false := listEmpty(exps);
if 1 == dim then
arr := listAppend(Expression.getArrayOrMatrixContents(e) for e in exps);
tp := Expression.typeof(listHead(arr));
outExp := Expression.makeArray(arr, tp, not Types.isArray(tp));
return;
end if;
for e in listReverse(exps) loop
// Here we get a linear representation of all expressions in the array
// and the dimensions necessary to build up the array again
(arr,dims) := evalCatGetFlatArray(e,dim);
arrs := arr::arrs;
dimsLst := dims::dimsLst;
end for;
for i in 1:(dim-1) loop
j := min(listHead(d) for d in dimsLst);
Error.assertion(j == max(listHead(d) for d in dimsLst), getInstanceName() + ": cat got uneven dimensions for dim=" + String(i) + " " + ExpressionDump.printExpStr(DAE.LIST(exps)), sourceInfo());
firstDims := j :: firstDims;
dimsLst := list(listRest(d) for d in dimsLst);
end for;
reverseDims := firstDims;
firstDims := listReverse(firstDims);
lastDims := list(listHead(d) for d in dimsLst);
lastDim := sum(d for d in lastDims);
reverseDims := lastDim::reverseDims;
// Fill in the elements of the new array in the new order; this uses
// an array structure for random access
expArr := arrayCreate(lastDim*product(d for d in firstDims), listHead(listHead(arrs)));
k := 1;
for exps in arrs loop
thisDim :: lastDims := lastDims;
l := 0;
for e in exps loop
arrayUpdate(expArr, k+mod(l, thisDim)+(lastDim*div(l, thisDim)), e);
l := l+1;
end for;
k := k + thisDim;
end for;
// Convert the flat array structure to a tree array structure with the
// correct dimensions
arr := arrayList(expArr);
outExp := Expression.listToArray(arr, listReverse(DAE.DIM_INTEGER(d) for d in reverseDims));
end evalCat;

protected function evalCatGetFlatArray
input DAE.Exp e;
input Integer dim;
output list<DAE.Exp> outExps={};
output list<Integer> outDims={};
protected
list<DAE.Exp> arr;
list<Integer> dims;
DAE.Type tp;
Integer i;
algorithm
if dim == 1 then
outExps := Expression.getArrayOrMatrixContents(e);
outDims := {listLength(outExps)};
return;
end if;
i := 0;
for exp in listReverse(Expression.getArrayOrMatrixContents(e)) loop
(arr, dims) := evalCatGetFlatArray(exp, dim-1);
if listEmpty(outDims) then
outDims := dims;
else
Error.assertion(valueEq(dims, outDims), getInstanceName() + ": Got unbalanced array from " + ExpressionDump.printExpStr(e), sourceInfo());
end if;
outExps := listAppend(arr, outExps);
i := i+1;
end for;
outDims := i :: outDims;
end evalCatGetFlatArray;

protected function simplifyBuiltinStringFormat
input DAE.Exp exp;
input DAE.Exp len_exp;
Expand Down
7 changes: 5 additions & 2 deletions Compiler/FrontEnd/Static.mo
Expand Up @@ -2823,7 +2823,7 @@ protected
DAE.Properties prop;
list<DAE.Properties> rest_props;
DAE.Type ty, sty;
DAE.Dimension dim2;
DAE.Dimension dim1, dim2;
algorithm
try
exp :: rest_expl := inExpl;
Expand All @@ -2839,7 +2839,10 @@ algorithm

(exp, prop as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims);
accum_expl := exp :: accum_expl;
_ :: dim2 :: _ := Types.getDimensions(ty);
dim1 :: dim2 :: _ := Types.getDimensions(ty);
if not Expression.dimensionsEqual(dim1, outDim1) then
Error.addSourceMessageAndFail(Error.COMMA_OPERATOR_DIFFERENT_SIZES, {ExpressionDump.printExpStr(listHead(inExpl)), ExpressionDump.dimensionString(outDim1), ExpressionDump.printExpStr(exp), ExpressionDump.dimensionString(dim1)}, inInfo);
end if;
// Comma between matrices => concatenation along second dimension.
outDim2 := Expression.dimensionsAdd(dim2, outDim2);
outProperties := Types.matchWithPromote(prop, outProperties, inHaveReal);
Expand Down
8 changes: 8 additions & 0 deletions Compiler/NFFrontEnd/NFBuiltinFuncs.mo
Expand Up @@ -161,5 +161,13 @@ constant Function IN_STREAM = Function.FUNCTION(Path.IDENT("inStream"),
InstNode.EMPTY_NODE(), {REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));

constant Function PROMOTE = Function.FUNCTION(Path.IDENT("promote"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));

constant Function CAT = Function.FUNCTION(Path.IDENT("cat"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));

annotation(__OpenModelica_Interface="frontend");
end NFBuiltinFuncs;

0 comments on commit 6c9726f

Please sign in to comment.