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

Commit cd7b28a

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Initial function evaluation implementation.
- Implemented basic function evaluation that supports all control structures and scalar assignments, but not e.g. arrays or records. - Moved storage of iteration ranges from the mutable iterators to the loop or reductions themselves, so they can safely be modified. - Added new mutable Expression for use by the function evaluation to avoid having to do name lookup. - Added flags --evalLoopLimit and --evalRecursionLimit to let users set the limits used to avoid infinite evaluation or stack overflows. Belonging to [master]: - OpenModelica/OpenModelica#73 - #2407 - OpenModelica/OpenModelica-testsuite#936
1 parent f92e6eb commit cd7b28a

18 files changed

+675
-250
lines changed

Compiler/NFFrontEnd/NFBuiltinFuncs.mo

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ constant InstNode INTEGER_DUMMY_NODE = NFInstNode.CLASS_NODE("Integer",
128128
constant Function INTEGER_FUNCTION = Function.FUNCTION(Path.IDENT("Integer"),
129129
INTEGER_DUMMY_NODE, {ENUM_PARAM}, {}, {}, {
130130
Slot.SLOT("e", SlotType.POSITIONAL, NONE(), NONE())
131-
}, Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
131+
}, Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true), Pointer.createImmutable(0));
132132

133133
constant InstNode INTEGER_NODE = InstNode.CLASS_NODE("IntegerFunc",
134134
DUMMY_ELEMENT, Visibility.PUBLIC,
@@ -153,38 +153,43 @@ constant Function STRING_REAL = Function.FUNCTION(Path.IDENT("String"),
153153
Slot.SLOT("significantDigits", SlotType.NAMED, SOME(Expression.INTEGER(6)), NONE()),
154154
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE()),
155155
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE())
156-
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
156+
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
157+
Pointer.createImmutable(true), Pointer.createImmutable(0));
157158

158159
// String(r, format="-0.6g")
159160
constant Function STRING_REAL_FORMAT = Function.FUNCTION(Path.IDENT("String"),
160161
STRING_DUMMY_NODE, {REAL_PARAM, STRING_PARAM}, {STRING_PARAM}, {}, {
161162
Slot.SLOT("r", SlotType.POSITIONAL, NONE(), NONE()),
162163
Slot.SLOT("format", SlotType.NAMED, NONE(), NONE())
163-
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
164+
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
165+
Pointer.createImmutable(true), Pointer.createImmutable(0));
164166

165167
// String(i, minimumLength=0, leftJustified=true)
166168
constant Function STRING_INT = Function.FUNCTION(Path.IDENT("String"),
167169
STRING_DUMMY_NODE, {INT_PARAM, INT_PARAM, BOOL_PARAM}, {STRING_PARAM}, {}, {
168170
Slot.SLOT("i", SlotType.POSITIONAL, NONE(), NONE()),
169171
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE()),
170172
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE())
171-
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
173+
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
174+
Pointer.createImmutable(true), Pointer.createImmutable(0));
172175

173176
// String(b, minimumLength=0, leftJustified=true)
174177
constant Function STRING_BOOL = Function.FUNCTION(Path.IDENT("String"),
175178
STRING_DUMMY_NODE, {BOOL_PARAM, INT_PARAM, BOOL_PARAM}, {STRING_PARAM}, {}, {
176179
Slot.SLOT("b", SlotType.POSITIONAL, NONE(), NONE()),
177180
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE()),
178181
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE())
179-
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
182+
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
183+
Pointer.createImmutable(true), Pointer.createImmutable(0));
180184

181185
// String(e, minimumLength=0, leftJustified=true)
182186
constant Function STRING_ENUM = Function.FUNCTION(Path.IDENT("String"),
183187
STRING_DUMMY_NODE, {ENUM_PARAM, INT_PARAM, BOOL_PARAM}, {STRING_PARAM}, {}, {
184188
Slot.SLOT("e", SlotType.POSITIONAL, NONE(), NONE()),
185189
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE()),
186190
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE())
187-
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
191+
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
192+
Pointer.createImmutable(true), Pointer.createImmutable(0));
188193

