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

Commit 2fe6fb8

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Improved handling of function parameter dims.
- Allow function parameter dimensions to be unknown or continuous. - Improved typing of size when size can't be evaluated. - Fixed type of min/max of array. Belonging to [master]: - #2028 - OpenModelica/OpenModelica-testsuite#784
1 parent 6136400 commit 2fe6fb8

File tree

5 files changed

+92
-64
lines changed

5 files changed

+92
-64
lines changed

Compiler/NFFrontEnd/NFCall.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ uniontype Call
570570
if nArgs == 1 then
571571
{(e,ty,variability)} := tyArgs;
572572
es := {e};
573+
ty := Type.arrayElementType(ty);
573574
else
574575
{(e1,ty1,variability1),(e2,ty2,variability2)} := tyArgs;
575576
es := {e1,e2};

Compiler/NFFrontEnd/NFCeval.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ algorithm
138138
algorithm
139139
dim := listGet(Type.arrayDims(Expression.typeOf(exp.exp)), Expression.toInteger(evalExp(exp1, target)));
140140
then
141-
Expression.INTEGER(Dimension.size(dim));
141+
if Dimension.isKnown(dim) then Expression.INTEGER(Dimension.size(dim)) else exp;
142142

143143
case Expression.SIZE()
144144
algorithm

Compiler/NFFrontEnd/NFSimplifyExp.mo

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ algorithm
9999
then
100100
Expression.CALL(call);
101101

102-
case Expression.SIZE()
103-
algorithm
104-
assert(false, "Unimplemented case for " + Expression.toString(exp) + " in " + getInstanceName());
105-
then fail();
106-
107102
case Expression.BINARY()
108103
algorithm
109104
exp1 := simplifyExp(exp.exp1);
@@ -181,11 +176,6 @@ algorithm
181176
assert(false, "Unimplemented case for " + Expression.toString(exp) + " in " + getInstanceName());
182177
then fail();
183178

184-
case Expression.SIZE()
185-
algorithm
186-
assert(false, "Unimplemented case for " + Expression.toString(exp) + " in " + getInstanceName());
187-
then fail();
188-
189179
case Expression.BINARY(exp1=Expression.INTEGER(value=i1), exp2=Expression.INTEGER(value=i2))
190180
then match exp.operator
191181
case Operator.ADD() then Expression.INTEGER(i1 + i2);

Compiler/NFFrontEnd/NFTypeCheck.mo

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,7 +2435,7 @@ algorithm
24352435
end for;
24362436
end if;
24372437

2438-
(exp, ty, ty_match) := matchTypes(binding.bindingType, comp_ty, binding.bindingExp);
2438+
(exp, ty, ty_match) := matchTypes(binding.bindingType, comp_ty, binding.bindingExp, true);
24392439

