/
EvaluateFunctions.mo
3491 lines (3217 loc) · 140 KB
/
EvaluateFunctions.mo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/
encapsulated package EvaluateFunctions
" file: EvaluateFunctions.mo
package: EvaluateFunctions
description: This package contains functions to evaluate modelica functions completely or partially"
public import Absyn;
public import BackendDAE;
public import DAE;
public import HashTable2;
public import BackendVarTransform;
public import HashSetExp;
protected import AbsynUtil;
protected import BackendDAEUtil;
protected import BackendDump;
protected import BackendEquation;
protected import BackendVariable;
protected import ClassInf;
protected import ComponentReference;
protected import DAEUtil;
protected import DAEDump;
protected import Expression;
protected import ExpressionDump;
protected import ExpressionSimplify;
protected import Flags;
protected import List;
protected import RemoveSimpleEquations;
protected import Util;
// =============================================================================
// TODO:
// - evaluation of for-loops
// - evaluation of while-loops
// - evaluation of xOut := funcCall1(funcCall2(xIn[1])); with funcCall2(xIn[1]) = xIn[1,2] for example have a look at Media.Examples.ReferenceAir.MoistAir
// - evaluation of BackendDAE.ARRAY_EQUATION
// =============================================================================
// =============================================================================
// type definitions
//
// =============================================================================
public uniontype FuncInfo "store informations when traversing the statements and evaluate the function calls"
record FUNCINFO
BackendVarTransform.VariableReplacements repl;
DAE.FunctionTree funcTree;
Integer idx;
end FUNCINFO;
end FuncInfo;
public uniontype Variability
record CONST end CONST;
record VARIABLE end VARIABLE;
end Variability;
public uniontype CallSignature
record SIGNATURE
Absyn.Path path;
list<Variability> inputsVari;//not scalar, take records, arrays, calls as a single input variability
Boolean canBeEvaluated;
end SIGNATURE;
end CallSignature;
// =============================================================================
// caching of already evaluated functions
//
// =============================================================================
protected function checkCallSignatureForExp
input DAE.Exp expIn;
input list<CallSignature> signLst;
output Boolean continueEval;
protected
CallSignature signature;
algorithm
continueEval := true;
signature := getCallSignatureForCall(expIn);
if List.isMemberOnTrue(signature,signLst,callSignatureIsEqual) then
SIGNATURE(canBeEvaluated = continueEval) := List.getMemberOnTrue(signature,signLst,callSignatureIsEqual);
end if;
end checkCallSignatureForExp;
protected function callSignatureStr "outputs a string representation for the CallSignature"
input CallSignature signat;
output String str;
protected
Absyn.Path path;
list<Variability> varis;
Boolean b;
algorithm
SIGNATURE(path=path,inputsVari=varis, canBeEvaluated=b) := signat;
str := AbsynUtil.pathString(path)+"[ "+stringDelimitList(List.map(varis,VariabilityString)," | ")+" ] "+boolString(b);
end callSignatureStr;
protected function VariabilityString "outputs a string representation for the Variability"
input Variability var;
output String str;
algorithm
str := match(var)
case(CONST())
then "CONST";
else "VARIABLE";
end match;
end VariabilityString;
protected function callSignatureIsEqual"outputs true if 2 CallSignatures are equal"
input CallSignature signat1;
input CallSignature signat2;
output Boolean isEqual;
protected
Absyn.Path path1,path2;
list<Variability> vari1,vari2;
algorithm
SIGNATURE(path=path1, inputsVari=vari1) := signat1;
SIGNATURE(path=path2, inputsVari=vari2) := signat2;
isEqual := false;
if AbsynUtil.pathEqual(path1,path2) then
if List.isEqualOnTrue(vari1,vari2,VariabilityIsEqual) then
isEqual := true;
end if;
end if;
end callSignatureIsEqual;
protected function VariabilityIsEqual"outputs true if 2 Variabilites are equal"
input Variability vari1;
input Variability vari2;
output Boolean isEqual;
algorithm
isEqual := match(vari1,vari2)
case(CONST(),CONST())
then true;
case(VARIABLE(),VARIABLE())
then true;
else
then false;
end match;
end VariabilityIsEqual;
protected function getCallSignatureForCall"determines the callSignature for a function call expression"
input DAE.Exp callExpIn;
output CallSignature signatureOut;
protected
Absyn.Path path;
list<DAE.Exp> expLst;
list<Variability> vari;
algorithm
try
DAE.CALL(path=path, expLst=expLst) := callExpIn;
vari := List.map(expLst,getVariabilityForExp);
signatureOut := SIGNATURE(path,vari,true);
else
print("evalFunc.getCallSignatureForCall failed for :\n"+ExpressionDump.printExpStr(callExpIn)+"\n");
fail();
end try;
end getCallSignatureForCall;
protected function getVariabilityForExp"determines if the exp is either constant or variable"
input DAE.Exp expIn;
output Variability variOut;
algorithm
variOut := match(expIn)
local
Variability vari;
case(DAE.ICONST())
then CONST();
case(DAE.RCONST())
then CONST();
case(DAE.SCONST())
then CONST();
case(DAE.BCONST())
then CONST();
case(DAE.CLKCONST())
then CONST();
case(DAE.ENUM_LITERAL())
then CONST();
case(DAE.CREF())
then VARIABLE();
case(DAE.BINARY())
equation
if Expression.isConst(expIn) then
vari = CONST();
else
vari=VARIABLE(); end if;
then vari;
case(DAE.UNARY())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.LBINARY())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.LUNARY())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.RELATION())
then VARIABLE();
case(DAE.IFEXP())
then VARIABLE();
case(DAE.CALL())
then VARIABLE();
case(DAE.RECORD())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.PARTEVALFUNCTION())
then VARIABLE();
case(DAE.ARRAY())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.MATRIX())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.RANGE())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.TUPLE())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.CAST())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.ASUB())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.TSUB())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.RSUB())
equation
if Expression.isConst(expIn) then vari = CONST();
else vari=VARIABLE(); end if;
then vari;
case(DAE.SIZE())
then VARIABLE();
case(DAE.CODE())
then VARIABLE();
case(DAE.EMPTY())
then VARIABLE();
case(DAE.REDUCTION())
then VARIABLE();
else
VARIABLE();
end match;
end getVariabilityForExp;
// =============================================================================
// evaluate functions
//
// =============================================================================
public function evalFunctions "backend optmization module to evaluate functions completely or partially.
partial constant outputs are added as extra equations. Therefore removeSimpleEquations is necessary afterwards
author:Waurich TUD 2014-04"
input BackendDAE.BackendDAE inDAE;
output BackendDAE.BackendDAE outDAE;
protected
Boolean changed;
BackendDAE.EqSystems eqSysts;
BackendDAE.Shared shared;
algorithm
try
BackendDAE.DAE(eqs=eqSysts, shared=shared) := inDAE;
(eqSysts, (shared, _, changed, _)) := List.mapFold(eqSysts, evalFunctions_main, (shared, 1, false, {}));
//shared = evaluateShared(shared);
if changed then
outDAE := updateVarKinds(RemoveSimpleEquations.fastAcausal(BackendDAE.DAE(eqSysts, shared)));
else
outDAE := inDAE;
end if;
else
outDAE := inDAE;
end try;
end evalFunctions;
protected function evaluateShared "evaluate objects in the shared structure that could be dependent of a function. i.e. parameters
author:Waurich TUD 2014-04"
input BackendDAE.Shared sharedIn;
output BackendDAE.Shared sharedOut;
protected
BackendDAE.Variables globalKnownVars;
DAE.FunctionTree funcTree;
list<BackendDAE.Var> varLst;
algorithm
globalKnownVars := BackendDAEUtil.getGlobalKnownVarsFromShared(sharedIn);
funcTree := BackendDAEUtil.getFunctions(sharedIn);
varLst := BackendVariable.varList(globalKnownVars);
varLst := List.map1(varLst,evaluateParameter,funcTree);
globalKnownVars := BackendVariable.listVar(varLst);
sharedOut := BackendDAEUtil.setSharedGlobalKnownVars(sharedIn,globalKnownVars);
end evaluateShared;
protected function evaluateParameter "evaluates a parameter"
input BackendDAE.Var varIn;
input DAE.FunctionTree funcTree;
output BackendDAE.Var varOut;
algorithm
varOut := matchcontinue(varIn,funcTree)
local
DAE.Exp bindExp;
case(BackendDAE.VAR(varKind=BackendDAE.PARAM()),_)
equation
BackendDump.printVar(varIn);
bindExp = BackendVariable.varBindExp(varIn);
true = Expression.isCall(bindExp);
ExpressionDump.dumpExp(bindExp);
((bindExp,_,_,_,_,_,_)) = evaluateConstantFunction(bindExp,bindExp,funcTree,1,{});
ExpressionDump.dumpExp(bindExp);
then
varIn;
else varIn;
end matchcontinue;
end evaluateParameter;
protected function evalFunctions_main "traverses the eqSystems for function calls and tries to evaluate them"
input BackendDAE.EqSystem eqSysIn;
input tuple<BackendDAE.Shared,Integer,Boolean, list<CallSignature>> tplIn;
output BackendDAE.EqSystem eqSysOut;
output tuple<BackendDAE.Shared,Integer,Boolean, list<CallSignature>> tplOut;
protected
Boolean changed;
Integer sysIdx;
BackendDAE.Shared sharedIn, shared;
BackendDAE.EquationArray eqs;
list<BackendDAE.Equation> eqLst, addEqs;
list<CallSignature> callSign;
algorithm
(sharedIn,sysIdx,changed,callSign) := tplIn;
BackendDAE.EQSYSTEM(orderedEqs=eqs) := eqSysIn;
eqLst := BackendEquation.equationList(eqs);
//traverse the eqSystem for function calls
(eqLst, shared, addEqs, _, changed, callSign) := List.mapFold5(eqLst, evalFunctions_findFuncs, sharedIn, {}, 1, changed, callSign);
eqs := BackendEquation.listEquation(listAppend(eqLst, addEqs));
eqSysOut := BackendDAEUtil.setEqSystEqs(eqSysIn, eqs);
tplOut := (shared, sysIdx+1, changed, callSign);
end evalFunctions_main;
protected function evalFunctions_findFuncs "traverses the lhs and rhs exps of an equation and tries to evaluate function calls "
input output BackendDAE.Equation eqIn;
input output BackendDAE.Shared shared;
input output list<BackendDAE.Equation> addEqs;
input output Integer idx;
input output Boolean changed;
input output list<CallSignature> callSign;
algorithm
eqIn := matchcontinue(eqIn)
local
Boolean b1,b2, changed1;
BackendDAE.Equation eq;
BackendDAE.EquationAttributes attr;
DAE.Exp exp1,exp2,lhsExp,rhsExp;
DAE.ElementSource source;
DAE.FunctionTree funcs;
list<BackendDAE.Equation> addEqs1, addEqs2;
list<DAE.Exp> lhs;
case(BackendDAE.EQUATION(exp=exp1, scalar=exp2,source=source,attr=attr))
equation
b1 = Expression.containFunctioncall(exp1);
b2 = Expression.containFunctioncall(exp2);
true = b1 or b2;
funcs = BackendDAEUtil.getFunctions(shared);
((rhsExp,lhsExp,addEqs1,funcs,idx,changed1,callSign)) = if b1 then evaluateConstantFunction(exp1,exp2,funcs,idx,callSign) else (exp2,exp1,{},funcs,idx,changed,callSign);
changed = changed1 or changed;
((rhsExp,lhsExp,addEqs2,funcs,idx,changed1,callSign)) = if b2 then evaluateConstantFunction(exp2,exp1,funcs,idx,callSign) else (rhsExp,lhsExp,{},funcs,idx,changed,callSign);
changed = changed1 or changed;
addEqs = listAppend(addEqs1,addEqs);
addEqs = listAppend(addEqs2,addEqs);
eq = BackendEquation.generateEquation(lhsExp,rhsExp,source,attr);
//if changed then print("FROM EQ "+BackendDump.equationString(eqIn)+"\n");print("GOT EQ "+BackendDump.equationString(eq)+"\n"); end if;
idx = idx+1;
then
eq;
case(BackendDAE.ARRAY_EQUATION())
equation
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print("this is an array equation. update evalFunctions_findFuncs\n");
end if;
then
eqIn;
case(BackendDAE.COMPLEX_EQUATION(left=exp1, right=exp2, source=source, attr=attr))
equation
b1 = Expression.containFunctioncall(exp1);
b2 = Expression.containFunctioncall(exp2);
true = b1 or b2;
funcs = BackendDAEUtil.getFunctions(shared);
((rhsExp,lhsExp,addEqs1,funcs,idx,changed1,callSign)) = if b1 then evaluateConstantFunction(exp1,exp2,funcs,idx,callSign) else (exp2,exp1,{},funcs,idx,changed,callSign);
changed = changed or changed1;
((rhsExp,lhsExp,addEqs2,funcs,idx,changed1,callSign)) = if b2 then evaluateConstantFunction(exp2,exp1,funcs,idx,callSign) else (rhsExp,lhsExp,{},funcs,idx,changed,callSign);
changed = changed or changed1;
addEqs = listAppend(addEqs1,addEqs);
addEqs = listAppend(addEqs2,addEqs);
shared = BackendDAEUtil.setSharedFunctionTree(shared, funcs);
eq = BackendEquation.generateEquation(lhsExp,rhsExp,source,attr);
//since tuple=tuple is not supported, these equations are converted into a list of simple equations
(eq,addEqs) = convertTupleEquations(eq,addEqs);
//if changed then print("FROM EQ "+BackendDump.equationString(eqIn)+"\n");print("GOT EQ "+BackendDump.equationString(eq)+"\n"); end if;
idx = idx+1;
then
eq;
else
eqIn;
end matchcontinue;
end evalFunctions_findFuncs;
public function evaluateConstantFunctionCallExp"checks if the expression is a call and can be evaluated to a constant value.
the output is either a constant expression or the input exp. no partial evaluation is performed in here."
input DAE.Exp expIn;
input DAE.FunctionTree funcsIn;
input Boolean evalConstArgsOnly;
output DAE.Exp expOut;
algorithm
expOut := matchcontinue(expIn,funcsIn)
local
Boolean hasAssert, hasReturn, hasTerminate, hasReinit, abort;
Integer idx;
Absyn.Path path;
BackendVarTransform.VariableReplacements repl;
DAE.CallAttributes attr1;
DAE.Exp exp;
DAE.Function func;
DAE.FunctionTree funcs;
list<DAE.ComponentRef> allInputCrefs, outputCrefs, allOutputCrefs, constInputCrefs, constCrefs, varScalarCrefsInFunc,constComplexCrefs,varComplexCrefs,varScalarCrefs,constScalarCrefs;
list<list<DAE.ComponentRef>> scalarInputs, scalarOutputs;
list<DAE.Element> elements, protectVars, algs, allInputs, allOutputs;
list<DAE.Exp> exps, exps0, sub, allInputExps, constInputExps, constExps, constComplexExps, constScalarExps;
list<list<DAE.Exp>> scalarExp;
case(DAE.CALL(path=path, expLst=exps0),_)
equation
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print("\nStart constant evaluation of expression: "+ExpressionDump.printExpStr(expIn)+"\n\n");
end if;
if evalConstArgsOnly then
true = Expression.isConstWorkList(exps0);
end if;
// get the elements of the function and the algorithms
SOME(func) = DAE.AvlTreePathFunction.get(funcsIn,path);
// fail if is an external function!
false = DAEUtil.isExtFunction(func);
elements = DAEUtil.getFunctionElements(func);
// get the input exps from the call
exps = List.map2(exps0, evaluateConstantFunctionCallExp, funcsIn, evalConstArgsOnly);
scalarExp = List.map1(exps, expandComplexEpressions, funcsIn);
allInputExps = List.flatten(scalarExp);
//print("allInputExps\n"+stringDelimitList(List.map(allInputExps,ExpressionDump.printExpStr),"\n")+"\n");
if listEmpty(elements) and DAEUtil.funcIsRecord(func) then // its a record
//-----------------------its a record-----------------------
expOut = DAE.TUPLE(allInputExps);
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then print("\nIts a record.\n");
end if;
else
//-----------------------its a function call-----------------------
// get all input crefs (from function body) (scalar and one dimensioanl)
allInputs = List.filterOnTrue(elements,DAEUtil.isInputVar);
scalarInputs = List.map(allInputs,expandComplexElementsToCrefs);
allInputCrefs = List.flatten(scalarInputs);
//print("\nallInputCrefs\n"+stringDelimitList(List.map(allInputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
protectVars = List.filterOnTrue(elements,DAEUtil.isProtectedVar);
algs = List.filterOnTrue(elements,DAEUtil.isAlgorithm);
algs = listAppend(protectVars,algs);
// get all output crefs (complex and scalar)
allOutputs = List.filterOnTrue(elements,DAEUtil.isOutputVar);
outputCrefs = List.map(allOutputs,DAEUtil.varCref);
scalarOutputs = List.map(allOutputs,getScalarsForComplexVar);
allOutputCrefs = listAppend(outputCrefs,List.flatten(scalarOutputs));
//print("\n allOutputs\n"+stringDelimitList(List.map(outputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("\nscalarOutputs\n"+stringDelimitList(List.map(List.flatten(scalarOutputs),ComponentReference.printComponentRefStr),"\n")+"\n");
// get the constant inputs
//print("\nallInputExps\n"+stringDelimitList(List.map(allInputExps,ExpressionDump.printExpStr),"\n")+"\n");
//print("\nall algs "+intString(listLength(algs))+"\n"+DAEDump.dumpElementsStr(algs)+"\n");
(constInputExps,constInputCrefs) = List.filterOnTrueSync(allInputExps,Expression.isConst,allInputCrefs);
//print("\nconstInputExps\n"+stringDelimitList(List.map(constInputExps,ExpressionDump.printExpStr),"\n")+"\n");
//print("\nconstInputCrefs\n"+stringDelimitList(List.map(constInputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("\nall algs "+intString(listLength(algs))+"\n"+DAEDump.dumpElementsStr(algs)+"\n");
//build replacement rules
repl = BackendVarTransform.emptyReplacements();
repl = BackendVarTransform.addReplacements(repl,constInputCrefs,constInputExps,NONE());
//repl = BackendVarTransform.addReplacements(repl,allInputCrefs,allInputExps,NONE());
//BackendVarTransform.dumpReplacements(repl);
// recognize if there are statements we cannot evaluate at the moment
_ = List.fold(algs,hasAssertFold,false);
_ = List.fold(algs,hasReturnFold,false);
_ = List.fold(algs,hasReturnFold,false);
_ = List.fold(algs,hasReinitFold,false);
// go through all algorithms and replace the variables with constants if possible, extend the ht after each algorithm, consider bindings of protected vars as well
(algs,_,repl,_) = List.mapFold3(algs,evaluateFunctions_updateAlgElements,funcsIn,repl,1);
//print("\nall algs after"+intString(listLength(algs))+"\n"+DAEDump.dumpElementsStr(algs)+"\n");
//BackendVarTransform.dumpReplacements(repl);
//get all replacements in order to check for constant outputs
(constCrefs,constExps) = BackendVarTransform.getAllReplacements(repl);
(constCrefs,constExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,allOutputCrefs,constExps); // extract outputs
(constExps,constCrefs) = List.filterOnTrueSync(constExps,Expression.isConst,constCrefs); // extract constant outputs
//print("all constant crefs \n"+stringDelimitList(List.map(constCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("all constant exps:\n"+ExpressionDump.printExpListStr(constExps)+"\n");
// get the completely constant complex outputs, the constant parts of complex outputs and the variable parts of complex outputs and the expressions
(constComplexCrefs,_,constScalarCrefs,varScalarCrefs) = checkIfOutputIsEvaluatedConstant(allOutputs,constCrefs,{},{},{},{});
constScalarExps = List.map1r(constScalarCrefs,BackendVarTransform.getReplacement,repl);
constComplexExps = List.map1r(constComplexCrefs,BackendVarTransform.getReplacement,repl);
(constScalarCrefs,constScalarExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,constScalarCrefs,constExps);
(constComplexCrefs,constComplexExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,constComplexCrefs,constExps);
//print("constComplexCrefs\n"+stringDelimitList(List.map(constComplexCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("varComplexCrefs\n"+stringDelimitList(List.map(varComplexCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("constScalarCrefs\n"+stringDelimitList(List.map(constScalarCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("varScalarCrefs\n"+stringDelimitList(List.map(varScalarCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
if listEmpty(varScalarCrefs) and listEmpty(varScalarCrefs) and listEmpty(constComplexCrefs) and not listEmpty(constScalarExps) then
// there is a constant scalar expression
if listLength(constScalarCrefs)==1 then expOut = listHead(constScalarExps);
else expOut = DAE.TUPLE(constScalarExps); end if;
elseif listEmpty(varScalarCrefs) and listEmpty(varScalarCrefs) and listEmpty(constScalarCrefs) and not listEmpty(constComplexExps) then
// there is a constant complex expression
if listLength(constComplexCrefs)==1 then expOut = listHead(constComplexExps);
else expOut = DAE.TUPLE(constComplexExps); end if;
else expOut = expIn;
end if;
end if;
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print("\nevaluated to: "+ExpressionDump.printExpStr(expOut)+"\n\n");
end if;
then expOut;
case(DAE.ASUB(DAE.CALL(path=path, expLst=exps, attr=attr1),sub),_)
equation
//this ASUB stuff occurs in the flattened DAE, check this special case because of removeSimpleEquations
exp = evaluateConstantFunctionCallExp(DAE.CALL(path=path, expLst=exps, attr=attr1), funcsIn, evalConstArgsOnly);
(exp,_) = ExpressionSimplify.simplify(DAE.ASUB(exp,sub));
if not Expression.isConst(exp) then exp = expIn; end if;
then exp;
else
// could not evaluate it
equation
then expIn;
end matchcontinue;
end evaluateConstantFunctionCallExp;
protected function hasUnknownType" true if one of the crefs in the exp is of unknown type.
author: vwaurich 2016-11"
input DAE.Exp eIn;
output Boolean bOut;
algorithm
bOut := match(eIn)
local
DAE.Type ty;
list<DAE.Exp> eLst;
case(DAE.TUPLE(PR = eLst))
algorithm
then List.mapBoolOr(eLst,hasUnknownType);
case(DAE.CREF(ty=DAE.T_UNKNOWN()))
then true;
else
then false;
end match;
end hasUnknownType;
protected function hasMultipleArrayDimensions
"outputs true if the expression type is an array with multiple dimensions."
input DAE.Exp eIn;
output Boolean bOut;
algorithm
bOut := match(eIn)
local
Boolean b;
DAE.Type ty;
list<DAE.Exp> eLst;
case(DAE.TUPLE(PR = eLst))
algorithm
then List.mapBoolOr(eLst,hasMultipleArrayDimensions);
case(DAE.CREF(ty=ty))
algorithm
if Types.isArray(ty) then
b := intNe(1, listLength(Types.getDimensionSizes(ty)));
else
b := false;
end if;
then b;
else
then false;
end match;
end hasMultipleArrayDimensions;
protected function doNotInline
"outputs true if the function should not be inlined."
input DAE.Function func;
output Boolean dontInline;
algorithm
dontInline := match(func)
case(DAE.FUNCTION(inlineType=DAE.NO_INLINE()))
then true;
else
then false;
end match;
end doNotInline;
public function evaluateConstantFunction "Analyses if the rhsExp is a function call. the constant inputs are inserted and it will be checked if the outputs can be evaluated to a constant.
If the function can be completely evaluated, the function call will be removed.
If its partially constant, the constant assignments are added as additional equations and the former function will be replaced with an updated new one.
author: Waurich TUD 2014-04"
input DAE.Exp rhsExpIn;
input DAE.Exp lhsExpIn;
input DAE.FunctionTree funcsIn;
input Integer eqIdx;
input list<CallSignature> callSignLstIn;
output tuple<DAE.Exp, DAE.Exp, list<BackendDAE.Equation>, DAE.FunctionTree,Integer,Boolean, list<CallSignature>> outTpl; //rhs,lhs,addEqs,funcTre,idx,haschanged
algorithm
outTpl := matchcontinue(rhsExpIn,lhsExpIn,funcsIn,eqIdx,callSignLstIn)
local
Boolean funcIsConst, funcIsPartConst, isConstRec, hasAssert, hasReturn, hasTerminate, hasReinit, abort, changed, isUnknownType, isNDimArray;
Integer idx;
list<Boolean> bList;
list<Integer> constIdcs;
Absyn.Path path;
BackendVarTransform.VariableReplacements repl;
HashTable2.HashTable ht;
DAE.CallAttributes attr1, attr2;
DAE.ComponentRef constCref, lhsCref;
DAE.Exp exp, exp2, constExp, outputExp;
DAE.Function func;
DAE.FunctionTree funcs;
DAE.Type ty, singleOutputType;
list<BackendDAE.Equation> constEqs;
list<DAE.ComponentRef> inputCrefs, outputCrefs, allInputCrefs, allOutputCrefs, constInputCrefs, constCrefs, varScalarCrefsInFunc, constScalarCrefsLhs,constComplexCrefs,varComplexCrefs,varScalarCrefs,constScalarCrefs;
list<DAE.Element> elements, algs, allInputs, protectVars, allOutputs, updatedVarOutputs, newOutputVars;
list<DAE.Exp> exps, expsIn, inputExps, complexExp, allInputExps, constInputExps, constExps, constComplexExps, constScalarExps, lhsExps, sub;
list<list<DAE.Exp>> scalarExp;
list<DAE.Statement> stmts;
list<DAE.Type> outputVarTypes;
list<String> outputVarNames;
list<list<DAE.ComponentRef>> scalarInputs, scalarOutputs;
CallSignature signature;
list<CallSignature> callSignLst;
Boolean continueEval;
case(DAE.CALL(path=path, expLst=expsIn, attr=attr1),_,_,_,callSignLst)
equation
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print("\nStart function evaluation of:\n"+ExpressionDump.printExpStr(lhsExpIn)+" := "+ExpressionDump.printExpStr(rhsExpIn)+"\n\n");
end if;
//------------------------------------------------
//Check if this particular call signature has been analysed before
//------------------------------------------------
//print(stringDelimitList(List.map(callSignLst,callSignatureStr),"\n"));
continueEval = checkCallSignatureForExp(rhsExpIn,callSignLst);
isUnknownType = hasUnknownType(lhsExpIn);
isNDimArray = hasMultipleArrayDimensions(lhsExpIn);
if not continueEval and Flags.isSet(Flags.EVAL_FUNC_DUMP) then print("THIS FUNCTION CALL WITH THIS SPECIFIC SIGNATURE CANNOT BE EVALUTED\n"); end if;
if not continueEval or isUnknownType or isNDimArray then fail(); end if;
//------------------------------------------------
//Collect all I/O Information for the function call
//------------------------------------------------
// get the elements of the function and the algorithms
SOME(func) = DAE.AvlTreePathFunction.get(funcsIn,path);
false = doNotInline(func);
elements = DAEUtil.getFunctionElements(func);
protectVars = List.filterOnTrue(elements,DAEUtil.isProtectedVar);
algs = List.filterOnTrue(elements,DAEUtil.isAlgorithm);
//algs = listAppend(protectVars,algs);
//print("elements: "+DAEDump.dumpElementsStr(elements)+"\n");
// some exceptions
if Flags.isSet(Flags.EVAL_FUNC_DUMP) and listEmpty(elements) then
print("Its a Record!\n");
false=true;
elseif Flags.isSet(Flags.EVAL_FUNC_DUMP) and (listEmpty(protectVars) and listEmpty(algs)) then
print("Its a Built-In!\n");
false=true;
end if;
false = listEmpty(elements); // its a record
false = listEmpty(algs); // its a built in function
// get the input exps from the call
exps = List.map2(expsIn, evaluateConstantFunctionCallExp, funcsIn, false);
scalarExp = List.map1(exps,expandComplexEpressions,funcsIn);//these exps are evaluated as well
allInputExps = List.flatten(scalarExp);
//print("allInputExps\n"+stringDelimitList(List.map(allInputExps,ExpressionDump.printExpStr),"\n")+"\n");
// get all input crefs (from function body) (scalar and one dimensioanl)
allInputs = List.filterOnTrue(elements,DAEUtil.isInputVar);
scalarInputs = List.map(allInputs,expandComplexElementsToCrefs);
allInputCrefs = List.flatten(scalarInputs);
//print("\nallInputCrefs\n"+stringDelimitList(List.map(allInputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
// get all output crefs (complex and scalar)
allOutputs = List.filterOnTrue(elements,DAEUtil.isOutputVar);
outputCrefs = List.map(allOutputs,DAEUtil.varCref);
scalarOutputs = List.map(allOutputs,getScalarsForComplexVar);
allOutputCrefs = listAppend(outputCrefs,List.flatten(scalarOutputs));
//print("\ncomplex OutputCrefs\n"+stringDelimitList(List.map(outputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("\nscalarOutputs\n"+stringDelimitList(List.map(List.flatten(scalarOutputs),ComponentReference.printComponentRefStr),"\n")+"\n");
// get the constant inputs
(constInputExps,constInputCrefs) = List.filterOnTrueSync(allInputExps,Expression.isConst,allInputCrefs);
//print("\nallInputExps\n"+stringDelimitList(List.map(allInputExps,ExpressionDump.printExpStr),"\n")+"\n");
//print("\nconstInputExps\n"+stringDelimitList(List.map(constInputExps,ExpressionDump.printExpStr),"\n")+"\n");
//print("\nconstInputCrefs\n"+stringDelimitList(List.map(constInputCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("\nall algs "+intString(listLength(algs))+"\n"+DAEDump.dumpElementsStr(algs)+"\n");
//------------------------------------------------
//evaluate function call
//------------------------------------------------
//build replacement rules
repl = BackendVarTransform.emptyReplacements();
repl = BackendVarTransform.addReplacements(repl,constInputCrefs,constInputExps,NONE());
//repl = BackendVarTransform.addReplacements(repl,allInputCrefs,allInputExps,NONE());
//BackendVarTransform.dumpReplacements(repl);
// recognize if there are statements we cannot evaluate at the moment
hasAssert = List.fold(algs,hasAssertFold,false);
hasReturn = List.fold(algs,hasReturnFold,false);
hasTerminate = List.fold(algs,hasReturnFold,false);
hasReinit = List.fold(algs,hasReinitFold,false);
abort = hasReturn or hasTerminate or hasReinit;
// go through all algorithms and replace the variables with constants if possible, extend the ht after each algorithm
(algs,funcs,repl,idx) = List.mapFold3(algs,evaluateFunctions_updateAlgElements,funcsIn,repl,eqIdx);
//print("\nall algs after"+intString(listLength(algs))+"\n"+DAEDump.dumpElementsStr(algs)+"\n");
//BackendVarTransform.dumpReplacements(repl);
//get all replacements in order to check for constant outputs
(constCrefs,constExps) = BackendVarTransform.getAllReplacements(repl);
(constCrefs,constExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,allOutputCrefs,constExps); // extract outputs
(constExps,constCrefs) = List.filterOnTrueSync(constExps,Expression.isConst,constCrefs); // extract constant outputs
//print("all constant crefs \n"+stringDelimitList(List.map(constCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("all constant exps:\n"+ExpressionDump.printExpListStr(constExps)+"\n");
// get the completely constant complex outputs, the constant parts of complex outputs and the variable parts of complex outputs and the expressions
(constComplexCrefs,varComplexCrefs,constScalarCrefs,varScalarCrefs) = checkIfOutputIsEvaluatedConstant(allOutputs,constCrefs,{},{},{},{});
(constScalarCrefs,constScalarExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,constScalarCrefs,constExps);
(constComplexCrefs,constComplexExps) = List.filter1OnTrueSync(constCrefs,ComponentReference.crefInLst,constComplexCrefs,constExps);
//print("constComplexCrefs\n"+stringDelimitList(List.map(constComplexCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("varComplexCrefs\n"+stringDelimitList(List.map(varComplexCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("constScalarCrefs\n"+stringDelimitList(List.map(constScalarCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//print("varScalarCrefs\n"+stringDelimitList(List.map(varScalarCrefs,ComponentReference.printComponentRefStr),"\n")+"\n");
//------------------------------------------------
//evaluate the result and build new function call accordingly
//------------------------------------------------
// is it completely constant or partially?
funcIsConst = listEmpty(varScalarCrefs) and listEmpty(varComplexCrefs) and (not listEmpty(constScalarCrefs) or not listEmpty(constComplexCrefs));
funcIsPartConst = ((not listEmpty(varScalarCrefs)) or (not listEmpty(varComplexCrefs))) and ((not listEmpty(constScalarCrefs)) or (not listEmpty(constComplexCrefs))) and not funcIsConst;
isConstRec = intEq(listLength(constScalarCrefs),listLength(List.flatten(scalarOutputs))) and listEmpty(varScalarCrefs) and listEmpty(varComplexCrefs) and listEmpty(constComplexCrefs);
//bcall1(isConstRec,print,"the function output is completely constant and its a record\n");
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
if funcIsConst then
if hasAssert then
print("the function output is completely constant but there is an assertion\n");
else
print("the function output is completely constant\n");
end if;
elseif not funcIsPartConst then
print("the function output is not constant in any case\n");
end if;
if abort then
print("the evaluated function is not used because there is a return or a terminate or a reinit statement\n");
end if;
end if;
funcIsConst = if (hasAssert and funcIsConst) or abort then false else funcIsConst; // quit if there is a return or terminate or use partial evaluation if there is an assert
funcIsPartConst = if hasAssert and funcIsConst then true else funcIsPartConst;
funcIsPartConst = if abort then false else funcIsPartConst; // quit if there is a return or terminate
true = funcIsPartConst or funcIsConst;
signature = getCallSignatureForCall(rhsExpIn);
signature.canBeEvaluated = true;
callSignLst = signature::callSignLst;
changed = funcIsPartConst or funcIsConst;
// build the new lhs, the new statements for the function, the constant parts...
(updatedVarOutputs,outputExp,varScalarCrefsInFunc) = buildVariableFunctionParts(scalarOutputs,constComplexCrefs,varComplexCrefs,constScalarCrefs,varScalarCrefs,allOutputs,lhsExpIn);
(constScalarCrefsLhs,constComplexCrefs) = buildConstFunctionCrefs(constScalarCrefs,constComplexCrefs,allOutputCrefs,lhsExpIn);
//print("constScalarExps\n"+stringDelimitList(List.map(constScalarExps,ExpressionDump.printExpStr),"\n")+"\n");
//print("constComplexExps\n"+stringDelimitList(List.map(constComplexExps,ExpressionDump.printExpStr),"\n")+"\n");
if not funcIsConst then
(algs,constEqs) = buildPartialFunction((varScalarCrefsInFunc,algs),(constScalarCrefs,constScalarExps,constComplexCrefs,constComplexExps,constScalarCrefsLhs),repl);
else
constEqs = {};
end if;
// build the new partial function
elements = listAppend(protectVars,algs);
elements = listAppend(updatedVarOutputs,elements);
elements = listAppend(allInputs,elements);
elements = List.unique(elements);
(func,path) = updateFunctionBody(func,elements,idx, updatedVarOutputs, allOutputs);
funcs = if funcIsPartConst then DAEUtil.addDaeFunction({func},funcs) else funcs;
idx = if funcIsPartConst or funcIsConst then (idx+1) else idx;
//decide which lhs to take (tuple or 1d)
outputExp = if funcIsPartConst then outputExp else lhsExpIn;
lhsExps = getCrefsForRecord(lhsExpIn);
outputExp = if isConstRec then DAE.TUPLE(lhsExps) else outputExp;
// which rhs
newOutputVars = List.filterOnTrue(updatedVarOutputs,DAEUtil.isOutputVar);
outputVarTypes = List.map(newOutputVars,DAEUtil.getVariableType);
outputVarNames = List.map(newOutputVars,DAEUtil.varName);
attr2 = DAEUtil.replaceCallAttrType(attr1,DAE.T_TUPLE(outputVarTypes,SOME(outputVarNames)));
DAE.CALL_ATTR(ty = singleOutputType) = attr1;
singleOutputType = if not listEmpty(newOutputVars) then listHead(outputVarTypes) else singleOutputType;//if the function is evaluated completely
attr1 = DAEUtil.replaceCallAttrType(attr1,singleOutputType);
attr2 = if intEq(listLength(newOutputVars),1) then attr1 else attr2;
//DAEDump.dumpCallAttr(attr2);
if List.hasOneElement(listAppend(constComplexExps,constScalarExps)) and funcIsConst then
exp = listHead(listAppend(constComplexExps,constScalarExps)); // either a single equation
elseif funcIsConst and not List.hasOneElement(listAppend(constComplexExps,constScalarExps)) then
exp = DAE.TUPLE(listAppend(constComplexExps,constScalarExps));// or a tuple equation
else
exp = rhsExpIn;
end if;
exp = if funcIsPartConst then DAE.CALL(path, expsIn, attr2) else exp; //its partially constant and we have to keep a function call to calc the rest
exp = if isConstRec then DAE.TUPLE(constScalarExps) else exp; // gather all constant record scalars in a tuple
outputExp = setRecordTypes(outputExp);
//BackendDump.dumpEquationList(constEqs,"the additional equations\n");
//print("LHS EXP:\n");
//ExpressionDump.dumpExp(outputExp);
//print("RHS EXP:\n");
//ExpressionDump.dumpExp(exp);
if Flags.isSet(Flags.EVAL_FUNC_DUMP) then
print("Finish evaluation:\n of: \n"+ExpressionDump.printExpStr(rhsExpIn)+"\nto:\n"+ExpressionDump.printExpStr(outputExp)+" := "+ExpressionDump.printExpStr(exp)+"\n");
if not listEmpty(constEqs) then
BackendDump.dumpEquationList(constEqs,"including the additional equations:\n");
end if;
end if;
then
((exp,outputExp,constEqs,funcs,idx,changed,callSignLst));
case(DAE.ASUB(DAE.CALL(path=path, expLst=exps, attr=attr1),sub),_,_,_,callSignLst)
equation
exp = DAE.CALL(path=path, expLst=exps, attr=attr1);
//Check if this particular call signature has been analysed before
continueEval = checkCallSignatureForExp(exp,callSignLst);
if not continueEval and Flags.isSet(Flags.EVAL_FUNC_DUMP) then print("THIS FUNCTION CALL WITH THIS SPECIFIC SIGNATURE CANNOT BE EVALUTED\n"); end if;
if not continueEval then fail(); end if;
//this ASUB stuff occurs in the flattened DAE, check this special case because of removeSimpleEquations
exp = evaluateConstantFunctionCallExp(exp,funcsIn, false);
(exp,_) = ExpressionSimplify.simplify(DAE.ASUB(exp,sub));
changed = true;
if not Expression.isConst(exp) then
exp = rhsExpIn;
changed=false;
end if;
then ((exp,lhsExpIn,{},funcsIn,eqIdx,changed,callSignLst));
else
equation
callSignLst = callSignLstIn;
if Expression.isCall(rhsExpIn) then
//Add a call signature for the call that could not been evaluated
signature = getCallSignatureForCall(rhsExpIn);
signature.canBeEvaluated = false;
if not List.isMemberOnTrue(signature,callSignLstIn,callSignatureIsEqual) then
callSignLst = signature::callSignLst;
end if;
end if;
then ((rhsExpIn,lhsExpIn,{},funcsIn,eqIdx,false,callSignLst));
end matchcontinue;
end evaluateConstantFunction;
protected function expandComplexEpressions "gets the complex contents or if its not complex, then the exp itself, if its a call, get the scalar outputs.
it would be possible to evaluate the exp before.
author:Waurich TUD 2014-05"
input DAE.Exp e;
input DAE.FunctionTree funcs;
output list<DAE.Exp> eLst;
algorithm
eLst := matchcontinue(e,funcs)
local
Absyn.Path path;
DAE.Function func;
list<DAE.Exp> lst;
list<DAE.Element> elements, allOutputs;
case(DAE.CALL(path=path, expLst=lst),_)
equation
SOME(func) = DAE.AvlTreePathFunction.get(funcs,path);
elements = DAEUtil.getFunctionElements(func);
if listEmpty(elements) then
// its a record
//eLst = lst;
else
// its a call, get the scalar outputs
SOME(func) = DAE.AvlTreePathFunction.get(funcs,path);
elements = DAEUtil.getFunctionElements(func);
allOutputs = List.filterOnTrue(elements,DAEUtil.isOutputVar);
lst = List.map(List.flatten(List.map(allOutputs,getScalarsForComplexVar)),Expression.crefExp);
end if;
then
lst;
case(_,_)
equation
lst = Expression.getComplexContents(e);
false = listEmpty(lst);
then
lst;
else
equation
//print("Could not scalarize EXP:\n");
//print(ExpressionDump.dumpExpStr(e,0)+"\n");
then {e};
end matchcontinue;
end expandComplexEpressions;
protected function expandComplexElementsToCrefs "gets the complex contents or if its not complex, then the element itself and converts them to crefs.
author:Waurich TUD 2014-05"
input DAE.Element e;
output list<DAE.ComponentRef> eLst;
algorithm
eLst := matchcontinue(e)
local
DAE.ComponentRef cref;
list<DAE.ComponentRef> lst;