189194
constant InstNode STRING_NODE = InstNode.CLASS_NODE("String",
190195
DUMMY_ELEMENT, Visibility.PUBLIC,
@@ -208,35 +213,43 @@ constant ComponentRef STRING_CREF =
208213

209214
constant Function ABS_REAL = Function.FUNCTION(Path.IDENT("abs"),
210215
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
211-
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
216+
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
217+
Pointer.createImmutable(true), Pointer.createImmutable(0));
212218

213219
constant Function MAX_REAL = Function.FUNCTION(Path.IDENT("max"),
214220
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
215-
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
221+
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
222+
Pointer.createImmutable(true), Pointer.createImmutable(0));
216223

217224
constant Function POSITIVE_MAX_REAL = Function.FUNCTION(Path.IDENT("$OMC$PositiveMax"),
218225
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
219-
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
226+
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
227+
Pointer.createImmutable(true), Pointer.createImmutable(0));
220228

221229
constant Function IN_STREAM = Function.FUNCTION(Path.IDENT("inStream"),
222230
InstNode.EMPTY_NODE(), {REAL_PARAM}, {REAL_PARAM}, {}, {},
223-
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
231+
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
232+
Pointer.createImmutable(true), Pointer.createImmutable(0));
224233

225234
constant Function PROMOTE = Function.FUNCTION(Path.IDENT("promote"),
226235
InstNode.EMPTY_NODE(), {}, {}, {}, {},
227-
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
236+
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
237+
Pointer.createImmutable(true), Pointer.createImmutable(0));
228238

229239
constant Function CAT = Function.FUNCTION(Path.IDENT("cat"),
230240
InstNode.EMPTY_NODE(), {}, {}, {}, {},
231-
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
241+
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
242+
Pointer.createImmutable(true), Pointer.createImmutable(0));
232243

233244
constant Function ARRAY_FUNC = Function.FUNCTION(Path.IDENT("array"),
234245
InstNode.EMPTY_NODE(), {}, {}, {}, {},
235-
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
246+
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
247+
Pointer.createImmutable(true), Pointer.createImmutable(0));
236248

237249
constant Function FILL_FUNC = Function.FUNCTION(Path.IDENT("fill"),
238250
InstNode.EMPTY_NODE(), {}, {}, {}, {},
239-
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));
251+
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN,
252+
Pointer.createImmutable(true), Pointer.createImmutable(0));
240253

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

Compiler/NFFrontEnd/NFCall.mo

Lines changed: 81 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,15 @@ uniontype Call
165165
record UNTYPED_MAP_CALL
166166
// Function fn;
167167
Expression exp;
168-
list<InstNode> iters;
168+
list<tuple<InstNode, Expression>> iters;
169169
end UNTYPED_MAP_CALL;
170170

171171
record TYPED_MAP_CALL
172172
// Function fn;
173173
Type ty;
174174
Variability var;
175175
Expression exp;
176-
list<InstNode> iters;
176+
list<tuple<InstNode, Expression>> iters;
177177
end TYPED_MAP_CALL;
178178

179179
function instantiate
@@ -271,7 +271,7 @@ uniontype Call
271271
protected
272272
ComponentRef fn_ref, arr_fn_ref;
273273
Expression exp;
274-
list<InstNode> iters;
274+
list<tuple<InstNode, Expression>> iters;
275275
Call call;
276276
Boolean is_builtin_reduction, is_array;
277277
algorithm
@@ -320,7 +320,7 @@ uniontype Call
320320
input InstNode scope;
321321
input SourceInfo info;
322322
output Expression exp;
323-
output list<InstNode> iters;
323+
output list<tuple<InstNode, Expression>> iters;
324324
algorithm
325325
_ := match args
326326
local
@@ -340,16 +340,15 @@ uniontype Call
340340
input InstNode scope;
341341
input SourceInfo info;
342342
output InstNode outScope = scope;
343-
output list<InstNode> outIters = {};
343+
output list<tuple<InstNode, Expression>> outIters = {};
344344
protected
345-
Binding binding;
345+
Expression range;
346346
InstNode iter;
347347
algorithm
348348
for i in inIters loop
349-
binding := Binding.fromAbsyn(i.range, false, 0, outScope, info);
350-
binding := Inst.instBinding(binding);
351-
(outScope, iter) := Inst.addIteratorToScope(i.name, binding, outScope, info);
352-
outIters := iter :: outIters;
349+
range := Inst.instExp(Util.getOption(i.range), outScope, info);
350+
(outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info);
351+
outIters := (iter, range) :: outIters;
353352
end for;
354353