24402440
if not isCompatibleMatch(ty_match) then
24412441
Error.addSourceMessage(Error.VARIABLE_BINDING_TYPE_MISMATCH,
@@ -2458,12 +2458,11 @@ algorithm
24582458
end match;
24592459
end matchBinding;
24602460

2461-
function checkDimension
2462-
"Checks that an expression used as a dimension is a parameter expression and
2463-
has a valid type for a dimension, otherwise prints an error and fails."
2461+
function checkDimensionType
2462+
"Checks that an expression used as a dimension has a valid type for a
2463+
dimension, otherwise prints an error and fails."
24642464
input Expression exp;
24652465
input Type ty;
2466-
input Variability var;
24672466
input SourceInfo info;
24682467
algorithm
24692468
if not Type.isInteger(ty) then
@@ -2478,13 +2477,7 @@ algorithm
24782477
fail();
24792478
end match;
24802479
end if;
2481-
2482-
if var > Variability.PARAMETER then
2483-
Error.addSourceMessage(Error.DIMENSION_NOT_KNOWN,
2484-
{Expression.toString(exp)}, info);
2485-
fail();
2486-
end if;
2487-
end checkDimension;
2480+
end checkDimensionType;
24882481

24892482
annotation(__OpenModelica_Interface="frontend");
24902483
end NFTypeCheck;

Compiler/NFFrontEnd/NFTyping.mo

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,14 @@ uniontype TypingError
100100
end TypingError;
101101

102102
type EquationScope = enumeration(NORMAL, INITIAL, IF, IF_PARAMETER);
103+
type ClassScope = enumeration(CLASS, FUNCTION);
103104

104105
public
105106
function typeClass
106107
input InstNode cls;
107108
input String name;
108109
algorithm
109-
typeComponents(cls);
110+
typeComponents(cls, ClassScope.CLASS);
110111
execStat("NFTyping.typeComponents(" + name + ")");
111112
typeBindings(cls, cls);
112113
execStat("NFTyping.typeBindings(" + name + ")");
@@ -117,13 +118,14 @@ end typeClass;
117118
function typeFunction
118119
input InstNode cls;
119120
algorithm
120-
typeComponents(cls);
121+
typeComponents(cls, ClassScope.FUNCTION);
121122
typeBindings(cls, cls);
122123
typeSections(cls);
123124
end typeFunction;
124125

125126
function typeComponents
126127
input InstNode cls;
128+
input ClassScope clsScope;
127129
protected
128130
Class c = InstNode.getClass(cls), c2;
129131
ClassTree cls_tree;
@@ -133,7 +135,7 @@ algorithm
133135
case Class.INSTANCED_CLASS(elements = cls_tree as ClassTree.FLAT_TREE())
134136
algorithm
135137
for c in cls_tree.components loop
136-
typeComponent(c);
138+
typeComponent(c, clsScope);
137139
end for;
138140
then
139141
();
@@ -147,7 +149,7 @@ algorithm
147149
// But keep the restriction.
148150
c2 := Class.setRestriction(c.restriction, c2);
149151
InstNode.updateClass(c2, cls);
150-
typeComponents(cls);
152+
typeComponents(cls, clsScope);
151153
then
152154
();
153155

@@ -204,6 +206,7 @@ end makeConnectorType;
204206

205207
function typeComponent
206208
input InstNode component;
209+
input ClassScope clsScope;
207210
output Type ty;
208211
protected
209212
InstNode node = InstNode.resolveOuter(component);
@@ -214,7 +217,7 @@ algorithm
214217
case Component.UNTYPED_COMPONENT()
215218
algorithm
216219
// Type the component's dimensions.
217-
typeDimensions(c.dimensions, node, c.binding, c.info);
220+
typeDimensions(c.dimensions, node, c.binding, clsScope, c.info);
218221

219222
// Construct the type of the component and update the node with it.
220223
ty := Type.liftArrayLeftList(makeClassType(c.classInst), arrayList(c.dimensions));
@@ -224,7 +227,7 @@ algorithm
224227
checkComponentAttributes(c.attributes, component);
225228

226229
// Type the component's children.
227-
typeComponents(c.classInst);
230+
typeComponents(c.classInst, clsScope);
228231
then
229232
ty;
230233

@@ -349,10 +352,11 @@ function typeDimensions
349352
input output array<Dimension> dimensions;
350353
input InstNode component;
351354
input Binding binding;
355+
input ClassScope clsScope;
352356
input SourceInfo info;
353357
algorithm
354358
for i in 1:arrayLength(dimensions) loop
355-
typeDimension(dimensions[i], component, binding, i, dimensions, info);
359+
typeDimension(dimensions[i], component, binding, i, clsScope, dimensions, info);
356360
end for;
357361
end typeDimensions;
358362

@@ -361,6 +365,7 @@ function typeDimension
361365
input InstNode component;
362366
input Binding binding;
363367
input Integer index;
368+
input ClassScope clsScope;
364369
input array<Dimension> dimensions;
365370
input SourceInfo info;
366371
algorithm
@@ -396,10 +401,20 @@ algorithm
396401
arrayUpdate(dimensions, index, Dimension.UNTYPED(dimension.dimension, true));
397402

398403
(exp, ty, var) := typeExp(dimension.dimension, info, ExpOrigin.DIMENSION());
399-
TypeCheck.checkDimension(exp, ty, var, info);
404+
TypeCheck.checkDimensionType(exp, ty, info);
400405

401-
exp := Ceval.evalExp(exp, Ceval.EvalTarget.DIMENSION(component, index, exp, info));
402-
exp := SimplifyExp.simplifyExp(exp);
406+
if var <= Variability.PARAMETER then
407+
// Evaluate the dimension if it's a parameter expression.
408+
exp := Ceval.evalExp(exp, Ceval.EvalTarget.DIMENSION(component, index, exp, info));
409+
exp := SimplifyExp.simplifyExp(exp);
410+
else
411+
// Dimensions must be parameter expressions, unless we're in a function.
412+
if clsScope <> ClassScope.FUNCTION then
413+
Error.addSourceMessage(Error.DIMENSION_NOT_KNOWN,
414+
{Expression.toString(exp)}, info);
415+
fail();
416+
end if;
417+
end if;
403418

404419
// It's possible to get an array expression here, for example if the
405420
// dimension expression is a parameter whose binding comes from a
@@ -417,7 +432,11 @@ algorithm
417432
then
418433
dim;
419434

420-
// If the dimension is unknown, try to infer it from the components binding.
435+
// If the dimension is unknown in a function, keep it unknown.
436+
case Dimension.UNKNOWN() guard clsScope == ClassScope.FUNCTION
437+
then dimension;
438+
439+
// If the dimension is unknown in a class, try to infer it from the components binding.
421440
case Dimension.UNKNOWN()
422441
algorithm
423442
dim := match binding
@@ -1123,7 +1142,7 @@ algorithm
11231142
else
11241143
error := TypingError.NO_ERROR();
11251144
d := arrayGet(c.dimensions, dimIndex);
1126-
d := typeDimension(d, node, c.binding, dimIndex, c.dimensions, c.info);
1145+
d := typeDimension(d, node, c.binding, dimIndex, ClassScope.CLASS, c.dimensions, c.info);
11271146
end if;
11281147
then
11291148
(d, error);
@@ -1172,7 +1191,7 @@ algorithm
11721191

11731192
case ComponentRef.CREF(node = InstNode.COMPONENT_NODE())
11741193
algorithm
1175-
node_ty := typeComponent(cref.node);
1194+
node_ty := typeComponent(cref.node, ClassScope.CLASS);
11761195
variability := ComponentRef.getVariability(cref);
11771196
subs := typeSubscripts(cref.subscripts, node_ty, cref.node, info);
11781197
cref_ty := Type.subscript(node_ty, subs);
@@ -1422,38 +1441,63 @@ algorithm
14221441
fail();
14231442
end if;
14241443

1425-
// TODO: Only evaluate the index if it's a constant (parameter?),
1426-
// otherwise just return a size expression.
1427-
index := Ceval.evalExp(index, Ceval.EvalTarget.IGNORE_ERRORS());
1428-
index := SimplifyExp.simplifyExp(index);
1429-
1430-
// TODO: Print an error if the index couldn't be evaluated to an int.
1431-
Expression.INTEGER(iindex) := index;
1432-
1433-
(dim, ty_err) := typeExpDim(sizeExp.exp, iindex, ExpOrigin.NO_ORIGIN(), info);
1434-
1435-
() := match ty_err
1436-
case NO_ERROR() then ();
1444+
if variability <= Variability.PARAMETER then
1445+
// Evaluate the index if it's a constant.
1446+
index := Ceval.evalExp(index, Ceval.EvalTarget.IGNORE_ERRORS());
1447+
index := SimplifyExp.simplifyExp(index);
1448+
1449+
// TODO: Print an error if the index couldn't be evaluated to an int.
1450+
Expression.INTEGER(iindex) := index;
1451+
1452+
// Get the iindex'd dimension of the expression.
1453+
(dim, ty_err) := typeExpDim(sizeExp.exp, iindex, ExpOrigin.NO_ORIGIN(), info);
1454+
1455+
() := match ty_err
1456+
case NO_ERROR() then ();
1457+
1458+
// The first argument wasn't an array.
1459+
case OUT_OF_BOUNDS(0)
1460+
algorithm
1461+
Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {"size"}, info);
1462+
then
1463+
fail();
1464+
1465+
// The index referred to an invalid dimension.
1466+
case OUT_OF_BOUNDS()
1467+
algorithm
1468+
Error.addSourceMessage(Error.INVALID_SIZE_INDEX,
1469+
{String(iindex), Expression.toString(sizeExp.exp), String(ty_err.upperBound)}, info);
1470+
then
1471+
fail();
1472+
end match;
1473+
1474+
if Dimension.isKnown(dim) then
1475+
// The dimension size is known, return its size.
1476+
exp := Expression.INTEGER(Dimension.size(dim));
1477+
else
1478+
// The dimension size is unknown, return a size expression. This can
1479+
// happen in functions where unknown dimensions are allowed.
1480+
exp := typeExp(sizeExp.exp, info);
1481+
exp := Expression.SIZE(exp, SOME(index));
1482+
end if;
14371483