355354
outIters := listReverse(outIters);
@@ -489,35 +488,40 @@ uniontype Call
489488
output Type ty;
490489
output Variability variability;
491490
protected
492-
Expression arg;
493-
Type arg_ty;
491+
Expression arg, range;
492+
Type iter_ty;
494493
Binding binding;
495-
Variability arg_var;
494+
Variability iter_var;
495+
InstNode iter;
496+
list<Dimension> dims = {};
497+
list<tuple<InstNode, Expression>> iters = {};
496498
algorithm
497499
(call, ty, variability) := match call
498500
// This is always a call to the function array()/$array(). See instIteratorCall.
499501
// Other mapping function calls are already wrapped by array() at this point.
500-
case UNTYPED_MAP_CALL() algorithm
501-
502-
for iter in call.iters loop
503-
Typing.typeIterator(iter, ExpOrigin.FUNCTION, structural = false);
504-
end for;
505-
(arg, arg_ty, arg_var) := Typing.typeExp(call.exp, origin, info);
506-
507-
ty := arg_ty;
508-
variability := Variability.CONSTANT;
509-
for iter in call.iters loop
510-
binding := Component.getBinding(InstNode.component(iter));
511-
ty := Type.liftArrayLeftList(ty,Type.arrayDims(Binding.getType(binding)));
512-
variability := Variability.variabilityMax(variability,Binding.variability(binding));
513-
end for;
514-
then
515-
(TYPED_MAP_CALL(ty, variability, arg, call.iters), ty, variability);
502+
case UNTYPED_MAP_CALL()
503+
algorithm
504+
variability := Variability.CONSTANT;
505+
506+
for i in call.iters loop
507+
(iter, range) := i;
508+
(range, iter_ty, iter_var) := Typing.typeIterator(iter, range, ExpOrigin.FUNCTION, structural = false);
509+
dims := listAppend(Type.arrayDims(iter_ty), dims);
510+
variability := Variability.variabilityMax(variability, iter_var);
511+
iters := (iter, range) :: iters;
512+
end for;
513+
iters := listReverseInPlace(iters);
516514

517-
else algorithm
518-
Error.assertion(false, getInstanceName() + " got invalid function call expression", sourceInfo());
519-
then
520-
fail();
515+
(arg, ty) := Typing.typeExp(call.exp, origin, info);
516+
ty := Type.liftArrayLeftList(ty, dims);
517+
then
518+
(TYPED_MAP_CALL(ty, variability, arg, iters), ty, variability);
519+
520+
else
521+
algorithm
522+
Error.assertion(false, getInstanceName() + " got invalid function call expression", sourceInfo());
523+
then
524+
fail();
521525
end match;
522526
end typeMapIteratorCall;
523527

@@ -646,69 +650,60 @@ uniontype Call
646650
function vectorizeCall
647651
input Call base_call;
648652
input FunctionMatchKind mk;
649-
input InstNode call_scope;
653+
input InstNode scope;
650654
input SourceInfo info;
651655
output Call vectorized_call;
652656
protected
653657
Type ty, vect_ty;
654658
Expression exp;
655659
Binding bind;
656-
list<InstNode> iters;
657-
InstNode iter, iter_scope;
660+
list<tuple<InstNode, Expression>> iters;
661+
InstNode iter;
658662
BindingOrigin origin;
659663
Integer i;
660664
list<Dimension> vect_dims;
661665
list<Boolean> arg_is_vected, b_list;
662666
Boolean b;
663667
list<Expression> vect_args;
664668
algorithm
665-
666669
vectorized_call := match base_call
667-
case TYPED_CALL() algorithm
668-
669-
FunctionMatchKind.VECTORIZED(vect_dims, arg_is_vected) := mk;
670-
iters := {};
671-
iter_scope := call_scope;
672-
i := 1;
673-
674-
for dim in vect_dims loop
675-
676-
// Create a range binding on which we will iterate to vectorize.
677-
ty := Type.ARRAY(Type.INTEGER(), {dim});
678-
exp := Expression.RANGE(ty, Expression.INTEGER(1), NONE(), Expression.INTEGER(Dimension.size(dim)));
679-
origin := BindingOrigin.create(0, NFBindingOrigin.ElementType.COMPONENT, info);
680-
bind := Binding.TYPED_BINDING(exp, ty, Variability.CONSTANT, origin, false);
681-
682-
// Add an iterator to the call scope.
683-
(iter_scope, iter) := Inst.addIteratorToScope("$i" + intString(i), bind, iter_scope, info, Type.INTEGER());
684-
iters := iter::iters;
685-
686-
// Now that iterator is ready apply it, as a subscript, to each argument that is supposed to be vectorized
687-
// Make a cref expression from the iterator
688-
exp := Expression.CREF(Type.INTEGER(), ComponentRef.makeIterator(iter, Type.INTEGER()));
689-
vect_args := {};
690-
b_list := arg_is_vected;
691-
for arg in base_call.arguments loop
692-
b::b_list := b_list;
693-
// If the argument is supposed to be vectorized
694-
if b then
695-
vect_args := Expression.applyIndexSubscript(exp, arg)::vect_args;
696-
else
697-
vect_args := arg::vect_args;
698-
end if;
699-
end for;
700-
base_call.arguments := listReverse(vect_args);
701-
702-
i := i + 1;
703-
end for;
704-
// iters := listReverse(iters);
670+
case TYPED_CALL()
671+
algorithm
672+
FunctionMatchKind.VECTORIZED(vect_dims, arg_is_vected) := mk;
673+
iters := {};
674+
i := 1;
675+
676+
for dim in vect_dims loop
677+
// Create the range on which we will iterate to vectorize.
678+
ty := Type.ARRAY(Type.INTEGER(), {dim});
679+
exp := Expression.RANGE(ty, Expression.INTEGER(1), NONE(), Expression.INTEGER(Dimension.size(dim)));
680+
681+
// Create the iterator.
682+
iter := InstNode.fromComponent("$i" + intString(i),
683+
Component.ITERATOR(Type.INTEGER(), Variability.CONSTANT, info), scope);
684+
685+
iters := (iter, exp) :: iters;
686+
687+
// Now that iterator is ready apply it, as a subscript, to each argument that is supposed to be vectorized
688+
// Make a cref expression from the iterator
689+
exp := Expression.CREF(Type.INTEGER(), ComponentRef.makeIterator(iter, Type.INTEGER()));
690+
vect_args := {};
691+
b_list := arg_is_vected;
692+
for arg in base_call.arguments loop
693+
// If the argument is supposed to be vectorized
694+
b :: b_list := b_list;
695+
vect_args := (if b then Expression.applyIndexSubscript(exp, arg) else arg) :: vect_args;
696+
end for;
705697