1438-
// The first argument wasn't an array.
1439-
case OUT_OF_BOUNDS(0)
1440-
algorithm
1441-
Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {"size"}, info);
1442-
then
1443-
fail();
1484+
variability := Variability.PARAMETER;
1485+
else
1486+
// If the index is not a constant, type the whole expression.
1487+
(exp, exp_ty) := typeExp(sizeExp.exp, info);
14441488

1445-
// The index referred to an invalid dimension.
1446-
case OUT_OF_BOUNDS()
1447-
algorithm
1448-
Error.addSourceMessage(Error.INVALID_SIZE_INDEX,
1449-
{String(iindex), Expression.toString(sizeExp.exp), String(ty_err.upperBound)}, info);
1450-
then
1451-
fail();
1452-
end match;
1489+
// Check that it's an array.
1490+
if not Type.isArray(exp_ty) then
1491+
Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {"size"}, info);
1492+
fail();
1493+
end if;
14531494

1454-
dim_size := Dimension.size(dim);
1495+
// Since we don't know which dimension to take the size of, return a size expression.
1496+
exp := Expression.SIZE(exp, SOME(index));
1497+
variability := Variability.CONTINUOUS;
1498+
end if;
14551499
then
1456-
(Expression.INTEGER(dim_size), Type.INTEGER(), Variability.CONSTANT);
1500+
(exp, Type.INTEGER(), variability);
14571501

14581502
case Expression.SIZE()
14591503
algorithm

0 commit comments

Comments
 (0)