706-
vect_ty := Type.liftArrayLeftList(base_call.ty, vect_dims);
698+
base_call.arguments := listReverse(vect_args);
699+
i := i + 1;
700+
end for;
707701

708-
then TYPED_MAP_CALL(vect_ty, base_call.var, Expression.CALL(base_call), iters);
702+
vect_ty := Type.liftArrayLeftList(base_call.ty, vect_dims);
703+
then
704+
TYPED_MAP_CALL(vect_ty, base_call.var, Expression.CALL(base_call), iters);
709705

710706
end match;
711-
712707
end vectorizeCall;
713708

714709
function evaluateCallType
@@ -1235,19 +1230,17 @@ protected
12351230
end toDAE;
12361231

12371232
function iteratorToDAE
1238-
input InstNode iter;
1233+
input tuple<InstNode, Expression> iter;
12391234
output DAE.ReductionIterator diter;
12401235
protected
1236+
InstNode iter_node;
1237+
Expression iter_range;
12411238
Component c;
12421239
Binding b;
12431240
algorithm
1244-
c := InstNode.component(iter);
1245-
diter := match c
1246-
case Component.ITERATOR() algorithm
1247-
b := Component.getBinding(c);
1248-
then
1249-
DAE.REDUCTIONITER(InstNode.name(iter), Expression.toDAE(Binding.getTypedExp(b)), NONE(), Type.toDAE(Binding.getType(b)));
1250-
end match;
1241+
(iter_node, iter_range) := iter;
1242+
diter := DAE.REDUCTIONITER(InstNode.name(iter_node), Expression.toDAE(iter_range), NONE(),
1243+
Type.toDAE(Expression.typeOf(iter_range)));
12511244
end iteratorToDAE;
12521245

12531246
function toString
@@ -1295,10 +1288,8 @@ protected
12951288
algorithm
12961289
name := Absyn.pathString(Function.name(NFBuiltinFuncs.ARRAY_FUNC));
12971290
arg_str := Expression.toString(call.exp);
1298-
c := stringDelimitList(list(
1299-
InstNode.name(iter) + " in "+ Binding.toString(Component.getBinding(InstNode.component(iter)))
1300-
for iter in call.iters)
1301-
, ", ");
1291+
c := stringDelimitList(list(InstNode.name(Util.tuple21(iter)) + " in " +
1292+
Expression.toString(Util.tuple22(iter)) for iter in call.iters), ", ");
13021293
then
13031294
name + "(" + arg_str + " for " + c + ")";
13041295

0 commit comments

Comments
 (0)