Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 83.4% 281 / 0 / 337
Functions: -% 0 / 0 / 0
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/Template/CodegenCFunctions.tpl
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 // This file defines templates for transforming Modelica/MetaModelica code to C
37 // code. They are used in the code generator phase of the compiler to write
38 // target code.
39 //
40 // CodegenC.tpl has the root template translateModel while
41 // this template contains only translateFunctions.
42 // These templates do not return any
43 // result but instead write the result to files. All other templates return
44 // text and are used by the root templates (most of them indirectly).
45
46 package CodegenCFunctions
47
48 import interface SimCodeTV;
49 import CodegenUtil.*;
50 import ExpressionDumpTpl;
51
52 /* public */ template generateEntryPoint(Absyn.Path entryPoint, String url) "used in Compiler/Script/CevalScript.mo"
53 ::=
54 let name = ("omc_" + underscorePath(entryPoint))
55 <<
56 /* This is an automatically generated entry point to a MetaModelica function */
57
58 #if defined(__cplusplus)
59 extern "C" {
60 #endif
61
62 #if defined(OMC_ENTRYPOINT_STATIC)
63
64 #include <stdio.h>
65 #include <openmodelica.h>
66
67 DLLImport extern int __omc_main(int argc, char **argv);
68
69 int main(int argc, char **argv)
70 {
71 return __omc_main(argc, argv);
72 }
73
74 #else
75
76 #include <meta/meta_modelica.h>
77 #include <stdio.h>
78 extern void
79 #if defined(OMC_GENERATE_RELOCATABLE_CODE)
80 (*<%name%>)
81 #else
82 <%name%>
83 #endif
84 (threadData_t*,modelica_metatype);
85
86 #ifdef _OPENMP
87 #include<omp.h>
88 /* Hack to make gcc-4.8 link in the OpenMP runtime if -fopenmp is given */
89 int (*force_link_omp)(void) = omp_get_num_threads;
90 #endif
91
92 static int rml_execution_failed()
93 {
94 fflush(NULL);
95 fprintf(stderr, "Execution failed!\n");
96 fflush(NULL);
97 return 1;
98 }
99
100 DLLModelDirection int __omc_main(int argc, char **argv)
101 {
102 OMC_INIT(0);
103 {
104 void *lst = mmc_mk_nil();
105 int i = 0;
106
107 for (i=argc-1; i>0; i--) {
108 lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst);
109 }
110
111 <%mainTop('<%name%>(threadData, lst);',url)%>
112 }
113
114 <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %>
115 fflush(NULL);
116 EXIT(0);
117 return 0;
118 }
119
120 #endif
121
122 #if defined(__cplusplus)
123 } /* end extern "C" */
124 #endif
125
126 >>
127 end generateEntryPoint;
128
129 1264 template mainTop(Text mainBody, String url)
130 ::=
131 <<
132 {
133 OMC_TRY_TOP()
134
135 OMC_TRY_STACK()
136
137 <%mainBody%>
138
139 OMC_ELSE()
140 rml_execution_failed();
141 fprintf(stderr, "Stack overflow detected and was not caught.\nSend us a bug report at <%url%>\n Include the following trace:\n");
142 printStacktraceMessages();
143 fflush(NULL);
144 return 1;
145 OMC_CATCH_STACK()
146
147 OMC_CATCH_TOP(return rml_execution_failed());
148 }
149 >>
150 end mainTop;
151
152 /* public */ template translateFunctions(FunctionCode functionCode)
153 "Generates C code and Makefile for compiling and calling Modelica and
154 MetaModelica functions.
155 used in Compiler/SimCode/SimCodeMain.mo"
156 ::=
157 match functionCode
158 case fc as FUNCTIONCODE(__) then
159 let()= System.tmpTickResetIndex(0,2) /* auxFunction index */
160 let()= System.tmpTickResetIndex(0,20) /*parfor index*/
161 let &staticPrototypes = buffer ""
162 let filePrefix = name
163 let _= (if mainFunction then textFile(functionsMakefile(functionCode), '<%filePrefix%>.makefile'))
164 let()= textFile(functionsHeaderFile(filePrefix, mainFunction, functions, extraRecordDecls, staticPrototypes), '<%filePrefix%>.h')
165 let()= textFileConvertLines(functionsFile(filePrefix, mainFunction, functions, literals, staticPrototypes), '<%filePrefix%>.c')
166 let()= textFile(externalFunctionIncludes(fc.externalFunctionIncludes), '<%filePrefix%>_includes.h')
167 let()= textFile(recordsFile(filePrefix, extraRecordDecls, false /*isSimulation*/), '<%filePrefix%>_records.c')
168 // If ParModelica generate the kernels file too.
169 if acceptParModelicaGrammar() then
170 let()= textFile(functionsParModelicaKernelsFile(filePrefix, mainFunction, functions), '<%filePrefix%>_kernels.cl')
171 "" // Return empty result since result written to files directly
172 end match
173 end translateFunctions;
174
175 ✗ template translateFunctionHeaderFiles(FunctionCode functionCode)
176 ::=
177 match functionCode
178 case fc as FUNCTIONCODE(__) then
179 let()= System.tmpTickResetIndex(0,2) /* auxFunction index */
180 let()= System.tmpTickResetIndex(0,20) /*parfor index*/
181 let &staticPrototypes = buffer ""
182 let filePrefix = name
183 let _= (if mainFunction then textFile(functionsMakefile(functionCode), '<%filePrefix%>.makefile'))
184 let()= textFile(functionsHeaderFile(filePrefix, mainFunction, functions, extraRecordDecls, staticPrototypes), '<%filePrefix%>.h')
185 let()= textFile(externalFunctionIncludes(fc.externalFunctionIncludes), '<%filePrefix%>_includes.h')
186 let()= textFile(recordsFile(filePrefix, extraRecordDecls, false /*isSimulation*/), '<%filePrefix%>_records.c')
187 "" // Return empty result since result written to files directly
188 end match
189 end translateFunctionHeaderFiles;
190
191 142 template functionsFile(String filePrefix,
192 Option<SimCodeFunction.Function> mainFunction,
193 list<SimCodeFunction.Function> functions,
194 list<Exp> literals,
195 Text &staticPrototypes)
196 "Generates the contents of the main C file for the function case."
197 ::=
198 <<
199 #include "omc_simulation_settings.h"
200 #include "<%filePrefix%>.h"
201 <% /* Note: The literals may not be part of the header due to separate compilation */
202 literals |> literal hasindex i0 fromindex 0 => literalExpConst(literal,i0) ; separator="\n";empty
203 %>
204 #include "util/modelica.h"
205
206 #include "<%filePrefix%>_includes.h"
207
208 <%if acceptParModelicaGrammar() then
209 <<
210 /* the OpenCL Kernels file name needed in libParModelicaExpl.a */
211 const char* omc_ocl_kernels_source = "<%filePrefix%>_kernels.cl";
212 /* the OpenCL program. Made global to avoid repeated builds */
213 extern cl_program omc_ocl_program;
214 /* The default OpenCL device. If not set (=0) show the selection option.*/
215 unsigned int default_ocl_device = <%getDefaultOpenCLDevice()%>;
216 >>
217 %>
218
219 <%if staticPrototypes then
220 <<
221 /* default, do not make protected functions static */
222 #if !defined(PROTECTED_FUNCTION_STATIC)
223 #define PROTECTED_FUNCTION_STATIC
224 #endif
225 <%staticPrototypes%>
226 >>
227 %>
228
229 <%match mainFunction case SOME(fn) then functionBody(fn,true,false)%>
230 <%functionBodies(functions,false)%>
231 <%\n%>
232 >>
233 end functionsFile;
234
235 142 template functionsHeaderFile(String filePrefix,
236 Option<SimCodeFunction.Function> mainFunction,
237 list<SimCodeFunction.Function> functions,
238 list<RecordDeclaration> extraRecordDecls,
239 Text &staticPrototypes)
240 "Generates the contents of the main C file for the function case."
241 ::=
242 <<
243 #ifndef <%makeC89Identifier(filePrefix)%>__H
244 #define <%makeC89Identifier(filePrefix)%>__H
245 <%commonHeader(filePrefix)%>
246 #ifdef __cplusplus
247 extern "C" {
248 #endif
249
250 <%extraRecordDecls |> rd => recordDeclarationHeader(rd) ;separator="\n"%>
251
252 <%match mainFunction case SOME(fn) then functionHeader(fn,true,false,staticPrototypes)%>
253
254 <%functionHeaders(functions, false, staticPrototypes)%>
255
256 #ifdef __cplusplus
257 }
258 #endif
259 #endif<%\n%>
260 >>
261 /* adrpo: leave a newline at the end of file to get rid of the warning */
262 end functionsHeaderFile;
263
264 142 template functionsMakefile(FunctionCode fnCode)
265 "Generates the contents of the makefile for the function case."
266 ::=
267 match getGeneralTarget(Config.simulationCodeTarget())
268 case "msvc" then
269 match fnCode
270 case FUNCTIONCODE(makefileParams=MAKEFILE_PARAMS(__)) then
271 let libsStr = (makefileParams.libs ;separator=" ")
272 <<
273 # Makefile generated by OpenModelica
274 # Platform: <%makefileParams.platform%>
275 #
276 # For nmake. share/omc/scripts/Compile.bat sets the toolchain up and can
277 # override CC (OMC_TOOLCHAIN=clang-cl).
278
279 CC=cl
280 OMHOME=<%makefileParams.omhome%>
281 OMLIB=$(OMHOME)/lib/<%Config.targetTriple()%>/omc
282 CFLAGS=/nologo /MD /std:c17 /Od /wd4068 /DOM_HAVE_PTHREADS /DIMPORT_INTO
283 CPPFLAGS=<%makefileParams.includes ; separator=" "%> /I"$(OMHOME)/include/omc/c" /I"$(OMHOME)/include/omc"<%
284 if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then " /DOMC_GENERATE_RELOCATABLE_CODE"
285 %>
286 LDFLAGS=/link /STACK:16777216 /LIBPATH:"$(OMLIB)" <%libsStr%> <%if metaModelicaRuntime() then "OpenModelicaCompiler.lib"%> <%makefileParams.runtimelibs%>
287
288 <%name%>: <%name%>.c <%name%>.h <%name%>_records.c
289 <%\t%>$(CC) /LD $(CFLAGS) $(CPPFLAGS) /Fe<%name%><%makefileParams.dllext%> <%name%>.c <%name%>_records.c $(LDFLAGS)
290 >>
291 end match
292 else
293 match fnCode
294 case FUNCTIONCODE(makefileParams=MAKEFILE_PARAMS(__)) then
295 let libsStr = (makefileParams.libs ;separator=" ")
296 let ParModelicaExpLibs = if acceptParModelicaGrammar() then '-lParModelicaExpl -lOpenCL' // else ""
297 let ExtraStack = if boolOr(stringEq(makefileParams.platform, "win32"),stringEq(makefileParams.platform, "win64")) then '--stack,16777216,'
298 let WinMingwExtraLibs = if metaModelicaRuntime() then (if boolOr(stringEq(makefileParams.platform, "win32"),stringEq(makefileParams.platform, "win64")) then '-lOpenModelicaCompiler')
299
300 <<
301 # Makefile generated by OpenModelica
302 # Platform: <%makefileParams.platform%>
303
304 # Dynamic loading uses -O0 by default
305 # define OMC_CFLAGS_OPTIMIZATION env variable to your desired optimization level to override this
306 OMC_CFLAGS_OPTIMIZATION=-O0
307 SIM_OR_DYNLOAD_OPT_LEVEL=$(OMC_CFLAGS_OPTIMIZATION)
308 CC=<%if acceptParModelicaGrammar() then 'g++' else '<%makefileParams.ccompiler%>'%>
309 CXX=<%makefileParams.cxxcompiler%>
310 LINK=<%makefileParams.linker%>
311 EXEEXT=<%makefileParams.exeext%>
312 DLLEXT=<%makefileParams.dllext%>
313 DEBUG_FLAGS=<% if Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then " -g" else "$(SIM_OR_DYNLOAD_OPT_LEVEL)" %>
314 CFLAGS= $(DEBUG_FLAGS) <%makefileParams.cflags%>
315 CPPFLAGS= <%makefileParams.includes ; separator=" "%> -I"<%makefileParams.omhome%>/include/omc/c" -I"<%makefileParams.omhome%>/include/omc" <%
316 if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then " -DOMC_GENERATE_RELOCATABLE_CODE"
317 %>
318 # define OMC_LDFLAGS_LINK_TYPE env variable to "static" to override this
319 OMC_LDFLAGS_LINK_TYPE=dynamic
320 RUNTIME_LIBS=<%makefileParams.runtimelibs%>
321 LDFLAGS= -L"<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc" -Wl,<%ExtraStack%>-rpath,'<%makefileParams.omhome%>/lib/<%Config.targetTriple()%>/omc' <%ParModelicaExpLibs%> <%WinMingwExtraLibs%> <%makefileParams.ldflags%> $(RUNTIME_LIBS)
322 PERL=perl
323 MAINFILE=<%name%>.c
324
325 .PHONY: <%name%>
326 <%name%>: $(MAINFILE) <%name%>.h <%name%>_records.c
327 <%\t%> $(CC) $(CFLAGS) $(CPPFLAGS) -c -o <%name%>.o $(MAINFILE)
328 <%\t%> $(CC) $(CFLAGS) $(CPPFLAGS) -c -o <%name%>_records.o <%name%>_records.c
329 <%\t%> $(LINK) -o <%name%>$(DLLEXT) <%name%>.o <%name%>_records.o <%libsStr%> $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -lm
330 >>
331 end match
332 end functionsMakefile;
333
334 1346 template commonHeader(String filePrefix)
335 ::=
336 <<
337 <%if metaModelicaRuntime() then '#include "meta/meta_modelica.h"'%>
338 #include "util/modelica.h"
339 #include <stdio.h>
340 #include <stdlib.h>
341 #include <errno.h>
342 <%if acceptParModelicaGrammar() then
343 <<
344 #include <ParModelica/explicit/openclrt/omc_ocl_interface.h>
345 >>
346 %>
347
348 >>
349 end commonHeader;
350
351
352 /* public */ template externalFunctionIncludes(list<String> includes)
353 "Generates external includes part in function files.
354 used in Compiler/Template/CodegenFMU.tpl.
355 Include openmodelica.h, because some Modelica libraries test if some tool depedent variable is set, e.g. TILMedia."
356 ::=
357 if includes then
358 <<
359 #ifdef __cplusplus
360 extern "C" {
361 #endif
362 #include "openmodelica.h" // Defines OPENMODELICA_H_ for libraries to test if called from OpenModelica.
363 #include "ModelicaUtilities.h" // Make Modelica C util functions available for external includes.
364
365 <% (includes ;separator="\n") %>
366 #ifdef __cplusplus
367 }
368 #endif<%\n%>
369 >>
370 end externalFunctionIncludes;
371
372 1346 template functionHeaders(list<SimCodeFunction.Function> functions, Boolean isSimulation, Text &staticPrototypes)
373 "Generates function header part in function files."
374 ::=
375 (functions |> fn => functionHeader(fn, false, isSimulation, staticPrototypes) ; separator="\n\n")
376 end functionHeaders;
377
378 ✗ template functionHeadersParModelica(String filePrefix, list<SimCodeFunction.Function> functions)
379 "Generates the content of the C file for functions in the simulation case."
380 ::=
381 <<
382 #ifndef <%makeC89Identifier(filePrefix)%>__H
383 #define <%makeC89Identifier(filePrefix)%>__H
384 //#include "helper.cl"
385
386 <%parallelFunctionHeadersImpl(functions)%>
387
388 #endif
389
390 <%\n%>
391 >>
392 /* adrpo: leave a newline at the end of file to get rid of the warning */
393 end functionHeadersParModelica;
394
395 ✗ template parallelFunctionHeadersImpl(list<SimCodeFunction.Function> functions)
396 "Generates function header part in function files."
397 ::=
398 (functions |> fn => parallelFunctionHeader(fn, false) ; separator="\n\n")
399 end parallelFunctionHeadersImpl;
400
401 7653 template functionHeader(SimCodeFunction.Function fn, Boolean inFunc, Boolean isSimulation, Text &staticPrototypes)
402 "Generates function header part in function files."
403 ::=
404 match fn
405 case FUNCTION(__) then
406 <<
407 <%functionHeaderNormal(underscorePath(name), functionArguments, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%>
408 <%if not funcHasParallelInOutArrays(fn) then functionHeaderBoxed(underscorePath(name), functionArguments, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%>
409 >>
410 case KERNEL_FUNCTION(__) then
411 <<
412 <%functionHeaderKernelFunctionInterface(underscorePath(name), functionArguments, outVars)%>
413 >>
414 case EXTERNAL_FUNCTION(dynamicLoad=true) then
415 <<
416 <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, true, isSimulation, staticPrototypes)%>
417 <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, true, isSimulation, staticPrototypes)%>
418
419 <%extFunDefDynamic(fn)%>
420 >>
421 case EXTERNAL_FUNCTION(__) then
422 <<
423 <%functionHeaderNormal(underscorePath(name), funArgs, outVars, inFunc, visibility, false, isSimulation, staticPrototypes)%>
424 <%functionHeaderBoxed(underscorePath(name), funArgs, outVars, inFunc, isBoxedFunction(fn), visibility, false, isSimulation, staticPrototypes)%>
425
426 <%extFunDef(fn)%>
427 >>
428 case RECORD_CONSTRUCTOR(__) then
429 let fname = underscorePath(name)
430 let funArgsStr = (funArgs |> var as VARIABLE(__) => ', <%varType(var)%> omc_<%CodegenUtil.crefStr(name)%>')
431 let vis = (match visibility case PUBLIC() then "DLLModelDirection")
432 <<
433 <% if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)
434 then
435 <<
436 typedef <%fname%> (*omctd_<%fname%>)(threadData_t *threadData<%funArgsStr%>);
437 <%vis%>
438 omctd_<%fname%> omc_<%fname%>;
439 >>
440 else
441 <<
442 <%vis%>
443 <%fname%> omc_<%fname%> (threadData_t *threadData<%funArgsStr%>);
444 >>
445 %>
446
447 <%functionHeaderBoxed(fname, funArgs, boxedRecordOutVars, inFunc, false, visibility, false, isSimulation, staticPrototypes)%>
448 >>
449 end functionHeader;
450
451 ✗ template parallelFunctionHeader(SimCodeFunction.Function fn, Boolean inFunc)
452 "Generates function header part in function files."
453 ::=
454 match fn
455 case PARALLEL_FUNCTION(__) then
456 <<
457 <%functionHeaderParallelImpl(underscorePath(name), functionArguments, outVars, inFunc, false)%>;
458 >>
459 end parallelFunctionHeader;
460
461 ✗ template functionHeaderParallelImpl(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean boxed)
462 "Generates parmodelica paralell function header part in kernels files."
463 ::=
464 let fargsStr = (fargs |> var => funArgDefinitionKernelFunctionInterface(var) ;separator=", ")
465 // let &fargsStr += if outVars then ", " + (outVars |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ")
466 // 'void omc_<%fname%>(<%fargsStr%>)'
467
468 match outVars
469 case {} then
470 'void omc_<%fname%>(<%fargsStr%>)'
471
472 case fvar::rest then
473 let rettype = varType(fvar)
474 let &fargsStr += if rest then ", " + (rest |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ")
475 '<%rettype%> omc_<%fname%>(<%fargsStr%>)'
476
477 else
478 error(sourceInfo(), 'functionHeaderParallelImpl failed')
479 end functionHeaderParallelImpl;
480
481 17363 template recordDeclaration(RecordDeclaration recDecl)
482 "Generates structs for a record declaration."
483 ::=
484 match recDecl
485 case r as RECORD_DECL_FULL(__) then
486 <<
487 <%recordDefinition(dotPath(defPath),
488 underscorePath(defPath),
489 (variables |> VARIABLE(__) => '"<%CodegenUtil.crefStr(name)%>"' ;separator=","),
490 listLength(variables))%>
491
492 <%recordConstructorDef(r.name, r.name, r.variables)%>
493 <%recordCreateFromVarsDef(r.name, r.variables)%>
494
495 <%recordCopyDef(r.name, r.variables)%>
496 <%if boolNot(SimCodeFunctionUtil.isTrivialRecord(r.name)) then
497 <<
498 <%recordReleaseDef(r.name, r.variables)%>
499 <%recordRetainDef(r.name, r.variables)%>
500 <%recordDisownDef(r.name, r.variables)%>
501 >>
502 %>
503 <%if r.usedExternally then recordCopyExternalDefs(r.name, r.variables)%>
504 >>
505 case r as RECORD_DECL_ADD_CONSTRCTOR(__) then
506 <<
507 <%recordConstructorDef(r.ctor_name, r.name, r.variables)%>
508 >>
509 case r as RECORD_DECL_DEF(__) then
510 <<
511 <%recordDefinition(dotPath(r.path),
512 underscorePath(r.path),
513 (r.fieldNames |> fname => '"<%fname%>"' ;separator=","),
514 listLength(r.fieldNames))%>
515 >>
516 end recordDeclaration;
517
518 17363 template recordDeclarationHeader(RecordDeclaration recDecl)
519 "Generates structs for a record declaration."
520 ::=
521 match recDecl
522 case r as RECORD_DECL_FULL(__) then recordDeclarationFullHeader(r)
523 case r as RECORD_DECL_ADD_CONSTRCTOR(__) then recordDeclarationExtraCtor(r)
524 // TODO revise me
525 case r as RECORD_DECL_DEF(__) then 'extern struct record_description <%underscorePath(r.path)%>__desc;<%\n%>'
526 end recordDeclarationHeader;
527
528 18 template recordDeclarationExtraCtor(RecordDeclaration recDecl)
529 "Generates structs for a extra record declaration. An extra
530 record declration is a constructor with some of its elements provided
531 from outside. Modelica puts a lot of freedom on record creation. You can
532 generally provide none, some or all elements to create a record without
533 providing a single constructor. Which means a record with N elements
534 can have 2^N possible constructions.
535 e.g.,
536 record R
537 Real a=1,b=1,c=1;
538 end R;
539 R r1(a=2);
540 R r2(a=3,c=4);
541 ....
542
543 These will be created by additional constructors:
544 R_1_construct(r1,2);
545 R_1_3_construct(r2,3,4);
546 ...
547
548 Do not worry, these are created once for every use case and ONLY if they
549 are actually used by something."
550 ::=
551 match recDecl
552 case r as RECORD_DECL_ADD_CONSTRCTOR(__) then
553 let ctor_name = r.ctor_name
554 let rec_name = r.name
555
556 let ctor_macro_name = '<%ctor_name%>_construct'
557 let ctor_macro_additional_inputs = (r.variables |> var as VARIABLE(__) => if var.bind_from_outside
558 then (", " + "in_" + CodegenUtil.crefStr(var.name))
559 )
560 let ctor_func_name = '<%ctor_macro_name%>_p'
561 let ctor_additional_inputs = (r.variables |> var as VARIABLE(__) => if var.bind_from_outside
562 then (", " + varType(var) + " in_" + CodegenUtil.crefStr(var.name))
563 )
564 <<
565 void <%ctor_func_name%>(threadData_t *threadData, void* v_ths <%ctor_additional_inputs%>);
566 #define <%ctor_macro_name%>(td, ths <%ctor_macro_additional_inputs%>) <%ctor_func_name%>(td, &ths <%ctor_macro_additional_inputs%>)
567
568 #define alloc_<%ctor_name%>_array(dst,ndims,...) generic_array_create(threadData, dst, <%ctor_func_name%>, ndims, sizeof(<%rec_name%>), __VA_ARGS__)
569 >>
570 end recordDeclarationExtraCtor;
571
572 4269 template recordDeclarationFullHeader(RecordDeclaration recDecl)
573 "Generates structs for a record declaration. This will generate
574 a default record constructor function (no arguments) and a record copy function.
575 These generated functions are fully recursive. That means records in records
576 will be handled properly.
577 It will also generate (#define) array versions of these functions."
578 ::=
579 match recDecl
580 case r as RECORD_DECL_FULL(__) then
581 let rec_name = r.name
582
583 let ctor_macro_name = '<%rec_name%>_construct'
584 let ctor_macro_additional_inputs = (r.variables |> var as VARIABLE(__) => if var.bind_from_outside
585 then (", " + "in_" + CodegenUtil.crefStr(var.name))
586 )
587 let ctor_func_name = '<%ctor_macro_name%>_p'
588 let ctor_additional_inputs = (r.variables |> var as VARIABLE(__) => if var.bind_from_outside
589 then (", " + varType(var) + " in_" + CodegenUtil.crefStr(var.name))
590 )
591
592 let cpy_macro_name = '<%rec_name%>_copy'
593 let cpy_func_name = '<%cpy_macro_name%>_p'
594
595 let release_macro_name = '<%rec_name%>_release'
596 let release_func_name = '<%release_macro_name%>_p'
597 let retain_macro_name = '<%rec_name%>_retain'
598 let retain_func_name = '<%retain_macro_name%>_p'
599 let disown_macro_name = '<%rec_name%>_disown'
600 let disown_func_name = '<%disown_macro_name%>_p'
601
602 let cpy_to_external_macro_name = '<%rec_name%>_copy_to_external'
603 let cpy_to_external_func_name = '<%cpy_to_external_macro_name%>_p'
604 let cpy_from_external_macro_name = '<%rec_name%>_copy_from_external'
605 let cpy_from_external_func_name = '<%cpy_from_external_macro_name%>_p'
606
607 let copy_to_vars_name = '<%rec_name%>_copy_to_vars'
608 let copy_to_vars_name_p = '<%copy_to_vars_name%>_p'
609 let copy_to_vars_inputs = r.variables |> var as VARIABLE(__) => (", " + varType(var) + "* in_" + CodegenUtil.crefStr(var.name))
610
611 let wrap_vars_macro_name = '<%rec_name%>_wrap_vars'
612 let wrap_vars_func_name = '<%wrap_vars_macro_name%>_p'
613 let wrap_vars_macro_inputs = r.variables |> var as VARIABLE(__) => (", " + "in_" + CodegenUtil.crefStr(var.name))
614 let wrap_vars_func_inputs = r.variables |> var as VARIABLE(__) => (", " + varType(var) + " in_" + CodegenUtil.crefStr(var.name))
615
616 <<
617 <% match aliasName
618 case SOME(str) then
619 <<
620 typedef <%str%> <%rec_name%>;
621 <% if r.usedExternally then
622 <<
623 typedef <%str%>_external <%rec_name%>_external;
624 >>
625 %>
626 >>
627 else
628 <<
629 typedef struct {
630 <%r.variables |> var as VARIABLE(__) => '<%varType(var)%> _<%CodegenUtil.crefStr(var.name)%>;' ;separator="\n"%>
631 } <%rec_name%>;
632 <% if r.usedExternally then
633 <<
634 typedef struct {
635 <%r.variables |> var as VARIABLE(__) => '<%extType(var.ty, true, false, false)%> _<%CodegenUtil.crefStr(var.name)%>;' ;separator="\n"%>
636 } <%rec_name%>_external;
637 >>
638 %>
639 >>
640 %>
641 extern struct record_description <%underscorePath(r.defPath)%>__desc;
642
643 void <%ctor_func_name%>(threadData_t *threadData, void* v_ths <%ctor_additional_inputs%>);
644 #define <%ctor_macro_name%>(td, ths <%ctor_macro_additional_inputs%>) <%ctor_func_name%>(td, &ths <%ctor_macro_additional_inputs%>)
645 void <%cpy_func_name%>(void* v_src, void* v_dst);
646 #define <%cpy_macro_name%>(src,dst) <%cpy_func_name%>(&src, &dst)
647
648 <%if r.usedExternally then
649 <<
650 void <%cpy_to_external_func_name%>(void* v_src, void* v_dst);
651 #define <%cpy_to_external_macro_name%>(src,dst) <%cpy_to_external_func_name%>(&src, &dst)
652 void <%cpy_from_external_func_name%>(void* v_src, void* v_dst);
653 #define <%cpy_from_external_macro_name%>(src,dst) <%cpy_from_external_func_name%>(&src, &dst)
654 >>
655 %>
656
657 void <%wrap_vars_func_name%>(threadData_t *threadData , void* v_dst <%wrap_vars_func_inputs%>);
658 #define <%wrap_vars_macro_name%>(td, dst <%wrap_vars_macro_inputs%>) <%wrap_vars_func_name%>(td, &dst <%wrap_vars_macro_inputs%>)
659
660 <%if SimCodeFunctionUtil.isTrivialRecord(rec_name) then
661 <<
662 #define <%release_macro_name%>(ths) ((void)0)
663 #define <%retain_macro_name%>(ths) ((void)0)
664 #define <%disown_macro_name%>(ths) ((void)0)
665 >>
666 else
667 <<
668 void <%release_func_name%>(void* v_ths);
669 #define <%release_macro_name%>(ths) <%release_func_name%>(&ths)
670 void <%retain_func_name%>(void* v_ths);
671 #define <%retain_macro_name%>(ths) <%retain_func_name%>(&ths)
672 void <%disown_func_name%>(void* v_ths);
673 #define <%disown_macro_name%>(ths) <%disown_func_name%>(&ths)
674 >>
675 %>
676
677 // This function is not needed anymore. If you want to know how a record
678 // is 'assigned to' in simulation context see assignRhsExpToRecordCrefSimContext and
679 // splitRecordAssignmentToMemberAssignments (simCode). Basically the record is
680 // split up assignments generated for each member individually.
681 // void <%copy_to_vars_name_p%>(void* v_src <%copy_to_vars_inputs%>);
682 // #define <%copy_to_vars_name%>(src,...) <%copy_to_vars_name_p%>(&src, __VA_ARGS__)
683
684 typedef base_array_t <%rec_name%>_array;
685 #define alloc_<%rec_name%>_array(dst,ndims,...) generic_array_create(threadData, dst, <%ctor_func_name%>, ndims, sizeof(<%rec_name%>), __VA_ARGS__)
686 #define <%rec_name%>_array_copy_data(src,dst) generic_array_copy_data(src, &dst, <%cpy_func_name%>, sizeof(<%rec_name%>))
687 #define <%rec_name%>_array_alloc_copy(src,dst) generic_array_alloc_copy(src, &dst, <%cpy_func_name%>, sizeof(<%rec_name%>))
688 #define <%rec_name%>_array_get(src,ndims,...) (*(<%rec_name%>*)(generic_array_get(&src, sizeof(<%rec_name%>), __VA_ARGS__)))
689 #define <%rec_name%>_array_get1(src,ndims,dim1) (((<%rec_name%>*)(src).data)[omc_array_index1((src), (dim1))])
690 #define <%rec_name%>_array_get2(src,ndims,dim1,dim2) (((<%rec_name%>*)(src).data)[omc_array_index2((src), (dim1), (dim2))])
691 #define <%rec_name%>_set(dst,val,...) generic_array_set(&dst, &val, <%cpy_func_name%>, sizeof(<%rec_name%>), __VA_ARGS__)
692 #define <%rec_name%>_array_release(dst) <%if SimCodeFunctionUtil.isTrivialRecord(rec_name) then 'omc_array_release(&dst)' else 'omc_record_array_release(&dst, <%release_func_name%>, sizeof(<%rec_name%>))'%>
693 >>
694 end recordDeclarationFullHeader;
695
696 4269 template recordCopyDef(String rec_name, list<Variable> variables)
697 "Generates code for copying one instance of a record to another
698 instance of the same record type."
699 ::=
700 let &varCopies = buffer ""
701 let &auxFunction = buffer ""
702 let dst_pref = 'dst->'
703 let src_pref = 'src->'
704 let _ = (variables |> var => recordMemberCopy(var, src_pref, dst_pref, &varCopies, &auxFunction) ;separator="\n")
705 <<
706 void <%rec_name%>_copy_p(void* v_src, void* v_dst) {
707 <%rec_name%>* src = (<%rec_name%>*)(v_src);
708 <%rec_name%>* dst = (<%rec_name%>*)(v_dst);
709 <%varCopies%>
710 }
711 >>
712 end recordCopyDef;
713
714 2749 template recordReleaseDef(String rec_name, list<Variable> variables)
715 "Drops the references the members hold. Empty for a record of scalars."
716 ::=
717 let &auxFunction = buffer ""
718 let body = (variables |> var as VARIABLE(__) =>
719 rcRelease(varType(var), 'ths-><%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'))
720 <<
721 void <%rec_name%>_release_p(void* v_ths) {
722 <%if body then '<%rec_name%>* ths = (<%rec_name%>*)(v_ths);<%\n%><%body%>' else "(void) v_ths;"%>
723 }
724 >>
725 end recordReleaseDef;
726
727 2749 template recordRetainDef(String rec_name, list<Variable> variables)
728 "One more owner of every member. Empty for a record of scalars."
729 ::=
730 let &auxFunction = buffer ""
731 let body = (variables |> var as VARIABLE(__) =>
732 rcRetain(varType(var), 'ths-><%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'))
733 <<
734 void <%rec_name%>_retain_p(void* v_ths) {
735 <%if body then '<%rec_name%>* ths = (<%rec_name%>*)(v_ths);<%\n%><%body%>' else "(void) v_ths;"%>
736 }
737 >>
738 end recordRetainDef;
739
740 2749 template recordDisownDef(String rec_name, list<Variable> variables)
741 "See omc_string_disown: the caller took the record, so the release at _return:
742 must not find its members here."
743 ::=
744 let &auxFunction = buffer ""
745 let body = (variables |> var as VARIABLE(__) =>
746 rcDisown(varType(var), 'ths-><%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'))
747 <<
748 void <%rec_name%>_disown_p(void* v_ths) {
749 <%if body then '<%rec_name%>* ths = (<%rec_name%>*)(v_ths);<%\n%><%body%>' else "(void) v_ths;"%>
750 }
751 >>
752 end recordDisownDef;
753
754 2863 template recordCopyExternalDefs(String rec_name, list<Variable> variables)
755 "Generates code for copying a record to/from the extrenal C counterpart.
756 The external C counterpart of a record has data types set according to the
757 Modelica Standard. The main difference right now is Intger tyepes. In
758 OpenModelica Integer types are represented by 'long' a.k.a modelica_integer.
759 In the external counter part of the record they are 'int'. These functions
760 make sure the conversion is done using assigment (possiblly truncating values)
761 to make sure that the data is not interpreted wrong due to the size differences.
762 See #8591 for more info."
763 ::=
764 let &varCopiesTo = buffer ""
765 let &varCopiesFrom = buffer ""
766 let &auxFunction = buffer ""
767 let dst_pref = 'dst->'
768 let src_pref = 'src->'
769 let _ = (variables |> var => recordMemberCopyToFromExternal(var, src_pref, dst_pref, true, &varCopiesTo, &auxFunction) ;separator="\n")
770 let _ = (variables |> var => recordMemberCopyToFromExternal(var, src_pref, dst_pref, false, &varCopiesFrom, &auxFunction) ;separator="\n")
771 <<
772 void <%rec_name%>_copy_to_external_p(void* v_src, void* v_dst) {
773 <%rec_name%>* src = (<%rec_name%>*)(v_src);
774 <%rec_name%>_external* dst = (<%rec_name%>_external*)(v_dst);
775 <%varCopiesTo%>
776 }
777 void <%rec_name%>_copy_from_external_p(void* v_src, void* v_dst) {
778 <%rec_name%>_external* src = (<%rec_name%>_external*)(v_src);
779 <%rec_name%>* dst = (<%rec_name%>*)(v_dst);
780 <%varCopiesFrom%>
781 }
782 >>
783 end recordCopyExternalDefs;
784
785 4269 template recordCreateFromVarsDef(String rec_name, list<Variable> variables)
786 "Generates code for creating and initializing (shallow copies) a record given values for
787 ALL its members. This is used internally by the generated code to reconstruct
788 records from (the scattered) simulation member variables of the record. We do
789 this when we have to send a record used in equation context to a function.
790
791 Note that this is defferent from the constructors we have. This one expects
792 all the memebers to be already created (allocated and given values whatever the value is).
793 Its job is to 'wrap' these variables by a given record instance, e.g., so it can be sent to
794 functions from simulation code.
795 "
796 ::=
797 let &auxFunction = buffer ""
798 let dst_pref = 'dst->'
799 let src_pref = 'in'
800
801 let varCopies = (variables |> var => match var
802 case var as VARIABLE(__) then
803 let dstName = dst_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
804 let srcName = src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
805 // The wrapper outlives the expression that built it, so it takes its own
806 // references; only a counted record gets the zeroed declaration for that.
807 if rcKind(rec_name) then rcAssignRetain(varType(var), dstName, srcName)
808 else '<%dstName%> = <%srcName%>;<%\n%>'
809 else error(sourceInfo(), "recordCreateFromVarsDef: Unhandled variable type"))
810
811 let fn_inputs = (variables |> var as VARIABLE(__) =>
812 (", " + varType(var) + " " + src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction))
813 )
814
815 let ctor_additional_inputs = (variables |> var as VARIABLE(__) => if var.bind_from_outside
816 then (", " + "in_" + CodegenUtil.crefStr(var.name))
817 )
818 <<
819 void <%rec_name%>_wrap_vars_p(threadData_t *threadData, void* v_dst <%fn_inputs%>) {
820 <%rec_name%>* dst = (<%rec_name%>*)(v_dst);
821 <%varCopies%>
822 }
823 >>
824 end recordCreateFromVarsDef;
825
826 42660 template recordMemberCopy(Variable var, String src_pref, String dst_pref, Text &varCopies, Text &auxFunction)
827 "Generates code for copying memembers of a record during a record copy operation.
828 This function is needed because we need to have a 'localized' operation. Localized as
829 in references in these copy operations need to be resolved to other mememers of the
830 record. So we use prefixes (e.g. src->) to generate crefs in these operations."
831 ::=
832 match var
833 case var as VARIABLE(__) then
834 let dstName = dst_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
835 let srcName = src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
836
837 match ty
838 case ty as T_ARRAY(__) then
839 let varType = expTypeShort(ty)
840 let &varCopies += '<%varType%>_array_copy_data(<%srcName%>, <%dstName%>);<%\n%>'
841 ""
842 case ty as T_COMPLEX(complexClassType=RECORD(__)) then
843 let recType = expTypeShort(ty)
844 let &varCopies += '<%recType%>_copy(<%srcName%>, <%dstName%>);<%\n%>'
845 ""
846 else
847 let &varCopies += rcAssignRetain(varType(var), dstName, srcName)
848 ""
849
850 end match
851 end recordMemberCopy;
852
853 59698 template recordMemberCopyToFromExternal(Variable var, String src_pref, String dst_pref, Boolean copy_to, Text &varCopies, Text &auxFunction)
854 "Generates code for copying memembers of a record during a record copy to/from the version
855 of the record created for use with external C code.
856 Right now this does not support copying of array or record record memebers. It only handles
857 simple scalar assignments"
858 ::=
859 match var
860 case var as VARIABLE(__) then
861 let dstName = dst_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
862 let srcName = src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
863
864 match ty
865 case ty as T_ARRAY(__) then
866 let &varCopies += 'omc_assert(NULL, omc_dummyFileInfo, "Copying of array record members to/from external functions is not yet supported.");<%\n%>'
867 ""
868 case ty as T_STRING(__) then
869 let &varCopies += if copy_to then
870 '<%dstName%> = omc_string_data(<%srcName%>);<%\n%>'
871 else
872 'omc_assert(NULL, omc_dummyFileInfo, "Copying of string record members from external functions is not yet supported.");<%\n%>'
873 ""
874 case ty as T_COMPLEX(complexClassType=RECORD(__)) then
875 let recType = expTypeShort(ty)
876 let &varCopies += if copy_to then
877 '<%recType%>_copy_to_external(<%srcName%>, <%dstName%>);<%\n%>'
878 else
879 '<%recType%>_copy_from_external(<%srcName%>, <%dstName%>);<%\n%>'
880 ""
881 else
882 let &varCopies += '<%dstName%> = <%srcName%>;<%\n%>'
883 ""
884
885 end match
886 end recordMemberCopyToFromExternal;
887
888 4287 template recordConstructorDef(String ctor_name, String rec_name, list<Variable> variables)
889 "Generates code for constructing a record. This means allocating memory for all
890 members of the record and then initializing them with their default values. Sometimes
891 we can have modelica derived records (e.g. record A = B(c=exp)), this will be a new
892 record type whcih needs an exp to be passed to to be initialized correctly. This is
893 also handled by these function. Check markDerivedRecordOutsideBindings and makeTypeRecordVar
894 in the OF and NF respectively."
895 ::=
896 let &varDecls = buffer ""
897 let &varFrees = buffer ""
898 let &auxFunction = buffer ""
899 let ctor_additional_inputs = (variables |> var as VARIABLE(__) => if var.bind_from_outside
900 then (", " + varType(var) + " in" + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction))
901 )
902 let varInits = (variables |> var => recordMemberAllocInit(var, appendCurrentCrefPrefix(contextFunction, "ths->"), &varDecls, &varFrees, &auxFunction) /*;separator="\n"*/)
903 <<
904 void <%ctor_name%>_construct_p(threadData_t *threadData, void* v_ths <%ctor_additional_inputs%>) {
905 <%rec_name%>* ths = (<%rec_name%>*)(v_ths);
906 <%varDecls%>
907 <%varInits%>
908 _return: OMC_LABEL_UNUSED ;
909 <%varFrees%>
910 }
911 >>
912 end recordConstructorDef;
913
914 42697 template recordMemberAllocInit(Variable var, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
915 ::=
916 match var
917 case var as VARIABLE(__) then
918
919 match var.ty
920 case ty as T_ARRAY(__) then arrayVarAllocInit(var.name, var.ty, ty.dims, var.value, var.bind_from_outside, var.kind, context, &varDecls, &varFrees, &auxFunction)
921
922 case ty as T_COMPLEX(complexClassType=RECORD(__)) then recordVarAllocInit(var.value, var.name, var.bind_from_outside, var.ty, context, &varDecls, &varFrees, &auxFunction)
923
924 else
925 // Unlike a local, a member is not declared with an initialiser, so the
926 // store below would release whatever the stack left in the slot.
927 let zero = rcZeroAssign(varType(var), contextCrefNoPrevExp(var.name, context, &auxFunction))
928 '<%zero%><%simpleVarInit(varType(var), var.value, var.name, var.bind_from_outside, context, &varDecls, &varFrees, &auxFunction)%>'
929 end match
930 end recordMemberAllocInit;
931
932 75909 template simpleVarInit(String ty, Option<Exp> value, ComponentRef var_cref, Boolean bind_outside, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
933 ::=
934 let var_name = contextCrefNoPrevExp(var_cref, context, &auxFunction)
935
936 match value
937 case SOME(rhs_exp) then
938 let &preExp = buffer ""
939 let rhs = if bind_outside then "in" + contextCrefNoPrevExp(var_cref, contextFunction /*unprefixed context*/, &auxFunction)
940 else daeExp(rhs_exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
941 <<
942 <%preExp%>
943 <%rcAssignRetain(ty, var_name, rhs)%>
944 >>
945 case NONE() then
946 '// <%var_name%> has no default value.<%\n%>'
947 end match
948
949 end simpleVarInit;
950
951 3827 template recordVarAllocInit(Option<Exp> value, ComponentRef var_cref, Boolean bind_outside, Type var_type, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
952 ::=
953 let &preExp = buffer ""
954 let &ctor_suffix = buffer ""
955 let type_name = expTypeShort(var_type)
956 let var_name = contextCrefNoPrevExp(var_cref, context, &auxFunction)
957
958 let ctor_additional_inputs = match var_type
959 case ty as DAE.T_COMPLEX() then
960 (ty.varLst |> sv hasindex i1 fromindex 1 =>
961 recordInitOutsideBindings(sv, i1, &ctor_suffix, context, &preExp, &varDecls, &varFrees, &auxFunction); empty /* increase the counter! */
962 )
963 end match
964
965 let allocation = '<%type_name%><%ctor_suffix%>_construct(threadData, <%var_name%><%ctor_additional_inputs%>);'
966
967 match value
968 case SOME(rhs_exp) then
969 let &preExp1 = buffer ""
970 let copy_stmt = if bind_outside then
971 let in_var_name = "in" + contextCrefNoPrevExp(var_cref, contextFunction /*unprefixed context*/, &auxFunction)
972 '<%type_name%>_copy(<%in_var_name%>, <%var_name%>);'
973 else
974 assignRhsExpToRecordCref(var_cref, rhs_exp, var_type, context, &preExp1, &varDecls, &varFrees, &auxFunction)
975 <<
976 <%preExp%>
977 <%allocation%>
978 <%preExp1%>
979 <%copy_stmt%>;
980
981 >>
982 case NONE() then
983 <<
984 <%preExp%>
985 <%allocation%> // <%var_name%> has no default value.<%\n%>
986 >>
987 end match
988
989 end recordVarAllocInit;
990
991 80 template recordInitOutsideBindings(DAE.Var subvar, Integer ix, Text& ctor_suffix, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
992 ::=
993 match subvar
994 case TYPES_VAR(binding=EQBOUND(exp=exp), bind_from_outside = true) then
995 let &ctor_suffix += "_" + ix
996 ", " + daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
997 case TYPES_VAR(bind_from_outside = true) then
998 error(sourceInfo(), 'Record has binding from outside but found a non EQBOUND binding. Implement me.')
999 end match
1000 end recordInitOutsideBindings;
1001
1002 11957 template arrayVarConstLiteralAlias(DAE.VarKind var_kind, Option<DAE.Exp> value, Boolean bind_outside, Text var_name, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
1003 "A Modelica `constant` array bound to a shared literal can never be assigned, so it can point
1004 straight at the literal instead of allocating a fresh copy of it on every call. Restricted to
1005 CONST on purpose: any other variability may be written to, and writing through a shared literal
1006 would hit read-only memory."
1007 ::=
1008 match var_kind
1009 case CONST(__) then
1010 if bind_outside then
1011 ""
1012 else
1013 (match value
1014 case SOME(lit as SHARED_LITERAL(__)) then
1015 let &preExp = buffer ""
1016 let litExp = daeExp(lit, context, &preExp, &varDecls, &varFrees, &auxFunction)
1017 '<%var_name%> = <%litExp%>; /* constant: alias the shared literal, no copy needed */<%\n%>'
1018 else "")
1019 else ""
1020 end arrayVarConstLiteralAlias;
1021
1022 11957 template arrayVarAllocInit(ComponentRef var_cref, Type var_type, list<DAE.Dimension> var_dims, Option<DAE.Exp> value, Boolean bind_outside, DAE.VarKind var_kind, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
1023 ::=
1024 let type_name = expTypeShort(var_type)
1025 let var_name = contextCrefNoPrevExp(var_cref, context, &auxFunction)
1026 let constAlias = arrayVarConstLiteralAlias(var_kind, value, bind_outside, var_name, context, &varDecls, &varFrees, &auxFunction)
1027
1028 if constAlias then constAlias else
1029 match value
1030 case SOME(rhs_exp) then
1031 let &preExpBind = buffer ""
1032 let rhs = if bind_outside then "in" + contextCrefNoPrevExp(var_cref, contextFunction /*unprefixed context*/, &auxFunction)
1033 else daeExp(rhs_exp, context, &preExpBind, &varDecls, &varFrees, &auxFunction)
1034
1035 if Expression.hasUnknownDims(var_dims) then
1036 <<
1037 <%preExpBind%>
1038 <%type_name%>_array_alloc_copy(<%rhs%>, <%var_name%>);
1039
1040 >>
1041 else
1042 let &preExpAlloc = buffer ""
1043 let dims_str = (var_dims |> dim => '(_index_t)<%dimension(dim, context, &preExpAlloc, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
1044 <<
1045 <%preExpAlloc%>
1046 alloc_<%type_name%>_array(&(<%var_name%>), <%listLength(var_dims)%>, <%dims_str%>);
1047 <%preExpBind%>
1048 <%type_name%>_array_copy_data(<%rhs%>, <%var_name%>);
1049
1050 >>
1051
1052 case NONE() then
1053 // If an array variable has unknown dimensions but does not have a default value (declaration binding)
1054 // then the variable is flexible. That means it can actually change its dimensions whenever it is
1055 // assigned to. Ya it is allowed :/
1056 if Expression.hasUnknownDims(var_dims) then
1057 <<
1058 generic_array_create_flexible(&<%var_name%>, <%listLength(var_dims)%>); // <%var_name%> has unknown size and no default value. It is flexible.<%\n%>
1059 >>
1060 else
1061 let &preExpAlloc = buffer ""
1062 let dims_str = (var_dims |> dim => '(_index_t)<%dimension(dim, context, &preExpAlloc, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
1063 <<
1064 <%preExpAlloc%>
1065 alloc_<%type_name%>_array(&(<%var_name%>), <%listLength(var_dims)%>, <%dims_str%>); // <%var_name%> has no default value.<%\n%>
1066 >>
1067 end match
1068
1069 end arrayVarAllocInit;
1070
1071
1072 21632 template recordDefinition(String origName, String encName, String fieldNames, Integer numFields)
1073 "Generates the definition struct for a record declaration."
1074 ::=
1075 match encName
1076 case "SourceInfo_SOURCEINFO" then ''
1077 else
1078 /* adrpo: 2011-03-14 make MSVC happy, no arrays of 0 size! */
1079 let fieldsDescription =
1080 match numFields
1081 case 0 then
1082 'const char* <%encName%>__desc__fields[1] = {"no fields"};'
1083 case _ then
1084 'const char* <%encName%>__desc__fields[<%numFields%>] = {<%fieldNames%>};'
1085 <<
1086 #define <%encName%>__desc_added 1
1087 <%fieldsDescription%>
1088 struct record_description <%encName%>__desc = {
1089 "<%encName%>", /* package_record__X */
1090 "<%origName%>", /* package.record_X */
1091 <%encName%>__desc__fields
1092 };
1093 >>
1094 end recordDefinition;
1095
1096 ✗ template recordDefinitionHeader(String origName, String encName, Integer numFields)
1097 "Generates the definition struct for a record declaration."
1098 ::=
1099 <<
1100 extern struct record_description <%encName%>__desc;
1101 >>
1102 end recordDefinitionHeader;
1103
1104 8208 template functionHeaderNormal(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes)
1105 ::=functionHeaderImpl(fname, fargs, outVars, inFunc, false, visibility, dynLoad, isSimulation, staticPrototypes)
1106 end functionHeaderNormal;
1107
1108 12462 template functionHeaderBoxed(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean isBoxed, SCode.Visibility visibility, Boolean dynLoad, Boolean isSimulation, Text &staticPrototypes)
1109 ::=
1110 let boxvar =
1111 <<
1112 static const <%litDefBox()%>(boxvar_lit_<%fname%>,2,0) {(void*) <%if unboxedFunctionReferences() then 'omc_<%fname%>' else '<%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then "&"%>boxptr_<%fname%>'%>,0}};
1113 #define boxvar_<%fname%> <%litRefBox()%>(boxvar_lit_<%fname%>)<%\n%>
1114 >>
1115 <<
1116 <%if isBoxed then '#define boxptr_<%fname%> omc_<%fname%><%\n%>' else functionHeaderImpl(fname, fargs, outVars, inFunc, true, visibility, dynLoad, isSimulation, staticPrototypes)%>
1117 <% match visibility
1118 case PROTECTED(__) then
1119 let &staticPrototypes += (if boolOr(isSimulation, Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)) then "" else boxvar)
1120 if boolOr(isSimulation, Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)) then '<%boxvar%> /* boxvar early */' else ""
1121 else boxvar %>
1122 >>
1123 end functionHeaderBoxed;
1124
1125 19519 template functionHeaderImpl(String fname, list<Variable> fargs, list<Variable> outVars, Boolean inFunc, Boolean boxed, SCode.Visibility visibility, Boolean dynamicLoad, Boolean isSimulation, Text &staticPrototypes)
1126 "Generates function header for a Modelica/MetaModelica function. Generates a
1127
1128 boxed version of the header if boxed = true, otherwise a normal header"
1129 ::=
1130 let &dummy = buffer ""
1131 let prototype = functionPrototype(fname, fargs, outVars, boxed, visibility, isSimulation, true, dummy)
1132 let inFnStr = if boolAnd(boxed,inFunc) then
1133 <<
1134 DLLModelDirection
1135 int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar);
1136 >>
1137 match visibility
1138 case PROTECTED(__) then
1139 if boolOr(isSimulation, Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)) then
1140 if dynamicLoad then "" else '<%prototype%>;<%\n%>'
1141 else
1142 let &staticPrototypes += if dynamicLoad then "" else '<%prototype%>;<%\n%>'
1143 inFnStr
1144 else
1145 <<
1146 <%inFnStr%>
1147 <%if dynamicLoad then '' else 'DLLModelDirection<%\n%><%prototype%>;'%>
1148 >>
1149 end functionHeaderImpl;
1150
1151 34784 template functionPrototype(String fname, list<Variable> fargs, list<Variable> outVars, Boolean boxed, SCode.Visibility visibility, Boolean isSimulation, Boolean isPrototype, Text &afterBody)
1152 "Generates function header definition for a Modelica/MetaModelica function. Generates a boxed version of the header if boxed = true, otherwise a normal definition"
1153 ::=
1154 let static = if isSimulation then "" else (match visibility case PROTECTED(__) then 'PROTECTED_FUNCTION_STATIC ')
1155 let fargsStr = if boxed then
1156 (fargs |> var => ", " + funArgBoxedDefinition(var) )
1157 else
1158 (fargs |> var => ", " + funArgDefinition(var) )
1159 let outarg = (match outVars
1160 case var::_ then (match var
1161 case VARIABLE(__) then if boxed then varTypeBoxed(var) else varType(var)
1162 case FUNCTION_PTR(__) then "modelica_fnptr")
1163 else "void")
1164 let boxPtrStr = if boxed then "boxptr" else "omc"
1165 let fn_name = '<%boxPtrStr%>_<%fname%>'
1166 let fn_name_impl = (if isPrototype then fn_name else '<%boxPtrStr%>impl_<%fname%>')
1167 let fn_name_typedef = (if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then '<%boxPtrStr%>td_<%fname%>' else fn_name)
1168 let fn_name_ptr_typedef = (if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then (if isPrototype then '(*<%fn_name_typedef%>)' else fn_name_impl) else fn_name)
1169 let res = (if outVars then
1170 let outargs = listRest(outVars) |> var => ", " + (match var
1171 case var as VARIABLE(__) then '<%if boxed then varTypeBoxed(var) else varType(var)%> *out<%funArgName(var)%>'
1172 case FUNCTION_PTR(__) then 'modelica_fnptr *out<%funArgName(var)%>')
1173 '<%outarg%> <%fn_name_ptr_typedef%>(threadData_t *threadData<%fargsStr%><%outargs%>)'
1174 else
1175 'void <%fn_name_ptr_typedef%>(threadData_t *threadData<%fargsStr%>)')
1176 (if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then
1177 // No static functions for relocatable code...
1178 (if isPrototype then
1179 <<
1180 typedef <%res%>;
1181 <%fn_name_typedef%> <%fn_name%>
1182 >>
1183 else
1184 let &afterBody += '<%fn_name_typedef%> <%fn_name%> = <%fn_name_impl%>;'
1185 res)
1186 else '<%static%><%res%>')
1187 end functionPrototype;
1188
1189 ✗ template functionHeaderKernelFunctionInterface(String fname, list<Variable> fargs, list<Variable> outVars)
1190 "Generates function header for a ParModelica Kernel function interface."
1191 ::=
1192 '<%functionHeaderKernelFunctionInterfacePrototype(fname, fargs, outVars)%>;'
1193 end functionHeaderKernelFunctionInterface;
1194
1195 ✗ template functionHeaderKernelFunctionInterfacePrototype(String fname, list<Variable> fargs, list<Variable> outVars)
1196 "Generates function header for a ParModelica Kernel function interface."
1197 ::=
1198 let fargsStr = 'threadData_t *threadData'
1199 let &fargsStr += if fargs then ", " + (fargs |> var => funArgDefinitionKernelFunctionInterface(var) ;separator=", ")
1200 // let &fargsStr += if outVars then ", " + (outVars |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ")
1201 // 'void omc_<%fname%>(<%fargsStr%>)'
1202
1203 match outVars
1204 case {} then
1205 'void omc_<%fname%>(<%fargsStr%>)'
1206
1207 case fvar::rest then
1208 let rettype = varType(fvar)
1209 let &fargsStr += if rest then ", " + (rest |> var => tupleOutfunArgDefinitionKernelFunctionInterface(var) ;separator=", ")
1210 '<%rettype%> omc_<%fname%>(<%fargsStr%>)'
1211
1212 else
1213 error(sourceInfo(), 'functionHeaderKernelFunctionInterfacePrototype failed')
1214 end functionHeaderKernelFunctionInterfacePrototype;
1215
1216 54344 template funArgName(Variable var)
1217 ::=
1218 let &auxFunction = buffer ""
1219 match var
1220 case VARIABLE(__) then contextCrefNoPrevExp(name,contextFunction,&auxFunction)
1221 case FUNCTION_PTR(__) then '_' + System.unquoteIdentifier(name)
1222 end funArgName;
1223
1224 39109 template funArgDefinition(Variable var)
1225 ::=
1226 let &auxFunction = buffer ""
1227 match var
1228 case VARIABLE(__) then ('<%varType(var)%> <%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>' + (if var.instDims then " = {0}"))
1229 case FUNCTION_PTR(__) then 'modelica_fnptr _<%System.unquoteIdentifier(name)%>'
1230 end funArgDefinition;
1231
1232 ✗ template funArgDefinitionKernelFunctionInterface(Variable var)
1233 ::=
1234 let &auxFunction = buffer ""
1235 match var
1236 case VARIABLE(__) then
1237 '<%varType(var)%> <%funArgName(var)%>'
1238 else error(sourceInfo(), 'funArgDefinitionKernelFunctionInterface : unsupported function argument type')
1239 end funArgDefinitionKernelFunctionInterface;
1240
1241 ✗ template tupleOutfunArgDefinitionKernelFunctionInterface(Variable var)
1242 ::=
1243 let &auxFunction = buffer ""
1244 match var
1245 case VARIABLE(__) then
1246 '<%varType(var)%> *out<%funArgName(var)%>'
1247 else error(sourceInfo(), 'tupleOutfunArgDefinitionKernelFunctionInterface : unsupported function argument type')
1248 end tupleOutfunArgDefinitionKernelFunctionInterface;
1249
1250 ✗ template funArgDefinitionKernelFunctionBody(Variable var)
1251 "Generates code to initialize variables.
1252 Does not return anything: just appends declarations to buffers."
1253 ::=
1254 let &auxFunction = buffer ""
1255 match var
1256 //function args will have nill instdims even if they are arrays. handled here
1257 case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then
1258 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1259 '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>'
1260
1261 case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then
1262 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1263 '__local modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __local modelica_integer* info_<%varName%>'
1264
1265 case var as VARIABLE(__) then
1266 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1267 if instDims then
1268 (match parallelism
1269 case PARGLOBAL(__) then
1270 '__global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __global modelica_integer* info_<%varName%>'
1271 case PARLOCAL(__) then
1272 '__local modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,<%\n%> __local modelica_integer* info_<%varName%>'
1273 )
1274 else
1275 'modelica_<%expTypeShort(var.ty)%> <%varName%>'
1276
1277 else '#error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody<%\n%>'
1278 end funArgDefinitionKernelFunctionBody;
1279
1280 ✗ template funArgDefinitionKernelFunctionBody2(Variable var, Text &parArgList /*BUFPA*/)
1281 "Generates code to initialize variables.
1282 Does not return anything: just appends declarations to buffers."
1283 ::=
1284 let &auxFunction = buffer ""
1285 match var
1286 //function args will have nill instdims even if they are arrays. handled here
1287 case var as VARIABLE(ty=T_ARRAY(__)) then
1288 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1289 let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,'
1290 let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>'
1291 ""
1292 case var as VARIABLE(__) then
1293 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1294 if instDims then
1295 let &parArgList += ',<%\n%> __global modelica_<%expTypeShort(var.ty)%>* data_<%varName%>,'
1296 let &parArgList += '<%\n%> __global modelica_integer* info_<%varName%>'
1297 " "
1298 else
1299 let &parArgList += ',<%\n%> modelica_<%expTypeShort(var.ty)%> <%varName%>'
1300 ""
1301 else let &parArgList += ' #error Unknown variable type in as function argument funArgDefinitionKernelFunctionBody2<%\n%>' ""
1302 end funArgDefinitionKernelFunctionBody2;
1303
1304 ✗ template parFunArgDefinitionFromLooptupleVar(tuple<DAE.ComponentRef,builtin.SourceInfo> tupleVar)
1305 ::=
1306 match tupleVar
1307 case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then
1308 let varName = contextArrayCref(cref,contextParallelFunction)
1309 match cref.identType
1310 case identType as T_ARRAY(ty = T_INTEGER(__)) then
1311 '__global modelica_integer* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>'
1312 case identType as T_ARRAY(ty = T_REAL(__)) then
1313 '__global modelica_real* data_<%varName%>,<%\n%>__global modelica_integer* info_<%varName%>'
1314
1315 else 'Template error in parFunArgDefinitionFromLooptupleVar'
1316
1317 case tupleVar as ((cref as CREF_IDENT(__),_)) then
1318 let varName = contextArrayCref(cref,contextParallelFunction)
1319 match cref.identType
1320 case identType as T_INTEGER(__) then
1321 'modelica_integer <%varName%>'
1322 case identType as T_REAL(__) then
1323 'modelica_real <%varName%>'
1324
1325 else 'Tempalte error in parFunArgDefinitionFromLooptupleVar'
1326
1327 end parFunArgDefinitionFromLooptupleVar;
1328
1329 ✗ template reconstructKernelArraysFromLooptupleVars(tuple<DAE.ComponentRef,builtin.SourceInfo> tupleVar, Text &reconstructedArrs)
1330 "reconstructs modelica arrays in the kernels."
1331 ::=
1332 match tupleVar
1333 case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then
1334 let varName = contextArrayCref(cref,contextParallelFunction)
1335 match cref.identType
1336 case identType as T_ARRAY(ty = T_INTEGER(__)) then
1337 let &reconstructedArrs += 'integer_array <%varName%>; <%\n%>'
1338 let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>'
1339 let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>'
1340 let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>'
1341 ""
1342 case identType as T_ARRAY(ty = T_REAL(__)) then
1343 let &reconstructedArrs += 'real_array <%varName%>; <%\n%>'
1344 let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>'
1345 let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>'
1346 let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>'
1347 ""
1348 else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' ""
1349 end reconstructKernelArraysFromLooptupleVars;
1350
1351 ✗ template reconstructKernelArrays(Variable var, Text &reconstructedArrs)
1352 "reconstructs modelica arrays in the kernels."
1353 ::=
1354 let &auxFunction = buffer ""
1355 match var
1356 //function args will have nill instdims even if they are arrays. handled here
1357 case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then
1358 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1359 let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>'
1360 let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>'
1361 let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>'
1362 let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>'
1363 ""
1364 case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then
1365 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1366 let &reconstructedArrs += 'local_<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>'
1367 let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>'
1368 let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>'
1369 let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>'
1370 ""
1371 case var as VARIABLE(__) then
1372 let varName = '<%contextCrefNoPrevExp(var.name,contextParallelFunction,&auxFunction)%>'
1373 if instDims then
1374 let &reconstructedArrs += '<%expTypeShort(var.ty)%>_array <%varName%>; <%\n%>'
1375 let &reconstructedArrs += '<%varName%>.data = data_<%varName%>; <%\n%>'
1376 let &reconstructedArrs += '<%varName%>.ndims = info_<%varName%>[0]; <%\n%>'
1377 let &reconstructedArrs += '<%varName%>.dim_size = info_<%varName%> + 1; <%\n%>'
1378 " "
1379 else
1380 ""
1381 else let &reconstructedArrs += '#wiered variable in kerenl reconstruction of arrays<%\n%>' ""
1382 end reconstructKernelArrays;
1383
1384 119154 template funArgBoxedDefinition(Variable var)
1385 "A definition for a boxed variable is always of type modelica_metatype,
1386 unless it's a function pointer"
1387 ::=
1388 let &auxFunction = buffer ""
1389 match var
1390 case VARIABLE(__) then 'modelica_metatype <%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>'
1391 case FUNCTION_PTR(__) then 'modelica_fnptr _<%System.unquoteIdentifier(name)%>'
1392 end funArgBoxedDefinition;
1393
1394 555 template extFunDef(SimCodeFunction.Function fn)
1395 "Generates function header for an external function."
1396 ::=
1397 match fn
1398 case func as EXTERNAL_FUNCTION(__) then
1399 let fn_name = extFunctionName(extName, language)
1400 let fargsStr = extFunDefArgs(extArgs, language)
1401 let fargsStrEscaped = '<%escapeCComments(fargsStr)%>'
1402 let isBuiltin = match language case "BUILTIN" then true end match
1403 /*
1404 * adrpo:
1405 * only declare the external function definition IF THERE WERE NO INCLUDES!
1406 * or if the function is not builtin
1407 */
1408 if boolOr(boolNot(listEmpty(includes)), boolNot(stringEq(isBuiltin, ""))) then
1409 <<
1410 /*
1411 * The function has annotation(Include=...>) or is builtin
1412 * the external function definition should be present
1413 * in one of these files and have this prototype:
1414 * extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStrEscaped%>);
1415 */
1416 >>
1417 else
1418 <<
1419 extern <%extReturnType(extReturn)%> <%fn_name%>(<%fargsStr%>);
1420 >>
1421 end match
1422 end extFunDef;
1423
1424 ✗ template extFunDefDynamic(SimCodeFunction.Function fn)
1425 "Generates function header for an external function."
1426 ::=
1427 match fn
1428 case func as EXTERNAL_FUNCTION(__) then
1429 let fn_name = extFunctionName(extName, language)
1430 let fargsStr = extFunDefArgs(extArgs, language)
1431 <<
1432 typedef <%extReturnType(extReturn)%> (*ptrT_<%fn_name%>)(<%fargsStr%>);
1433 extern ptrT_<%fn_name%> ptr_<%fn_name%>;
1434 >>
1435 end extFunDefDynamic;
1436
1437 555 template extFunDefArgs(list<SimExtArg> args, String language)
1438 ::=
1439 match language
1440 case "BUILTIN"
1441 case "C" then (args |> arg => extFunDefArg(arg) ;separator=", ")
1442 case "FORTRAN 77" then (args |> arg => extFunDefArgF77(arg) ;separator=", ")
1443 else error(sourceInfo(), 'Unsupported external language: <%language%>')
1444 end extFunDefArgs;
1445
1446 279 template extReturnType(SimExtArg extArg)
1447 "Generates return type for external function."
1448 ::=
1449 match extArg
1450 /* For records use the externl type version of the record */
1451 case ex as SIMEXTARG(type_ = ty as T_COMPLEX(complexClassType=RECORD(__))) then '<%expTypeShort(ty)%>_external'
1452 case ex as SIMEXTARG(__) then extType(type_,true /*Treat this as an input (pass by value, except for records)*/,false,true)
1453 case SIMNOEXTARG(__) then "void"
1454 case SIMEXTARGEXP(__) then error(sourceInfo(), 'Expression types are unsupported as return arguments <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
1455 else error(sourceInfo(), "Unsupported return argument")
1456 end extReturnType;
1457
1458 5877 template extType(Type type, Boolean isInput, Boolean isArray, Boolean returnType)
1459 "Generates type for external function argument or return value."
1460 ::=
1461 let s = match type
1462 case T_INTEGER(__) then "int"
1463 case T_REAL(__) then "double"
1464 case T_STRING(__) then "const char*"
1465 case T_BOOL(__) then "int"
1466 case T_ENUMERATION(__) then "int"
1467 case T_ARRAY(__) then extType(ty,isInput,true,returnType)
1468 case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__))
1469 then "void *"
1470 case T_COMPLEX(complexClassType=RECORD(path=rname))
1471 then '<%underscorePath(rname)%>'
1472 case T_METATYPE(__)
1473 case T_METABOXED(__)
1474 then "modelica_metatype"
1475 case T_FUNCTION_REFERENCE_VAR(__)
1476 then "modelica_fnptr"
1477 else error(sourceInfo(), 'Unknown external C type <%unparseType(type)%>')
1478 match type case T_ARRAY(__) then s else if isInput then (if isArray then '<%match s case "const char*" then "" else "const "%><%s%>*' else s) else '<%s%>*'
1479 end extType;
1480
1481 148 template extTypeF77(Type type, Boolean isReference)
1482 "Generates type for external function argument or return value for F77."
1483 ::=
1484 let s = match type
1485 case T_INTEGER(__) then "int"
1486 case T_REAL(__) then "double"
1487 case T_STRING(__) then "char"
1488 case T_BOOL(__) then "int"
1489 case T_ENUMERATION(__) then "int"
1490 case T_ARRAY(__) then extTypeF77(ty, true)
1491 case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__))
1492 then "void*"
1493 case T_COMPLEX(complexClassType=RECORD(path=rname))
1494 then '<%underscorePath(rname)%>'
1495 case T_METATYPE(__) case T_METABOXED(__) then "void*"
1496 else error(sourceInfo(), 'Unknown external F77 type <%unparseType(type)%>')
1497 match type case T_ARRAY(__) then s else if isReference then '<%s%>*' else s
1498 end extTypeF77;
1499
1500 1578 template extFunDefArg(SimExtArg extArg)
1501 "Generates the definition of an external function argument.
1502 Assume that language is C for now."
1503 ::=
1504 let &auxFunction = buffer ""
1505 match extArg
1506 case SIMEXTARG(cref=c, isInput=ii, isArray=ia, type_= ty as T_COMPLEX(complexClassType=RECORD(__))) then
1507 let name = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
1508 let typeStr = expTypeShort(ty)
1509 <<
1510 <%typeStr%>_external* /*<%name%>*/
1511 >>
1512 case SIMEXTARGEXP(type_= ty as T_COMPLEX(complexClassType=RECORD(__))) then
1513 let typeStr = expTypeShort(ty)
1514 <<
1515 <%typeStr%>*
1516 >>
1517 case SIMEXTARG(cref=c, isInput=ii, isArray=ia, type_=t) then
1518 let name = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
1519 let typeStr = extType(t,ii,ia,false)
1520 <<
1521 <%typeStr%> /*<%name%>*/
1522 >>
1523 case SIMEXTARGEXP(__) then
1524 let typeStr = extType(type_,true,false,false)
1525 <<
1526 <%typeStr%>
1527 >>
1528 case SIMEXTARGSIZE(cref=c) then
1529 <<
1530 size_t
1531 >>
1532 end extFunDefArg;
1533
1534 95 template extFunDefArgF77(SimExtArg extArg)
1535 ::=
1536 let &auxFunction = buffer ""
1537 match extArg
1538 case SIMEXTARG(cref=c, isInput = isInput, type_=t) then
1539 let name = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
1540 let typeStr = '<%extTypeF77(t,true)%>'
1541 '<%typeStr%> /*<%name%>*/'
1542
1543 case SIMEXTARGEXP(__) then '<%extTypeF77(type_,true)%>'
1544
1545 /* adpro: 2011-06-23
1546 * DO NOT USE CONST HERE as sometimes is used with size(A, 1)
1547
1548 * sometimes with n in Modelica.Math.Matrices.Lapack and you
1549 * get conflicting external definitions in the same Model_function.h
1550 * file
1551 */
1552 case SIMEXTARGSIZE(__) then 'int *'
1553 end extFunDefArgF77;
1554
1555
1556 5907 template functionName(SimCodeFunction.Function fn, Boolean dotPath)
1557 ::=
1558 match fn
1559 case FUNCTION(__)
1560 case EXTERNAL_FUNCTION(__)
1561 case RECORD_CONSTRUCTOR(__) then if dotPath then dotPath(name) else underscorePath(name)
1562 end functionName;
1563
1564
1565 1346 template functionBodies(list<SimCodeFunction.Function> functions, Boolean isSimulation)
1566 "Generates the body for a set of functions."
1567 ::=
1568 (functions |> fn => functionBody(fn, false, isSimulation) ;separator="\n")
1569 end functionBodies;
1570
1571 ✗ template functionBodiesParModelica(list<SimCodeFunction.Function> functions)
1572 "Generates the body for a set of functions."
1573 ::=
1574 (functions |> fn => functionBodyParModelica(fn, false); separator="\n")
1575 end functionBodiesParModelica;
1576
1577 7653 template functionBody(SimCodeFunction.Function fn, Boolean inFunc, Boolean isSimulation)
1578 "Generates the body for a function."
1579 ::=
1580 match fn
1581 case fn as FUNCTION(__) then functionBodyRegularFunction(fn, inFunc, isSimulation)
1582 case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunctionInterface(fn, inFunc)
1583 case fn as EXTERNAL_FUNCTION(__) then functionBodyExternalFunction(fn, inFunc, isSimulation)
1584 case fn as RECORD_CONSTRUCTOR(__) then functionBodyRecordConstructor(fn, isSimulation)
1585 end functionBody;
1586
1587 ✗ template functionBodyParModelica(SimCodeFunction.Function fn, Boolean inFunc)
1588 "Generates the body for a function."
1589 ::=
1590 match fn
1591 case fn as FUNCTION(__) then extractParforBodies(fn, inFunc)
1592 case fn as KERNEL_FUNCTION(__) then functionBodyKernelFunction(fn, inFunc)
1593 case fn as PARALLEL_FUNCTION(__) then functionBodyParallelFunction(fn, inFunc)
1594 end functionBodyParModelica;
1595
1596 ✗ template extractParforBodies(SimCodeFunction.Function fn, Boolean inFunc)
1597 "Generates the body for a Modelica/MetaModelica function."
1598 ::=
1599 match fn
1600 case FUNCTION(__) then
1601 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
1602
1603 let &varDecls = buffer ""
1604 let &varFrees = buffer ""
1605 let &auxFunction = buffer ""
1606 let bodyPart = extractParFors(body, &varDecls, &varFrees, &auxFunction)
1607 <<
1608 <%auxFunction%>
1609 <%bodyPart%>
1610 >>
1611 end extractParforBodies;
1612
1613 7653 template functionBodyRegularFunction(SimCodeFunction.Function fn, Boolean inFunc, Boolean isSimulation)
1614 "Generates the body for a Modelica/MetaModelica function."
1615 ::=
1616 match fn
1617 case FUNCTION(__) then
1618 let()= codegenResetTryThrowIndex()
1619 let()= System.tmpTickReset(1)
1620 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
1621 let fname = underscorePath(name)
1622 let &varDecls = buffer ""
1623 let &varFrees = buffer ""
1624 let &varInits = buffer ""
1625 let &auxFunction = buffer ""
1626 let restoreJmpbuf = (if statementsContainReturn(body) then
1627 (if statementsContainTryBlock(body) then
1628 let &varDecls += 'jmp_buf *old_mmc_jumper = threadData->mmc_jumper;<%\n%>'
1629 'threadData->mmc_jumper = old_mmc_jumper;<%\n%>'))
1630 let _ = (variableDeclarations |> var hasindex i1 fromindex 1 =>
1631 varInitLocal(var, fn, &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */
1632 )
1633 let bodyPart = funStatement(body, &varDecls, &varFrees, &auxFunction)
1634 // Captured before the frees run: they null the local it is read from.
1635 let &varDecls += (match outVars case v::_ then '<%retVarType(v)%> omc_ret_;<%\n%>')
1636 let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var))
1637
1638 let freeConstructedExternalObjects = (variableDeclarations |> var as VARIABLE(ty=T_COMPLEX(complexClassType=EXTERNAL_OBJ(path=path_ext))) => 'omc_<%underscorePath(path_ext)%>_destructor(threadData,<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>);'; separator = "\n")
1639 /* Needs to be done last as it messes with the tmp ticks :) */
1640 let &varDecls += addRootsTempArray()
1641
1642 let boxedFn = if not funcHasParallelInOutArrays(fn) then functionBodyBoxed(fn, isSimulation) else ""
1643 let &afterBody = buffer ""
1644 let prototype = functionPrototype(fname, functionArguments, outVars, false, visibility, isSimulation, false, afterBody)
1645 <<
1646 <%auxFunction%>
1647 <% match visibility case PUBLIC(__) then "DLLModelDirection" %>
1648 <%prototype%>
1649 {
1650 <%varDecls%>
1651 <% if boolNot(isSimulation) then 'OMC_SO();<%\n%>'%>_tailrecursive: OMC_LABEL_UNUSED
1652 <%varInits%>
1653 <%bodyPart%>
1654 _return: OMC_LABEL_UNUSED
1655 <%outVarAssign%><%restoreJmpbuf%>
1656 <%freeConstructedExternalObjects%>
1657 <%match outVars
1658 case v::_ then 'omc_ret_ = <%funArgName(v)%>;<%\n%>'
1659 %><%match outVars case v::_ then rcRetainOut(v)%><%varFrees%>
1660 <%match outVars
1661 case v::_ then 'return omc_ret_;'
1662 else 'return;'
1663 %>
1664 }
1665 <%afterBody%>
1666 <% if inFunc then generateInFunc(fname,functionArguments,outVars) %>
1667 <%boxedFn%>
1668 >>
1669 end functionBodyRegularFunction;
1670
1671 ✗ template outVarsHoldNoHeapData(list<Variable> outVars)
1672 "Returns non-empty if none of the outputs can carry heap allocated data, i.e. every output is a
1673 scalar Real/Integer/Boolean. Arrays, records, strings, metatypes and function pointers can all
1674 reference memory the caller keeps using, so they rule the function out."
1675 ::=
1676 let heapOut = (outVars |> var => outVarHoldsHeapData(var))
1677 if heapOut then "" else "x"
1678 end outVarsHoldNoHeapData;
1679
1680 ✗ template outVarHoldsHeapData(Variable var)
1681 "Returns non-empty if this output may carry heap allocated data."
1682 ::=
1683 match var
1684 case var as VARIABLE(__) then
1685 if instDims then
1686 "x"
1687 else
1688 match varType(var)
1689 case "modelica_real"
1690 case "modelica_integer"
1691 case "modelica_boolean" then ""
1692 else "x"
1693 else "x"
1694 end outVarHoldsHeapData;
1695
1696 ✗ template functionHasExternalObject(list<Variable> vars)
1697 "Returns non-empty if the list holds an external object. Such an object can own memory across
1698 calls, and external code reached through it could keep a pointer to something the function
1699 allocated, so those functions are left alone. Call it for the arguments as well as the
1700 declarations: variableDeclarations never contains the inputs."
1701 ::=
1702 (vars |> var =>
1703 match var
1704 case VARIABLE(ty=T_COMPLEX(complexClassType=EXTERNAL_OBJ(__))) then "x"
1705 else "")
1706 end functionHasExternalObject;
1707
1708 142 template generateInFunc(Text fname, list<Variable> functionArguments, list<Variable> outVars)
1709 ::=
1710 <<
1711 /* type_description marshalling for the -d=gen entry point below. */
1712 #include "util/read_write.h"
1713
1714 DLLModelDirection
1715 int in_<%fname%>(threadData_t *threadData, type_description * inArgs, type_description * outVar)
1716 {
1717 //if (!mmc_GC_state) mmc_GC_init();
1718 <%functionArguments |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%>
1719 <%outVars |> var => '<%funArgDefinition(var)%>;' ;separator="\n"%>
1720 <%functionArguments |> arg => readInVar(arg) ;separator="\n"%>
1721 OMC_TRY_TOP_INTERNAL()
1722 <%match outVars
1723 case v::_ then '<%funArgName(v)%> = '
1724 %>omc_<%fname%>(threadData<%functionArguments |> var => (", " + funArgName(var) )%><%List.restOrEmpty(outVars) |> var => (", &" + funArgName(var) )%>);
1725 if (OMC_ERROR_RAISED()) { OMC_ERROR_CLEAR(); OMC_THROW_INTERNAL(); }
1726 OMC_CATCH_TOP(return 1)
1727 <% match outVars case first::_ then writeOutVar(first) else "write_noretcall(outVar);" %>
1728 <% List.restOrEmpty(outVars) |> var => writeOutVar(var) ;separator="\n"; empty %>
1729 fflush(NULL);
1730 return 0;
1731 }
1732 #ifdef GENERATE_MAIN_EXECUTABLE
1733 static int rml_execution_failed()
1734 {
1735 fflush(NULL);
1736 fprintf(stderr, "Execution failed!\n");
1737 fflush(NULL);
1738 return 1;
1739 }
1740
1741 int main(int argc, char **argv) {
1742 OMC_INIT(0);
1743 {
1744 void *lst = mmc_mk_nil();
1745 int i = 0;
1746
1747 for (i=argc-1; i>0; i--) {
1748 lst = mmc_mk_cons(mmc_mk_scon(argv[i]), lst);
1749 }
1750
1751 <%mainTop('omc_<%fname%>(threadData, lst);',"https://trac.openmodelica.org/OpenModelica/newticket")%>
1752 }
1753
1754 <%if Flags.isSet(HPCOM) then "terminateHpcOmThreads();" %>
1755 fflush(NULL);
1756 EXIT(0);
1757 return 0;
1758 }
1759 #endif
1760 >>
1761 end generateInFunc;
1762
1763 ✗ template functionBodyKernelFunction(SimCodeFunction.Function fn, Boolean inFunc)
1764 "Generates the body for a ParModelica Kernel function."
1765 ::=
1766 match fn
1767 case KERNEL_FUNCTION(__) then
1768 let()= System.tmpTickReset(1)
1769 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
1770 let fname = underscorePath(name)
1771
1772 //retTyep for kernels is always void
1773 //let retType = if outVars then '<%fname%>_rettype' else "void"
1774
1775 let &varDecls = buffer ""
1776 let &varFrees = buffer ""
1777 let &varInits = buffer ""
1778 let &auxFunction = buffer ""
1779 let _ = (variableDeclarations |> var =>
1780 varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */
1781 )
1782
1783 // This odd arrangment and call is to get the commas in the right places
1784 // between the argumetns.
1785 // This puts correct comma placment even when the 'outvar' list is empty
1786 let argStr = (functionArguments |> var => '<%funArgDefinitionKernelFunctionBody(var)%>' ;separator=",\n ")
1787 //let &argStr += (outVars |> var => '<%parFunArgDefinition(var)%>' ;separator=",\n")
1788 let _ = (outVars |> var =>
1789 funArgDefinitionKernelFunctionBody2(var, &argStr) ;separator=",\n")
1790
1791 // Reconstruct array arguments to structures in the kernels
1792 let &reconstrucedArrays = buffer ""
1793 let _ = (functionArguments |> var =>
1794 reconstructKernelArrays(var, &reconstrucedArrays)
1795 )
1796 let _ = (outVars |> var =>
1797 reconstructKernelArrays(var, &reconstrucedArrays)
1798 )
1799
1800 let bodyPart = parModelicafunStatement(body, &varDecls, &varFrees, &auxFunction)
1801
1802 /* Needs to be done last as it messes with the tmp ticks :) */
1803 let &varDecls += addRootsTempArray()
1804
1805 <<
1806 <%auxFunction%>
1807
1808 __kernel void omc_<%fname%>(
1809 <%\t%><%\t%><%argStr%>)
1810 {
1811 /* functionBodyKernelFunction: Reconstruct Arrays */
1812 <%reconstrucedArrays%>
1813
1814 /* functionBodyKernelFunction: locals */
1815 <%varDecls%>
1816
1817 /* functionBodyKernelFunction: var inits */
1818 <%varInits%>
1819 /* functionBodyKernelFunction: body */
1820 <%bodyPart%>
1821
1822 /* Free GPU/OpenCL CPU memory */
1823 <%varFrees%>
1824 }
1825
1826 >>
1827 end functionBodyKernelFunction;
1828
1829 //Generates the body of a parallel function
1830 ✗ template functionBodyParallelFunction(SimCodeFunction.Function fn, Boolean inFunc)
1831 "Generates the body for a Modelica parallel function."
1832 ::=
1833 match fn
1834 case PARALLEL_FUNCTION(__) then
1835 let &auxFunction = buffer ""
1836 let()= codegenResetTryThrowIndex()
1837 let()= System.tmpTickReset(1)
1838 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
1839 let fname = underscorePath(name)
1840 let &varDecls = buffer ""
1841 let &varFrees = buffer ""
1842 let &varInits = buffer ""
1843 let &outVarFrees = buffer "" /*we don't free them. this is just ignored*/
1844 let &auxFunction = buffer ""
1845
1846 let _ = (variableDeclarations |> var =>
1847 varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty
1848 )
1849 // let _ = (outVars |> var =>
1850 // varInit(var, "", &varDecls, &varInits, &outVarFrees, &auxFunction) ; empty
1851 // )
1852 let bodyPart = parModelicafunStatement(body, &varDecls, &varFrees, &auxFunction)
1853 let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var))
1854
1855 /* Needs to be done last as it messes with the tmp ticks :) */
1856 let &varDecls += addRootsTempArray()
1857
1858 <<
1859 <%auxFunction%>
1860 <%functionHeaderParallelImpl(fname, functionArguments, outVars, false, false)%>
1861 {
1862 <%varDecls%>
1863
1864 <%varInits%>
1865
1866 <%bodyPart%>
1867
1868 <%outVarAssign%>
1869
1870 <%match outVars
1871 case v::_ then 'return <%funArgName(v)%>;'
1872 else 'return;'
1873 %>
1874 }
1875 >>
1876 end functionBodyParallelFunction;
1877
1878 ✗ template functionBodyKernelFunctionInterface(SimCodeFunction.Function fn, Boolean inFunc)
1879 "Generates the body for a Modelica/MetaModelica function."
1880 ::=
1881 match fn
1882 case KERNEL_FUNCTION(__) then
1883 let()= codegenResetTryThrowIndex()
1884 let()= System.tmpTickReset(1)
1885 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
1886 let fname = underscorePath(name)
1887 let &varDecls = buffer ""
1888 let &varFrees = buffer ""
1889 let &varInits = buffer ""
1890 let &auxFunction = buffer ""
1891
1892 let _ = (variableDeclarations |> var hasindex i1 fromindex 1 =>
1893 varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */
1894 )
1895 let _ = (outVars |> var hasindex i1 fromindex 1 =>
1896 varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction) ; empty /* increase the counter! */
1897 )
1898
1899 let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var))
1900
1901 let cl_kernelVar = tempDecl("cl_kernel", &varDecls, &varFrees)
1902 let kernel_arg_number = '<%fname%>_arg_nr'
1903
1904 let &kernelArgSets = buffer ""
1905 let _ = (functionArguments |> var =>
1906 setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets)
1907 )
1908 let _ = (outVars |> var =>
1909 setKernelArg_ith(var, &cl_kernelVar, &kernel_arg_number, &kernelArgSets)
1910 )
1911
1912 // let defines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#define <%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%> (*out<%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>)' ;separator="\n")
1913 // let undefines = (List.restOrEmpty(outVars) |> var as VARIABLE(__) => '#undef <%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>' ;separator="\n")
1914
1915 <<
1916
1917 <%functionHeaderKernelFunctionInterfacePrototype(fname, functionArguments, outVars)%>
1918 {
1919 // declerations
1920 <%varDecls%>
1921 // inits
1922 <%varInits%>
1923
1924 /* functionBodyKernelFunctionInterface : <%fname%> Kernel creation and execution */
1925 int <%kernel_arg_number%> = 0;
1926 <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "omc_<%fname%>");
1927 <%kernelArgSets%>
1928 ocl_execute_kernel(<%cl_kernelVar%>);
1929 clReleaseKernel(<%cl_kernelVar%>);
1930 /*functionBodyKernelFunctionInterface : <%fname%> kernel execution ends here.*/
1931
1932 // outvar assign
1933 <%outVarAssign%>
1934
1935 //varfree
1936 /*
1937 <%varFrees%>
1938 */
1939
1940 // return
1941 <%match outVars
1942 case var::_ then 'return <%funArgName(var)%>;'
1943 else 'return;'
1944 %>
1945 }
1946
1947 >>
1948
1949 end functionBodyKernelFunctionInterface;
1950
1951 ✗ template setKernelArg_ith(Variable var, Text &KernelName, Text &argNr, Text &parVarList /*BUFPA*/)
1952 ::=
1953 let &auxFunction = buffer ""
1954 match var
1955 //function args will have nill instdims even if they are arrays. handled here
1956 case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARGLOBAL(__)) then
1957 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
1958 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>'
1959 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>'
1960 ""
1961 case var as VARIABLE(ty=T_ARRAY(__),parallelism=PARLOCAL(__)) then
1962 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
1963 // Increment twice. Both data and info set in the function
1964 // let &parVarList += 'ocl_set_local_array_kernel_arg(<%KernelName%>, <%argNr%>, &<%varName%>); ++<%argNr%>; ++<%argNr%>; <%\n%>'
1965 let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_<%expTypeShort(var.ty)%>) * device_array_nr_of_elements(&<%varName%>)); ++<%argNr%>; <%\n%>'
1966 let &parVarList += 'ocl_set_local_kernel_arg(<%KernelName%>, <%argNr%>, sizeof(modelica_integer) * (<%varName%>.info[0]+1)*sizeof(modelica_integer)); ++<%argNr%>; <%\n%>'
1967 ""
1968 case var as VARIABLE(__) then
1969 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
1970 if instDims then
1971 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>'
1972 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>'
1973 ""
1974 else
1975 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>'
1976 ""
1977 end setKernelArg_ith;
1978
1979
1980 ✗ template setKernelArgFormTupleLoopVars_ith(tuple<DAE.ComponentRef,builtin.SourceInfo> tupleVar, Text &KernelName, Text &argNr, Text &parVarList, Context context /*BUFPA*/)
1981 ::=
1982 match tupleVar
1983 //function args will have nill instdims even if they are arrays. handled here
1984 case tupleVar as ((cref as CREF_IDENT(identType = T_ARRAY(__)),_)) then
1985 let varName = contextArrayCref(cref,context)
1986 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.data); ++<%argNr%>; <%\n%>'
1987 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>.info_dev); ++<%argNr%>; <%\n%>'
1988 ""
1989 case tupleVar as ((cref as CREF_IDENT(__),_)) then
1990 let varName = contextArrayCref(cref,context)
1991 let &parVarList += 'ocl_set_kernel_arg(<%KernelName%>, <%argNr%>, <%varName%>); ++<%argNr%>; <%\n%>'
1992 ""
1993 end setKernelArgFormTupleLoopVars_ith;
1994
1995
1996 555 template functionBodyExternalFunction(SimCodeFunction.Function fn, Boolean inFunc, Boolean isSimulation)
1997 "Generates the body for an external function (just a wrapper)."
1998 ::=
1999 match fn
2000 case efn as EXTERNAL_FUNCTION(__) then
2001 let()= System.tmpTickReset(1)
2002 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
2003 let fname = underscorePath(name)
2004 let retType = if outVars then '<%fname%>_rettype' else "void"
2005 let &preExp = buffer ""
2006 let &varDecls = buffer ""
2007 let &varFrees = buffer ""
2008 let &outputAlloc = buffer ""
2009 let &auxFunction = buffer ""
2010 let callPart = extFunCall(fn, &preExp, &varDecls, &varFrees, &outputAlloc, &auxFunction)
2011 let _ = ( outVars |> var =>
2012 varInit(var, "", &varDecls, &outputAlloc, &varFrees, &auxFunction)
2013 ; empty /* increase the counter! */ )
2014
2015 let outVarAssign = (List.restOrEmpty(outVars) |> var => varOutput(var))
2016
2017 // Captured before the frees run: they null the local it is read from.
2018 let &varDecls += (match outVars case v::_ then if metaModelicaRuntime() then "" else '<%retVarType(v)%> omc_ret_;<%\n%>')
2019 let &varDecls += addRootsTempArray()
2020 let boxedFn = functionBodyBoxed(fn, isSimulation)
2021 let &afterBody = buffer ""
2022 let prototype = functionPrototype(fname, funArgs, outVars, false, visibility, isSimulation, false, afterBody)
2023 // A MetaModelica external throws through mmc_jumper; no landing of its own.
2024 let fnBody = if metaModelicaRuntime() then <<
2025 <%auxFunction%>
2026 <%prototype%>
2027 {
2028 <%varDecls%>
2029 <%modelicaLine(info)%>
2030 <%outputAlloc%>
2031 <%preExp%>
2032 <%callPart%>
2033 <%outVarAssign%>
2034 <%match outVars
2035 case v::_ then 'return <%funArgName(v)%>;'
2036 else 'return;'
2037 %>
2038 }
2039 <%afterBody%>
2040 >>
2041 else <<
2042 <%auxFunction%>
2043 <%prototype%>
2044 {
2045 <%varDecls%>
2046 jmp_buf omc_ext_jmp_, *omc_ext_old_ = threadData->externalJumpBuffer;
2047 size_t omc_ext_strings_ = omc_external_strings_mark();
2048 int omc_ext_threw_ = 0;
2049 <%modelicaLine(info)%>
2050 threadData->externalJumpBuffer = &omc_ext_jmp_;
2051 if (setjmp(omc_ext_jmp_) == 0) {
2052 <%outputAlloc%>
2053 <%preExp%>
2054 <%callPart%>
2055 <%outVarAssign%>
2056 } else {
2057 omc_ext_threw_ = 1;
2058 }
2059 _return: OMC_LABEL_UNUSED
2060 threadData->externalJumpBuffer = omc_ext_old_;
2061 omc_external_strings_release(omc_ext_strings_);
2062 if (omc_ext_threw_) {
2063 OMC_EXTERNAL_ERROR();
2064 }
2065 <%match outVars
2066 case v::_ then 'omc_ret_ = <%funArgName(v)%>;<%\n%>'
2067 %><%match outVars case v::_ then rcRetainOut(v)%><%varFrees%>
2068 <%match outVars
2069 case v::_ then 'return omc_ret_;'
2070 else 'return;'
2071 %>
2072 }
2073 <%afterBody%>
2074 >>
2075 <<
2076 <% if dynamicLoad then
2077 <<
2078 ptrT_<%extFunctionName(extName, language)%> ptr_<%extFunctionName(extName, language)%>=NULL;
2079 >> %>
2080 <%fnBody%>
2081 <% if inFunc then generateInFunc(fname, funArgs, outVars) %>
2082 <%boxedFn%>
2083 >>
2084 end functionBodyExternalFunction;
2085
2086
2087 4254 template functionBodyRecordConstructor(SimCodeFunction.Function fn, Boolean isSimulation)
2088 "Generates the body for a record constructor."
2089 ::=
2090 match fn
2091 case RECORD_CONSTRUCTOR(__) then
2092 let()= System.tmpTickReset(1)
2093 let &varDecls = buffer ""
2094 let &varFrees = buffer ""
2095 let &varInits = buffer ""
2096 let &auxFunction = buffer ""
2097 let fname = underscorePath(name)
2098 let structType = '<%fname%>'
2099 let structVar = tempDecl(structType, &varDecls, &varFrees)
2100 let _ = (locals |> var =>
2101 varInitRecord(var, structVar, &varDecls, &varFrees, &varInits, &auxFunction) ; empty /* increase the counter! */
2102 )
2103 let boxedFn = functionBodyBoxed(fn, isSimulation)
2104 // The caller takes the record, so it is disowned before the frees run.
2105 let &varDecls += '<%structType%> omc_ret_;<%\n%>'
2106 <<
2107 <%auxFunction%>
2108 <%fname%> omc<%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then "impl"%>_<%fname%>(threadData_t *threadData<%funArgs |> VARIABLE(__) => ', <%expTypeArrayIf(ty)%> omc_<%CodegenUtil.crefStr(name)%>'%>)
2109 {
2110 <%varDecls%>
2111 <%funArgs |> VARIABLE(__) => rcAssignRetain(expTypeArrayIf(ty), '<%structVar%>._<%CodegenUtil.crefStr(name)%>', 'omc_<%CodegenUtil.crefStr(name)%>') ;separator=""%>
2112 omc_ret_ = <%structVar%>;
2113 <%rcDisown(structType, structVar)%><%varFrees%>
2114 return omc_ret_;
2115 }
2116 <%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then 'omctd_<%fname%> omc_<%fname%> = omcimpl_<%fname%>;'%>
2117
2118 <%boxedFn%>
2119 >>
2120 end functionBodyRecordConstructor;
2121
2122 242 template varInitRecord(Variable var, String prefix, Text &varDecls, Text &varFrees, Text &varInits, Text &auxFunction)
2123 "Generates code to initialize variables.
2124 Does not return anything: just appends declarations to buffers."
2125 ::=
2126 match var
2127 case var as VARIABLE(parallelism = NON_PARALLEL(__)) then
2128 let varName = '<%prefix%>._<%CodegenUtil.crefStr(var.name)%>'
2129 let initRecords = initRecordMembers(var, &varDecls, &varFrees, &varInits, &auxFunction)
2130 let &varInits += initRecords
2131 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, appendCurrentCrefPrefix(contextFunction, prefix + "."), &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2132 if instDims then
2133 let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2134 let defaultValue = varAllocDefaultValue(var, appendCurrentCrefPrefix(contextFunction, prefix + "."), varName, defaultAlloc, &varDecls, &varFrees, &varInits, &auxFunction)
2135 let &varInits += defaultValue
2136 ""
2137 else
2138 (match var.value
2139 case SOME(exp) then
2140 let defaultValue = '<%varName%> = <%daeExp(exp, appendCurrentCrefPrefix(contextFunction, prefix + "."), &varInits, &varDecls, &varFrees, &auxFunction)%>;<%\n%>'
2141 let &varInits += defaultValue
2142
2143 " "
2144 else
2145 "")
2146
2147 case var as FUNCTION_PTR(__) then
2148 ""
2149 else error(sourceInfo(), 'Unknown local variable type in record')
2150 end varInitRecord;
2151
2152 12462 template functionBodyBoxed(SimCodeFunction.Function fn, Boolean isSimulation)
2153 "Generates code for a boxed version of a function. Extracts the needed data
2154 from a function and calls functionBodyBoxedImpl"
2155 ::=
2156 let fname = match fn
2157 case FUNCTION(__)
2158 case EXTERNAL_FUNCTION(__)
2159 case RECORD_CONSTRUCTOR(__) then
2160 underscorePath(name)
2161 <<
2162 <%
2163 match fn
2164 case FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, functionArguments, outVars, visibility, isSimulation)
2165 case EXTERNAL_FUNCTION(__) then if not isBoxedFunction(fn) then functionBodyBoxedImpl(name, funArgs, outVars, visibility, isSimulation)
2166 case RECORD_CONSTRUCTOR(__) then boxRecordConstructor(fn, isSimulation)
2167 %>
2168 >>
2169 end functionBodyBoxed;
2170
2171 7057 template functionBodyBoxedImpl(Absyn.Path name, list<Variable> funargs, list<Variable> outvars, SCode.Visibility visibility, Boolean isSimulation)
2172 "Helper template for functionBodyBoxed, does all the real work."
2173 ::=
2174 let() = System.tmpTickReset(1)
2175 let()= System.tmpTickResetIndex(0,1) /* Boxed array indices */
2176 let fname = underscorePath(name)
2177 let retTypeBoxed = if outvars then 'modelica_metatype' else "void"
2178 let &varDecls = buffer ""
2179 let &varFrees = buffer ""
2180 let &varBox = buffer ""
2181 let &varUnbox = buffer ""
2182 let &auxFunction = buffer ""
2183 let args = (funargs |> arg => (", " + funArgUnbox(arg, &varDecls, &varFrees, &varBox, &auxFunction)))
2184 let &varBoxIgnore = buffer ""
2185 let &outputAllocIgnore = buffer ""
2186 let &varFreesIgnore = buffer ""
2187 let &auxFunctionIgnore = buffer ""
2188 let outputs = ( List.restOrEmpty(outvars) |> var hasindex i1 fromindex 1 =>
2189 match var
2190 case v as VARIABLE(__) then
2191 if mmcConstructorType(liftTypeWithDims(v.ty,v.instDims)) then
2192 let _ = varInit(var, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore)
2193 ", &" + funArgName(var)
2194 else
2195 ", out" + funArgName(var)
2196 case FUNCTION_PTR(__) then ", out" + funArgName(var)
2197 ; empty
2198 )
2199 let retvar = (match outvars
2200 case {} then ""
2201 case (v as VARIABLE(__))::_ then
2202 let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore)
2203 let out = ("out" + funArgName(v))
2204 let _ = funArgBox(out, funArgName(v), "", liftTypeWithDims(v.ty,v.instDims), &varUnbox, &varDecls, &varFrees)
2205 (if mmcConstructorType(liftTypeWithDims(v.ty,v.instDims)) then
2206 let &varDecls += 'modelica_metatype <%out%>;<%\n%>'
2207 out
2208 else
2209 funArgName(v))
2210 case v::_ then
2211 let _ = varInit(v, "", &varDecls, &outputAllocIgnore, &varFreesIgnore, &auxFunctionIgnore)
2212 funArgName(v)
2213 )
2214 let _ = (List.restOrEmpty(outvars) |> var as VARIABLE(__) =>
2215 let arg = funArgName(var)
2216 funArgBox('*out<%arg%>', arg, 'out<%arg%>', liftTypeWithDims(var.ty,var.instDims), &varUnbox, &varDecls, &varFrees)
2217 ; separator="\n")
2218 let &afterBody = buffer ""
2219 let prototype = functionPrototype(fname, funargs, outvars, true, visibility, isSimulation, false, afterBody)
2220 <<
2221 <%auxFunction%>
2222 <%prototype%>
2223 {
2224 <%varDecls%>
2225 <%addRootsTempArray()%>
2226 <%varBox%>
2227 <%match outvars case v::_ then '<%funArgName(v)%> = '%>omc_<%fname%>(threadData<%args%><%outputs%>);
2228 <%varUnbox%>
2229 <%varFrees%>
2230 <%match outvars case v::_ then 'return <%retvar%>;' else "return;"%>
2231 }
2232 <%afterBody%>
2233 >>
2234 end functionBodyBoxedImpl;
2235
2236 4254 template boxRecordConstructor(SimCodeFunction.Function fn, Boolean isSimulation)
2237 ::=
2238 let &auxFunction = buffer ""
2239 match fn
2240 case RECORD_CONSTRUCTOR(__) then
2241 let() = System.tmpTickReset(1)
2242 let fname = underscorePath(name)
2243 let retType = '<%fname%>_rettypeboxed'
2244 let funArgsStr = (funArgs |> var => match var
2245 case VARIABLE(__) then ", " + contextCrefNoPrevExp(name,contextFunction,&auxFunction)
2246 case FUNCTION_PTR(__) then ", " + name
2247 else error(sourceInfo(),"boxRecordConstructor:Unknown variable"))
2248 let start = daeExpMetaHelperBoxStart(incrementInt(listLength(funArgs), 1))
2249 <<
2250 <%if isSimulation then "" else match visibility case PROTECTED(__) then "PROTECTED_FUNCTION_STATIC "%>modelica_metatype boxptr<%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then "impl"%>_<%fname%>(threadData_t *threadData<%funArgs |> var => (", " + funArgBoxedDefinition(var))%>)
2251 {
2252 return omc_mk_box<%start%>3, &<%fname%>__desc<%funArgsStr%>);
2253 }
2254 <%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then 'boxptrtd_<%fname%> boxptr_<%fname%> = boxptrimpl_<%fname%>;'%>
2255 >>
2256 end boxRecordConstructor;
2257
2258 17117 template funArgUnbox(Variable var, Text &varDecls, Text &varFrees, Text &varBox, Text &auxFunction)
2259 ::=
2260 match var
2261 case VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then
2262 error(sourceInfo(), 'Trying to generate a boxed function with non protected parglobal array.')
2263 case VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then
2264 error(sourceInfo(), 'Trying to generate a boxed function with non protected parlocal array.')
2265 case VARIABLE(__) then
2266 let varName = contextCrefNoPrevExp(name,contextFunction,&auxFunction)
2267 unboxVariable(varName, ty, &varBox, &varDecls, &varFrees)
2268 case FUNCTION_PTR(__) then // Function pointers don't need to be boxed.
2269 '_<%name%>'
2270 end funArgUnbox;
2271
2272 50473 template unboxVariable(String varName, Type varType, Text &preExp, Text &varDecls, Text &varFrees)
2273 ::=
2274 match varType
2275 case T_STRING(__) then if metaModelicaRuntime() then varName else 'omc_unbox_string(<%varName%>)'
2276 case T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))
2277 case T_METATYPE(__)
2278 case T_METARECORD(__)
2279 case T_METAUNIONTYPE(__)
2280 case T_METALIST(__)
2281 case T_METAARRAY(__)
2282 case T_METAPOLYMORPHIC(__)
2283 case T_METAOPTION(__)
2284 case T_METATUPLE(__)
2285 case T_METABOXED(__) then varName
2286 case T_COMPLEX(complexClassType = RECORD(__)) then
2287 unboxRecord(varName, varType, &preExp, &varDecls, &varFrees)
2288 case T_ARRAY(__) then
2289 '*((base_array_t*)<%varName%>)'
2290 else
2291 let shortType = mmcTypeShort(varType)
2292 let ty = 'modelica_<%shortType%>'
2293 let tmpVar = tempDecl(ty, &varDecls, &varFrees)
2294 let &preExp += '<%tmpVar%> = omc_unbox_<%shortType%>(<%varName%>);<%\n%>'
2295 tmpVar
2296 end unboxVariable;
2297
2298 2192 template unboxRecord(String recordVar, Type ty, Text &preExp, Text &varDecls, Text &varFrees)
2299 ::=
2300 match ty
2301 case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then
2302 // The members are the box's, read out of it and not retained, so this record
2303 // has nothing to release: the box still owns what it points at.
2304 let &borrowed = buffer ""
2305 let tmpVar = tempDecl('<%underscorePath(path)%>', &varDecls, &borrowed)
2306 let &preExp += (vars |> TYPES_VAR(name = compname) hasindex offset fromindex 2 =>
2307 let varType = mmcTypeShort(ty)
2308 let untagTmp = tempDecl('modelica_metatype', &varDecls, &varFrees)
2309 //let offsetStr = incrementInt(i1, 1)
2310 let &unboxBuf = buffer ""
2311 let unboxStr = unboxVariable(untagTmp, ty, &unboxBuf, &varDecls, &varFrees)
2312 <<
2313 <%untagTmp%> = (OMC_BOX_FIELD(<%recordVar%>, <%offset%>));
2314 <%unboxBuf%>
2315 <%tmpVar%>._<%System.unquoteIdentifier(compname)%> = <%unboxStr%>;
2316 >>
2317 ;separator="\n")
2318 tmpVar
2319 end unboxRecord;
2320
2321 18245 template funArgBox(String outName, String varName, String condition, Type ty, Text &varUnbox, Text &varDecls, Text &varFrees)
2322 "Generates code to box a variable."
2323 ::=
2324 let constructorType = mmcConstructorType(ty)
2325 if constructorType then
2326 let constructor = mmcConstructor(ty, varName, &varUnbox, &varDecls, &varFrees)
2327 let &varUnbox += if condition then 'if (<%condition%>) { <%outName%> = <%constructor%>; }<%\n%>' else '<%outName%> = <%constructor%>;<%\n%>'
2328 outName
2329 else // Some types don't need to be boxed, since they're already boxed.
2330 let &varUnbox += '/* skip box <%varName%>; <%unparseType(ty)%> */<%\n%>'
2331 varName
2332 end funArgBox;
2333
2334 21388 template mmcConstructorType(Type type)
2335 ::=
2336 match type
2337 case T_INTEGER(__)
2338 case T_BOOL(__)
2339 case T_REAL(__)
2340 case T_ENUMERATION(__)
2341 case T_ARRAY(__)
2342 case T_COMPLEX(complexClassType = RECORD(__)) then 'modelica_metatype'
2343 // A counted string is a type of its own, so a boxed wrapper has to box it
2344 // like the rest; a MetaModelica string already is a metatype.
2345 case T_STRING(__) then if metaModelicaRuntime() then "" else 'modelica_metatype'
2346 end mmcConstructorType;
2347
2348 15353 template mmcConstructor(Type type, String varName, Text &preExp, Text &varDecls, Text &varFrees)
2349 ::=
2350 match type
2351 case T_INTEGER(__) then 'omc_mk_icon(<%varName%>)'
2352 case T_BOOL(__) then 'omc_mk_icon(<%varName%>)'
2353 case T_REAL(__) then 'omc_mk_rcon(<%varName%>)'
2354 case T_STRING(__) then 'omc_mk_string(<%varName%>)'
2355 case T_ENUMERATION(__) then 'omc_mk_icon(<%varName%>)'
2356 case T_ARRAY(__) then 'omc_mk_modelica_array(<%varName%>)'
2357 case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then
2358 let varCount = daeExpMetaHelperBoxStart(incrementInt(listLength(vars), 1))
2359 let varsStr = (vars |> var as TYPES_VAR(__) =>
2360 let tmp = tempDecl("modelica_metatype", &varDecls, &varFrees)
2361 let varname = '<%varName%>._<%name%>'
2362 ", " + funArgBox(tmp, varname, "", ty, &preExp, &varDecls, &varFrees)
2363 )
2364 'omc_mk_box<%varCount%>3, &<%underscorePath(path)%>__desc<%varsStr%>)'
2365 case T_COMPLEX(__) then 'omc_mk_box(<%varName%>)'
2366 end mmcConstructor;
2367
2368 198 template readInVar(Variable var)
2369 "Generates code for reading a variable from inArgs."
2370 ::=
2371 let &auxFunction = buffer ""
2372 match var
2373 case VARIABLE(name=cr, ty=T_COMPLEX(complexClassType=RECORD(__))) then
2374 <<
2375 if (read_modelica_record(&inArgs, <%readInVarRecordMembers(ty, contextCrefNoPrevExp(cr,contextFunction,&auxFunction))%>)) return 1;
2376 >>
2377 case VARIABLE(name=cr, ty=T_STRING(__)) then
2378 <<
2379 if (read_<%expTypeArrayIf(ty)%>(&inArgs, <%if not metaModelicaRuntime() then '(<%expTypeArrayIf(ty)%>*)'%> &<%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>)) return 1;
2380 >>
2381 case VARIABLE(__) then
2382 <<
2383 if (read_<%expTypeArrayIf(ty)%>(&inArgs, &<%contextCrefNoPrevExp(name,contextFunction,&auxFunction)%>)) return 1;
2384 >>
2385 end readInVar;
2386
2387
2388 12 template readInVarRecordMembers(Type type, String prefix)
2389 "Helper to readInVar."
2390 ::=
2391 match type
2392 case T_COMPLEX(varLst=vl) then
2393 (vl |> subvar as TYPES_VAR(__) =>
2394 match ty case T_COMPLEX(__) then
2395 let newPrefix = '<%prefix%>._<%subvar.name%>'
2396 readInVarRecordMembers(ty, newPrefix)
2397 else
2398 '&(<%prefix%>._<%subvar.name%>)'
2399 ;separator=", ")
2400 end readInVarRecordMembers;
2401
2402
2403 226 template writeOutVar(Variable var)
2404 "Generates code for writing a variable to outVar."
2405
2406 ::=
2407 match var
2408 case VARIABLE(ty=T_COMPLEX(complexClassType=RECORD(__))) then
2409 <<
2410 write_modelica_record(outVar, <%writeOutVarRecordMembers(ty, funArgName(var))%>);
2411 >>
2412 case VARIABLE(__) then
2413
2414 <<
2415 write_<%varType(var)%>(outVar, &<%funArgName(var)%>);
2416 >>
2417 end writeOutVar;
2418
2419
2420 11 template writeOutVarRecordMembers(Type type, String prefix)
2421 "Helper to writeOutVar."
2422 ::=
2423 match type
2424 case T_COMPLEX(varLst=vl, complexClassType=n) then
2425 let basename = underscorePath(ClassInfUtil.getStateName(n))
2426 let args = (vl |> subvar as TYPES_VAR(__) =>
2427 match ty case T_COMPLEX(__) then
2428 let newPrefix = '<%prefix%>._<%subvar.name%>'
2429 '<%expTypeRW(ty)%>, <%writeOutVarRecordMembers(ty, newPrefix)%>'
2430 else
2431 '<%expTypeRW(ty)%>, &(<%prefix%>._<%subvar.name%>)'
2432 ;separator=", ")
2433 <<
2434 &<%basename%>__desc<%if args then ', <%args%>'%>, TYPE_DESC_NONE
2435 >>
2436 end writeOutVarRecordMembers;
2437
2438 36448 template varInitLocal(Variable var, SimCodeFunction.Function fn, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction)
2439 "varInit, except that a small array of constant size (stackArrayLength) is
2440 stored on the stack. Array assignments copy, so its data never outlives the
2441 function; temporaries may share it, so the dimensions are an immortal
2442 reference-counted block."
2443 ::=
2444 match var
2445 case VARIABLE(__) then
2446 let n = stackArrayLength(var, fn)
2447 if intGt(stackArrayLength(var, fn), 0) then
2448 let varName = contextCrefNoPrevExp(name, contextFunction, &auxFunction)
2449 let type = expTypeShort(ty)
2450 let &varDecls +=
2451 <<
2452 modelica_<%type%> <%varName%>_data[<%n%>];
2453 static struct { mmc_uint_t rc; _index_t d[<%listLength(instDims)%>]; } <%varName%>_dims = { OMC_RC_IMMORTAL, {<%instDims |> d => match d case DIM_INTEGER(__) then integer ;separator=", "%>} };
2454 <%type%>_array <%varName%> = {.ndims = <%listLength(instDims)%>, .dim_size = <%varName%>_dims.d, .data = <%varName%>_data, .flexible = 0, .owns_data = 0};<%\n%>
2455 >>
2456 let &varInits += (match value
2457 case SOME(rhs_exp) then
2458 let &preExp = buffer ""
2459 let rhs = daeExp(rhs_exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
2460 '<%preExp%><%type%>_array_copy_data(<%rhs%>, <%varName%>);<%\n%>'
2461 else 'memset(<%varName%>_data, 0, sizeof(<%varName%>_data));<%\n%>')
2462 ""
2463 else varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction)
2464 else varInit(var, "", &varDecls, &varInits, &varFrees, &auxFunction)
2465 end varInitLocal;
2466
2467 48996 template varInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction)
2468 "Generates code to initialize variables.
2469 Does not return anything: just appends declarations to buffers."
2470 ::=
2471 match var
2472 case var as VARIABLE(parallelism = NON_PARALLEL(__)) then
2473 let varName = contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)
2474 let typeNameFull = varType(var)
2475 let initVar = match typeNameFull case "modelica_metatype"
2476 case "modelica_string" then ' = NULL'
2477 else ''
2478 let &varDecls += if not outStruct then '<%typeNameFull%> <%varName%><%if rcKind(typeNameFull) then rcZeroInit(typeNameFull) else initVar%>;<%\n%>' //else ""
2479 let &varFrees += if not outStruct then rcRelease(typeNameFull, varName) else ""
2480
2481 if instDims then
2482 let &varInits += arrayVarAllocInit(var.name, var.ty, instDims, var.value, var.bind_from_outside, var.kind, contextFunction, &varDecls, &varFrees, &auxFunction)
2483 ""
2484 else if isRecordType(var.ty) then
2485 let &varInits += recordVarAllocInit(var.value, var.name, var.bind_from_outside, var.ty, contextFunction, &varDecls, &varFrees, &auxFunction)
2486 ""
2487 else
2488 let &varInits += simpleVarInit(typeNameFull, var.value, var.name, var.bind_from_outside, contextFunction, &varDecls, &varFrees, &auxFunction)
2489 ""
2490
2491 //mahge: OpenCL/CUDA GPU variables.
2492 case var as VARIABLE(__) then
2493 parVarInit(var, outStruct, &varDecls, &varInits, &varFrees, &auxFunction)
2494
2495 case var as FUNCTION_PTR(__) then
2496 let &varDecls += 'modelica_fnptr _<%name%>;<%\n%>'
2497 let varInitText = (match defaultValue
2498 case SOME(exp) then
2499 let v = daeExp(exp, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)
2500 '_<%name%> = <%v%>;<%\n%>')
2501 let &varInits += varInitText
2502 ""
2503 else error(sourceInfo(), 'Unknown local variable type')
2504 end varInit;
2505
2506 /* ParModelica Extension. */
2507 ✗ template parVarInit(Variable var, String outStruct, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction)
2508 "Generates code to initialize ParModelica variables.
2509 Does not return anything: just appends declarations to buffers."
2510 ::=
2511 match var
2512 case var as VARIABLE(parallelism = PARGLOBAL(__)) then
2513 let varName = '<%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'
2514
2515 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2516
2517 if instDims then
2518 let &varDecls += 'device_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>'
2519 let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2520 let defaultValue = varAllocDefaultValue(var, contextFunction, varName, defaultAlloc, &varDecls, &varFrees, &varInits, &auxFunction)
2521 let &varInits += defaultValue
2522
2523 // let &varFrees += 'free_device_array(&<%varName%>);<%\n%>'
2524 ""
2525 else
2526 (match var.value
2527 case SOME(exp) then
2528 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2529 let defaultValue = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>;<%\n%>'
2530 let &varInits += defaultValue
2531
2532 " "
2533 else
2534 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2535 "")
2536
2537 case var as VARIABLE(parallelism = PARLOCAL(__)) then
2538 let varName = '<%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'
2539
2540 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2541 if instDims then
2542 let &varDecls += 'device_local_<%expTypeShort(var.ty)%>_array <%varName%>;<%\n%>'
2543 let defaultAlloc = 'alloc_device_local_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2544 let defaultValue = varAllocDefaultValue(var, contextFunction, varName, defaultAlloc, &varDecls, &varFrees, &varInits, &auxFunction)
2545 let &varInits += defaultValue
2546
2547 // let &varFrees += 'free_device_array(&<%varName%>);<%\n%>'
2548 ""
2549 else
2550 (match var.value
2551 case SOME(exp) then
2552 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2553 let defaultValue = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>;<%\n%>'
2554 let &varInits += defaultValue
2555
2556 " "
2557 else
2558 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2559 "")
2560
2561 else
2562 let &varDecls += '#error Unknown parallel variable type<%\n%>'
2563 error(sourceInfo(), 'parVarInit:error Unknown parallel variable type')
2564 end parVarInit;
2565
2566 ✗ template varInitParallel(Variable var, String outStruct, Integer i, Text &varDecls, Text &varInits, Text &varFrees, Text &auxFunction)
2567 "Generates code to initialize variables in PARALLEL FUNCTIONS.
2568 Does not return anything: just appends declarations to buffers."
2569 ::=
2570 match var
2571 case var as VARIABLE(__) then
2572 let &varDecls += if not outStruct then '<%varType(var)%> <%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>;<%\n%>' //else ""
2573 let varName = if outStruct then '<%outStruct%>.targ<%i%>' else '<%contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)%>'
2574
2575 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2576 if instDims then
2577 let defaultAlloc = 'alloc_<%expTypeShort(var.ty)%>_array_c99_<%listLength(instDims)%>(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>, memory_state);<%\n%>'
2578 let defaultValue = varAllocDefaultValue(var, contextFunction, varName, defaultAlloc, &varDecls, &varFrees, &varInits, &auxFunction)
2579 let &varInits += defaultValue
2580 " "
2581 else
2582 (match var.value
2583 case SOME(exp) then
2584 let defaultValue = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%> = <%daeExp(exp, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>;<%\n%>'
2585 let &varInits += defaultValue
2586 " "
2587 else
2588 "")
2589 case var as FUNCTION_PTR(__) then
2590 ""
2591 else
2592 let &varDecls += '#error Unknown local variable type<%\n%>'
2593 error(sourceInfo(), 'varInitParallel:error Unknown local variable type')
2594 end varInitParallel;
2595
2596 ✗ template varAllocDefaultValue(Variable var, Context context, String lhsVarName, Text allocNoDefault, Text &varDecls, Text &varFrees, Text &varInits, Text &auxFunction)
2597 ::=
2598 match var
2599 case var as VARIABLE(__) then
2600 match value
2601 // TODO make me error and see what fails
2602 case SOME(CREF(componentRef = cr)) then
2603 let &sub = buffer ""
2604 'copy_<%expTypeShort(var.ty)%>_array(<%contextCref(cr,context, &varInits, &varDecls, &varFrees, &auxFunction, &sub)%>, &<%lhsVarName%>);<%\n%>'
2605 case SOME(arr as ARRAY(ty = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state)))) then
2606 let &varInits += allocNoDefault
2607 let varName = contextCrefNoPrevExp(var.name, context, &auxFunction)
2608 let rec_name = '<%underscorePath(ClassInfUtil.getStateName(record_state))%>'
2609 let &preExp = buffer ""
2610 let params = (arr.array |> e hasindex i1 fromindex 1 =>
2611 let prefix = if arr.scalar then '(<%expTypeFromExpModelica(e)%>)' else '&'
2612 '<%rec_name%>_array_get(<%varName%>, 1, <%i1%>) = <%prefix%><%daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)%>;'
2613 ;separator="\n")
2614 <<
2615 <%preExp%>
2616 <%params%>
2617 >>
2618 // Treat shared array literals like other arrays, i.e. copy them. Array
2619 // outputs in functions might otherwise end up pointing to shared literals,
2620 // causing a segfault if such an array is then assigned to.
2621 case SOME(arr as SHARED_LITERAL(__))
2622 case SOME(arr as ARRAY(__)) then
2623 let arrayExp = '<%daeExp(arr, context, &varInits, &varDecls, &varFrees, &auxFunction)%>'
2624 'copy_<%expTypeShort(var.ty)%>_array(<%arrayExp%>, &<%lhsVarName%>);<%\n%>'
2625 case SOME(exp) then
2626 '<%lhsVarName%> = <%daeExp(exp, context, &varInits, &varDecls, &varFrees, &auxFunction)%>;<%\n%>'
2627 else
2628 let &varInits += allocNoDefault
2629 ""
2630 end varAllocDefaultValue;
2631
2632 1849 template varOutput(Variable var)
2633 "Generates code to copy result value from a function to dest."
2634 ::=
2635 match var
2636 case FUNCTION_PTR(__) then
2637 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = (modelica_fnptr)<%funArgName(var)%>; }<%\n%>'
2638 case VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then
2639 // If the info (for parallel arrays) is NULL, the output is an array with unknown dimensions. Copy the array.
2640 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->info == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {<%expTypeShort(var.ty)%>_array_copy_data(<%funArgName(var)%>, *out<%funArgName(var)%>);} }<%\n%>'
2641 case VARIABLE(ty=T_ARRAY(__)) then
2642 // If the dim_size is NULL, the output is an array with unknown dimensions. Copy the array.
2643 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {<%expTypeShort(var.ty)%>_array_copy_data(<%funArgName(var)%>, *out<%funArgName(var)%>);} }<%\n%>'
2644 case VARIABLE(parallelism = PARGLOBAL(__)) then
2645 /*Seems like we still get an array var with the wrong type here. It have instdims though >_<. TODO I guess*/
2646 if instDims then
2647 <<
2648 if (out<%funArgName(var)%>) {
2649 if (out<%funArgName(var)%>->info == NULL) {
2650 omc_assert(threadData, omc_dummyFileInfo, "Unknown size parallel array.");
2651 }
2652 else {
2653 <%expTypeShort(var.ty)%>_array_copy_data(<%funArgName(var)%>, *out<%funArgName(var)%>);
2654 }
2655 }<%\n%>
2656 >>
2657 else
2658 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>'
2659 case VARIABLE(ty=T_STRING(__), instDims={}) then
2660 // The out slot owns a reference too, so what it held is released.
2661 if rcKind("modelica_string") then
2662 'if (out<%funArgName(var)%>) { omc_string_move(out<%funArgName(var)%>, <%funArgName(var)%>); omc_string_disown(<%funArgName(var)%>); }<%\n%>'
2663 else
2664 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>'
2665 case v as VARIABLE(ty=T_COMPLEX(complexClassType=RECORD(__)), instDims={}) then
2666 // The same move: the out slot's own members go first.
2667 let recTy = varType(v)
2668 if rcKind(recTy) then
2669 'if (out<%funArgName(var)%>) { <%recTy%>_release((*out<%funArgName(var)%>)); *out<%funArgName(var)%> = <%funArgName(var)%>; <%recTy%>_disown(<%funArgName(var)%>); }<%\n%>'
2670 else
2671 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>'
2672 case VARIABLE(__) then
2673 /*Seems like we still get an array var with the wrong type here. It have instdims though >_<. TODO I guess*/
2674 if instDims then
2675 'if (out<%funArgName(var)%>) { if (out<%funArgName(var)%>->dim_size == NULL) {copy_<%expTypeShort(var.ty)%>_array(<%funArgName(var)%>, out<%funArgName(var)%>);} else {<%expTypeShort(var.ty)%>_array_copy_data(<%funArgName(var)%>, *out<%funArgName(var)%>);} }<%\n%>'
2676 else
2677 'if (out<%funArgName(var)%>) { *out<%funArgName(var)%> = <%funArgName(var)%>; }<%\n%>'
2678 else error(sourceInfo(), 'varOutput:error Unknown variable type as output')
2679 end varOutput;
2680
2681 ✗ template varOutputKernelInterface(Variable var, String dest, Integer ix, Text &varDecls, Text &varFrees,
2682 Text &varInits, Text &varCopy, Text &varAssign, Text &auxFunction)
2683 "Generates code to copy result value from a function to dest."
2684 ::=
2685 match var
2686 case var as VARIABLE(parallelism = PARGLOBAL(__)) then
2687 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
2688 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2689 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2690 if instDims then
2691 let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2692 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2693 ""
2694 else
2695 let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>'
2696 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2697 ""
2698
2699 case var as VARIABLE(parallelism = PARLOCAL(__)) then
2700 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
2701 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2702 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2703 if instDims then
2704 let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2705 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2706 ""
2707 else
2708 let &varInits += '<%varName%> = ocl_device_alloc(sizeof(modelica_<%expTypeShort(var.ty)%>));<%\n%>'
2709 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2710 ""
2711
2712 case var as VARIABLE(__) then
2713 let varName = '<%contextCrefNoPrevExp(var.name,contextFunction,&auxFunction)%>'
2714 let &varDecls += '<%varType(var)%> <%varName%>;<%\n%>'
2715 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &varInits, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2716 if instDims then
2717 let &varInits += 'alloc_<%expTypeShort(var.ty)%>_array(&<%varName%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2718 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2719 ""
2720 else
2721 let initRecords = initRecordMembers(var, &varDecls, &varFrees, &varInits, &auxFunction)
2722 let &varInits += initRecords
2723 let &varAssign += '<%dest%>.c<%ix%> = <%varName%>;<%\n%>'
2724 ""
2725 case var as FUNCTION_PTR(__) then
2726 let &varAssign += '<%dest%>.c<%ix%> = (modelica_fnptr) _<%var.name%>;<%\n%>'
2727 ""
2728 end varOutputKernelInterface;
2729
2730 242 template initRecordMembers(Variable var, Text &varDecls, Text &varFrees, Text &varInits, Text &auxFunction)
2731 ::=
2732 match var
2733 case VARIABLE(ty = T_COMPLEX(complexClassType = RECORD(__), varLst = members)) then
2734 let &preExp = buffer ""
2735 let &ctor_suffix = buffer ""
2736 let varName = contextCrefNoPrevExp(name, contextFunction, &auxFunction)
2737 let typeName = varType(var)
2738
2739 let ctor_additional_inputs = (ty.varLst |> sv hasindex i1 fromindex 1 =>
2740 recordInitOutsideBindings(sv, i1, &ctor_suffix, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction); empty /* increase the counter! */
2741 )
2742 <<
2743 <%preExp%>
2744 <%typeName%><%ctor_suffix%>_construct(threadData, <%varName%><%ctor_additional_inputs%>);<%\n%>
2745 >>
2746 end initRecordMembers;
2747
2748 3021 template extVarName(ComponentRef cr)
2749 ::= '_<%crefToMStr(appendStringFirstIdent("_ext", cr))%>'
2750 end extVarName;
2751
2752 555 template extFunCall(SimCodeFunction.Function fun, Text &preExp, Text &varDecls, Text &varFrees, Text &varInit, Text &auxFunction)
2753 "Generates the call to an external function."
2754 ::=
2755 match fun
2756 case EXTERNAL_FUNCTION(__) then
2757 match language
2758 case "BUILTIN"
2759 case "C" then extFunCallC(fun, &preExp, &varDecls, &varFrees, &auxFunction)
2760 case "FORTRAN 77" then extFunCallF77(fun, &preExp, &varDecls, &varFrees, &varInit, &auxFunction)
2761 else error(sourceInfo(), 'Unsupported external language: <%language%>')
2762 end extFunCall;
2763
2764 543 template extFunCallC(SimCodeFunction.Function fun, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
2765 "Generates the call to an external C function."
2766 ::=
2767 match fun
2768 case EXTERNAL_FUNCTION(__) then
2769 /* adpro: 2011-06-24 do vardecls -> extArgs as there might be some sets in there! */
2770 let &preExp += (List.union(extArgs, extArgs) |> arg => extFunCallVardecl(arg, &varDecls, &varFrees, &auxFunction, false) ;separator="\n") + "\n"
2771 let _ = (biVars |> bivar => extFunCallBiVar(bivar, &preExp, &varDecls, &varFrees, &auxFunction) ;separator="\n")
2772 let fname = if dynamicLoad then 'ptr_<%extFunctionName(extName, language)%>' else '<%extName%>'
2773 let dynamicCheck = if dynamicLoad then
2774 <<
2775 if(<%fname%>==NULL)
2776 {
2777 FILE_INFO info = {<%infoArgs(info)%>};
2778 omc_terminate(info, "dynamic external function <%extFunctionName(extName, language)%> not set!");
2779 } else
2780 >>
2781 else ''
2782 let args = (extArgs |> arg => extArg(arg, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
2783 let returnAssign = match extReturn case SIMEXTARG(cref=c) then
2784 '<%extVarName(c)%> = '
2785 else
2786 ""
2787 /* https://github.com/OpenModelica/OpenModelica/issues/9681
2788 * ModelicaError should be handled as assert failing with AssertionLevel = error
2789 */
2790 let modelicaError = match extName
2791 case "ModelicaError" then
2792 <<
2793 FILE_INFO info = {<%infoArgs(info)%>};
2794 omc_assert(threadData, info, <%args%>);
2795 >> else ""
2796
2797 <<
2798 <%match extReturn case SIMEXTARG(__) then extFunCallVardecl(extReturn, &varDecls, &varFrees, &auxFunction, true)%>
2799 <%dynamicCheck%>
2800 <%if modelicaError then '<%modelicaError%>' else '<%returnAssign%><%fname%>(<%args%>);'%>
2801 <%extArgs |> arg => extFunCallVarcopy(arg, &auxFunction) ;separator="\n"%>
2802 <%match extReturn case SIMEXTARG(__) then extFunCallVarcopy(extReturn, &auxFunction)%>
2803 <%extArgs |> arg => extFunCallFree(arg, &auxFunction)%>
2804 >>
2805 end extFunCallC;
2806
2807 1374 template extFunCallFree(SimExtArg arg, Text &auxFunction)
2808 "Drops what extArg allocated to hand the external function C89 data. Only the
2809 string case allocates: data_of_string_c89_array builds an array of char* out of
2810 the counted strings, the others hand over the array's own buffer."
2811 ::=
2812 match arg
2813 case SIMEXTARG(cref=c, isArray=true, type_=t) then
2814 match expTypeShort(t)
2815 case "string" then
2816 let cVarName = System.stringReplace(contextCrefNoPrevExp(c, contextFunction, &auxFunction), ".", "_")
2817 'omc_rc_release((void*) <%cVarName%>_c89);<%\n%>'
2818 else ""
2819 else ""
2820 end extFunCallFree;
2821
2822 12 template extFunCallF77(SimCodeFunction.Function fun, Text &preExp, Text &varDecls, Text &varFrees, Text &varInit, Text &auxFunction)
2823 "Generates the call to an external Fortran 77 function."
2824 ::=
2825 match fun
2826 case EXTERNAL_FUNCTION(__) then
2827 /* adpro: 2011-06-24 do vardecls -> bivar -> extArgs as there might be some sets in there! */
2828 let &varDecls += '/* extFunCallF77: varDecs */<%\n%>'
2829 let varDecs = (List.union(extArgs, extArgs) |> arg => extFunCallVardeclF77(arg, &varDecls, &varFrees, &auxFunction) ;separator="\n")
2830 let &varDecls += '/* extFunCallF77: biVarDecs */<%\n%>'
2831 let &preExp += '/* extFunCallF77: biVarDecs */<%\n%>'
2832 let biVarDecs = (biVars |> arg => extFunCallBiVarF77(arg, &varInit, &varDecls, &varFrees, &auxFunction) ;separator="\n")
2833 let &varDecls += '/* extFunCallF77: args */<%\n%>'
2834 let &preExp += '/* extFunCallF77: args */<%\n%>'
2835 let args = (extArgs |> arg => extArgF77(arg, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
2836 let &preExp += '/* extFunCallF77: end args */<%\n%>'
2837 let returnAssign = match extReturn case SIMEXTARG(cref=c) then
2838 '<%extVarName(c)%> = '
2839 else
2840 ""
2841 <<
2842 <%varDecs%>
2843 <%biVarDecs%>
2844 /* extFunCallF77: extReturn */
2845 <%match extReturn case SIMEXTARG(__) then extFunCallVardeclF77(extReturn, &varDecls, &varFrees, &auxFunction)%>
2846 /* extFunCallF77: CALL */
2847 <%returnAssign%><%extName%>_(<%args%>);
2848 /* extFunCallF77: copy args */
2849 <%List.union(extArgs,extArgs) |> arg => extFunCallVarcopyF77(arg, &auxFunction) ;separator="\n"%>
2850 /* extFunCallF77: copy return */
2851 <%match extReturn case SIMEXTARG(__) then extFunCallVarcopyF77(extReturn, &auxFunction)%>
2852 >>
2853
2854 end extFunCallF77;
2855
2856 1857 template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &varFrees, Text &auxFunction, Boolean isReturn)
2857 "Helper to extFunCall. Generate variable declarations."
2858 ::=
2859 match arg
2860 // Input array argument
2861 case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
2862 match expTypeShort(ty)
2863 case "integer" then
2864 let argName = '<%contextCrefNoPrevExp(c, contextFunction, &auxFunction)%>'
2865 let cVarName = System.stringReplace(argName, ".", "_") + "_packed"
2866 let &varDecls += 'integer_array <%cVarName%><%rcZeroInit("integer_array")%>;<%\n%>'
2867 let &varFrees += rcRelease("integer_array", cVarName)
2868 'pack_alloc_integer_array(&<%argName%>, &<%cVarName%>);<%\n%>'
2869 else ""
2870
2871 // Array argument (string)
2872 case SIMEXTARG(isInput = false, isArray = true, type_ = ty, cref = c) then
2873 match expTypeShort(ty)
2874 case "string" then
2875 'fill_string_array(&<%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%>, omc_string_uninitialized);<%\n%>'
2876 else ""
2877
2878 // Input scalar argument
2879 case SIMEXTARG(isInput = true, isArray = false, type_ = ty, cref = c) then
2880 match ty
2881 case T_STRING(__) then
2882 ""
2883 case T_FUNCTION_REFERENCE_VAR(__) then
2884 match c
2885 case CREF_IDENT(__) then
2886 let &varDecls += 'modelica_fnptr <%extVarName(c)%>;<%\n%>'
2887 <<
2888 if (OMC_BOX_FIELD(_<%ident%>, 2)) {
2889 <%generateThrow()%> /* The FFI does not allow closures */
2890 }
2891 <%extVarName(c)%> = <%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then '*(void**)' %>OMC_BOX_FIELD(_<%ident%>, 1);
2892 >>
2893 else
2894 error(sourceInfo(), 'Got function pointer that is not a CREF_IDENT: <%CodegenUtil.crefStr(c)%>, <%unparseType(ty)%>')
2895 else
2896 let lhs = extVarName(c)
2897 let rhs = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
2898 match ty
2899 case T_COMPLEX(complexClassType=RECORD(__)) then
2900 let rec_typename = expTypeShort(ty)
2901 let &varDecls += '<%rec_typename%>_external <%lhs%>;<%\n%>'
2902 <<
2903 <%rec_typename%>_copy_to_external(<%rhs%>, <%lhs%>);
2904 >>
2905 else
2906 let &varDecls += '<%extType(ty,true,false,false)%> <%lhs%>;<%\n%>'
2907 <<
2908 <%lhs%> = (<%extType(ty,true,false,false)%>) <%rhs%>;
2909 >>
2910
2911 // Output Scalar (outputIndex > 0)
2912 case SIMEXTARG(outputIndex = oi, isArray = false, type_ = ty, cref = c) then
2913 match oi case 0 then
2914 ""
2915 else
2916 match ty
2917 case T_COMPLEX(complexClassType=RECORD(__)) then
2918 let rec_typename = expTypeShort(ty)
2919 let &varDecls += '<%rec_typename%>_external <%extVarName(c)%>;<%\n%>'
2920 ""
2921 else
2922 let &varDecls += '<%extType(ty,true,false,true)%> <%extVarName(c)%>;<%\n%>'
2923 ""
2924 end extFunCallVardecl;
2925
2926 86 template extFunCallVardeclF77(SimExtArg arg, Text &varDecls, Text &varFrees, Text &auxFunction)
2927 ::=
2928 match arg
2929 case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
2930 let arrTy = expTypeArrayIf(ty)
2931 let &varDecls += '<%arrTy%> <%extVarName(c)%><%rcZeroInit(arrTy)%>;<%\n%>'
2932 let &varFrees += rcRelease(arrTy, extVarName(c))
2933 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);'
2934 case ea as SIMEXTARG(outputIndex = oi, isArray = ia, type_= ty, cref = c) then
2935 match oi case 0 then "" else
2936 match ia
2937 case false then
2938 let default_val = typeDefaultValue(ty)
2939 let default_exp = if ea.hasBinding then "" else match default_val case "" then "" else ' = <%default_val%>'
2940 let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%><%default_exp%>;<%\n%>'
2941 ""
2942 else
2943 let arrTy = expTypeArrayIf(ty)
2944 let &varDecls += '<%arrTy%> <%extVarName(c)%><%rcZeroInit(arrTy)%>;<%\n%>'
2945 let &varFrees += rcRelease(arrTy, extVarName(c))
2946 'convert_alloc_<%expTypeArray(ty)%>_to_f77(&<%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%>, &<%extVarName(c)%>);'
2947 case SIMEXTARG(type_ = ty, cref = c) then
2948 let &varDecls += '<%extTypeF77(ty,false)%> <%extVarName(c)%>;<%\n%>'
2949 ""
2950 end extFunCallVardeclF77;
2951
2952 15448 template boolStrC(Boolean v)
2953 ::= if v then '1 /* true */' else '0 /* false */'
2954 end boolStrC;
2955
2956 25 template typeDefaultValue(DAE.Type ty)
2957 ::=
2958 match ty
2959 case ty as T_INTEGER(__) then '0'
2960 case ty as T_REAL(__) then '0.0'
2961 case ty as T_BOOL(__) then boolStrC(false)
2962 case ty as T_STRING(__) then '0' /* Always segfault is better than only sometimes segfault :) */
2963 else ""
2964 end typeDefaultValue;
2965
2966 1 template extFunCallBiVar(Variable var, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
2967 ::=
2968 match var
2969 case var as VARIABLE(__) then
2970 let var_name = contextCrefNoPrevExp(name, contextFunction, &auxFunction)
2971 let zeroInit = if instDims then rcZeroInit(varType(var))
2972 let &varDecls += '<%varType(var)%> <%var_name%><%zeroInit%>;<%\n%>'
2973 let defaultValue = match value
2974 case SOME(v) then
2975 '<%daeExp(v, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)%>'
2976 else ""
2977 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
2978 if instDims then
2979 let type = expTypeArray(var.ty)
2980 let &varFrees += rcRelease(type, var_name)
2981 let &preExp += if defaultValue then 'copy_<%type%>(<%defaultValue%>, &<%var_name%>);<%\n%>' else 'alloc_<%type%>(&<%var_name%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
2982 ""
2983 else
2984 let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' else ''
2985 ""
2986 end extFunCallBiVar;
2987
2988 44 template extFunCallBiVarF77(Variable var, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
2989 ::=
2990 match var
2991 case var as VARIABLE(__) then
2992 let var_name = contextCrefNoPrevExp(name,contextFunction,&auxFunction)
2993 let zeroInit = if instDims then rcZeroInit(varType(var))
2994 let &varDecls += '<%varType(var)%> <%var_name%><%zeroInit%>;<%\n%>'
2995 let &varDecls += '<%varType(var)%> <%extVarName(name)%><%zeroInit%>;<%\n%>'
2996 let defaultValue = match value
2997 case SOME(v) then
2998 '<%daeExp(v, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)%>'
2999 else ""
3000 let instDimsInit = (instDims |> dim => '(_index_t)<%dimension(dim, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
3001 if instDims then
3002 let type = expTypeArray(var.ty)
3003 let &varFrees += rcRelease(type, var_name)
3004 let &varFrees += rcRelease(type, extVarName(name))
3005 let &preExp += if defaultValue then 'copy_<%type%>(<%defaultValue%>, &<%var_name%>);<%\n%>' else 'alloc_<%type%>(&<%var_name%>, <%listLength(instDims)%>, <%instDimsInit%>);<%\n%>'
3006 let &preExp += 'convert_alloc_<%type%>_to_f77(&<%var_name%>, &<%extVarName(name)%>);<%\n%>'
3007 ""
3008 else
3009 let &preExp += if defaultValue then '<%var_name%> = <%defaultValue%>;<%\n%>' else ''
3010 ""
3011 end extFunCallBiVarF77;
3012
3013 299 template extFunCallVarcopy(SimExtArg arg, Text &auxFunction)
3014 "Helper to extFunCall. Unpack/copy for output of external function call."
3015 ::=
3016 match arg
3017 // Not an output
3018 case SIMEXTARG(outputIndex=0) then ""
3019
3020 // Array output
3021 case SIMEXTARG(outputIndex=oi, isInput=isInput, isArray=true, cref=c, type_=ty) then
3022 let var_name = contextCrefNoPrevExp(c, contextFunction, &auxFunction)
3023 match expTypeShort(ty)
3024 case "integer" then
3025 if isInput then
3026 'unpack_copy_integer_array(&<%var_name%>_packed, &<%var_name%>);'
3027 else
3028 'unpack_integer_array(&<%var_name%>);'
3029 case "string" then 'unpack_string_array(&<%var_name%>, <%var_name%>_c89);'
3030 else ""
3031
3032 // Scalar record output
3033 case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty as T_COMPLEX(complexClassType=RECORD(__)), cref=c) then
3034 let rhs = extVarName(c)
3035 let lhs = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
3036 let rec_typename = expTypeShort(ty)
3037 <<
3038 <%expTypeShort(ty)%>_copy_from_external(<%rhs%>, <%lhs%>);
3039 >>
3040
3041 // Scalar output
3042 case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then
3043 let cr = '<%extVarName(c)%>'
3044 <<
3045 <%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%> = (<%expTypeModelica(ty)%>)<%
3046 match ty
3047 case T_STRING(__) then 'omc_string_new(<%cr%>)'
3048 else cr%>;
3049 >>
3050 end extFunCallVarcopy;
3051
3052 87 template extFunCallVarcopyF77(SimExtArg arg, Text &auxFunction)
3053 "Generates code to copy results from output variables into the out struct.
3054 Helper to extFunCallF77."
3055 ::=
3056 match arg
3057 case SIMEXTARG(outputIndex=oi, isArray=ai, type_=ty, cref=c) then
3058 match oi case 0 then
3059 ""
3060 else
3061 let outarg = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
3062 let ext_name = extVarName(c)
3063 match ai
3064 case false then
3065 '<%outarg%> = (<%expTypeModelica(ty)%>)<%ext_name%>;<%\n%>'
3066 case true then
3067 '<%rcReleaseBefore(expTypeArray(ty), outarg)%>convert_alloc_<%expTypeArray(ty)%>_from_f77(&<%ext_name%>, &<%outarg%>);'
3068 end extFunCallVarcopyF77;
3069
3070 1144 template extArg(SimExtArg extArg, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3071 "Helper to extFunCall. Access data of external function argument."
3072 ::=
3073 match extArg
3074 // Array argument
3075 case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t, isInput=isInput) then
3076 let argName = contextCrefNoPrevExp(c, contextFunction, &auxFunction)
3077 let cVarName = System.stringReplace(argName, ".", "_")
3078 let cType = extType(t, isInput, true, false)
3079 let shortTypeStr = expTypeShort(t)
3080 let &varDecls += '<%cType%> <%cVarName%>_c89;<%\n%>'
3081 let packedArgName = if isInput then (
3082 match shortTypeStr
3083 case "integer" then '<%cVarName%>_packed'
3084 else argName)
3085 else argName
3086 let &preExp += '<%cVarName%>_c89 = data_of_<%shortTypeStr%>_c89_array(<%packedArgName%>);<%\n%>'
3087 '<%cVarName%>_c89'
3088
3089 // Scalar argument, no output
3090 case SIMEXTARG(cref=c, isInput=ii, outputIndex=0, type_=t) then
3091 match t
3092 case T_STRING(__) then
3093 let cr = contextCrefNoPrevExp(c,contextFunction,&auxFunction)
3094 'omc_string_data(<%cr%>)'
3095 case T_COMPLEX(complexClassType=RECORD(__)) then '&<%extVarName(c)%>'
3096 else extVarName(c)
3097
3098 // Scalar output
3099 case SIMEXTARG(cref=c, isInput=ii, outputIndex=oi, type_=t) then
3100 '&<%extVarName(c)%>'
3101
3102 case SIMEXTARGEXP(__) then
3103 daeExternalCExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
3104
3105 // Size argument
3106 case SIMEXTARGSIZE(cref=c) then
3107 let typeStr = expTypeShort(type_)
3108 let name = contextCrefNoPrevExp(c,contextFunction, &auxFunction)
3109 let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
3110 'size_of_dimension_base_array(<%name%>, <%dim%>)'
3111 end extArg;
3112
3113 56 template extArgF77(SimExtArg extArg, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3114 ::=
3115 match extArg
3116 case SIMEXTARG(cref=c, isArray=true, type_=t) then
3117 // Arrays are converted to fortran format that are stored in _ext-variables.
3118 'data_of_<%expTypeShort(t)%>_f77_array(<%extVarName(c)%>)'
3119 case SIMEXTARG(cref=c, outputIndex=oi, type_=T_INTEGER(__)) then
3120 // Always prefix fortran arguments with &.
3121 let suffix = if oi then "_ext"
3122 '(int*) &<%contextCrefNoPrevExp(appendStringFirstIdent(suffix, c),contextFunction,&auxFunction)%>'
3123 case SIMEXTARG(cref=c, outputIndex=oi, type_ = T_STRING(__)) then
3124 // modelica_string SHOULD NOT BE PREFIXED by &!
3125 '(char*)omc_string_data(<%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%>)'
3126 case SIMEXTARG(cref=c, outputIndex=oi, type_=t) then
3127 // Always prefix fortran arguments with &.
3128 let suffix = if oi then "_ext"
3129 '&<%contextCrefNoPrevExp(appendStringFirstIdent(suffix, c), contextFunction, &auxFunction)%>'
3130 case SIMEXTARGEXP(exp=exp, type_ = T_STRING(__)) then
3131 // modelica_string SHOULD NOT BE PREFIXED by &!
3132 let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
3133 let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls, &varFrees)
3134 let &preExp += '<%tvar%> = <%texp%>;<%\n%>'
3135 '(char*)omc_string_data(<%tvar%>)'
3136 case SIMEXTARGEXP(__) then
3137 daeExternalF77Exp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
3138 case SIMEXTARGSIZE(cref=c) then
3139 // Fortran functions only takes references to variables, so we must store
3140 // the result from size_of_dimension_<type>_array in a temporary variable.
3141 let sizeVarName = tempSizeVarName(c, exp, &auxFunction)
3142 let sizeVar = tempDecl("int", &varDecls, &varFrees)
3143 let dim = daeExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
3144 let &preExp += '<%sizeVar%> = size_of_dimension_base_array(<%contextCrefNoPrevExp(c,contextFunction, &auxFunction)%>, <%dim%>);<%\n%>'
3145 '&<%sizeVar%>'
3146 end extArgF77;
3147
3148 3 template tempSizeVarName(ComponentRef c, DAE.Exp indices, Text &auxFunction)
3149
3150 ::=
3151 match indices
3152 case ICONST(__) then '<%contextCrefNoPrevExp(c,contextFunction,&auxFunction)%>_size_<%integer%>'
3153 else error(sourceInfo(), 'tempSizeVarName:UNHANDLED_EXPRESSION')
3154 end tempSizeVarName;
3155
3156 7653 template funStatement(list<DAE.Statement> statementLst, Text &varDecls, Text &varFrees, Text &auxFunction)
3157 "Generates function statements."
3158 ::=
3159 statementLst |> stmt => algStatement(stmt, contextFunction, &varDecls, &varFrees, &auxFunction) ; separator="\n"
3160 end funStatement;
3161
3162 ✗ template parModelicafunStatement(list<DAE.Statement> statementLst, Text &varDecls, Text &varFrees, Text &auxFunction)
3163 "Generates function statements With PARALLEL context. Similar to Function context.
3164 Except in some cases like assignments."
3165 ::=
3166 statementLst |> stmt => algStatement(stmt, contextParallelFunction, &varDecls, &varFrees, &auxFunction) ; separator="\n"
3167 end parModelicafunStatement;
3168
3169 ✗ template extractParFors(list<DAE.Statement> statementLst, Text &varDecls, Text &varFrees, Text &auxFunction)
3170 "Generates bodies of parfor loops to the kernel file.
3171 The sequential C operations needed to implement the parallel
3172 for loop will be handled by the normal funStatment template."
3173 ::=
3174 statementLst |> stmt => extractParFors_impl(stmt, contextParallelFunction, &varDecls, &varFrees, &auxFunction) ; separator="\n"
3175 end extractParFors;
3176
3177
3178 ✗ template extractParFors_impl(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3179 "Generates an algorithm statement."
3180 ::=
3181 match stmt
3182 case s as STMT_PARFOR(__) then algStmtParForBody(s, contextParallelFunction, &varDecls, &varFrees, &auxFunction)
3183 end extractParFors_impl;
3184
3185
3186
3187 126140 template algStatement(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3188 "Generates an algorithm statement."
3189 ::=
3190 match System.tmpTickIndexReserve(1, 0) /* Remember the old tmpTick */
3191 case oldIndex
3192 then let res = (match stmt
3193 case s as STMT_ASSIGN(exp1=PATTERN(__)) then algStmtAssignPattern(s, context, &varDecls, &varFrees, &auxFunction)
3194 case s as STMT_ASSIGN(__) then algStmtAssign(s, context, &varDecls, &varFrees, &auxFunction)
3195 case s as STMT_ASSIGN_ARR(__) then algStmtAssignArr(s, context, &varDecls, &varFrees, &auxFunction)
3196 case s as STMT_TUPLE_ASSIGN(__) then algStmtTupleAssign(s, context, &varDecls, &varFrees, &auxFunction)
3197 case s as STMT_IF(__) then algStmtIf(s, context, &varDecls, &varFrees, &auxFunction)
3198 case s as STMT_FOR(__) then algStmtFor(s, context, &varDecls, &varFrees, &auxFunction)
3199 case s as STMT_PARFOR(__) then algStmtParForInterface(s, context, &varDecls, &varFrees, &auxFunction)
3200 case s as STMT_WHILE(__) then algStmtWhile(s, context, &varDecls, &varFrees, &auxFunction)
3201 case s as STMT_ASSERT(__) then algStmtAssert(s, context, &varDecls, &varFrees, &auxFunction)
3202 case s as STMT_TERMINATE(__) then algStmtTerminate(s, context, &varDecls, &varFrees, &auxFunction)
3203 case s as STMT_WHEN(__) then algStmtWhen(s, context, &varDecls, &varFrees, &auxFunction)
3204 case s as STMT_BREAK(__) then 'break;<%\n%>'
3205 case s as STMT_CONTINUE(__) then 'continue;<%\n%>'
3206 case s as STMT_FAILURE(__) then algStmtFailure(s, context, &varDecls, &varFrees, &auxFunction)
3207 case s as STMT_RETURN(__) then 'goto _return;<%\n%>'
3208 case s as STMT_NORETCALL(__) then algStmtNoretcall(s, context, &varDecls, &varFrees, &auxFunction)
3209 case s as STMT_REINIT(__) then algStmtReinit(s, context, &varDecls, &varFrees, &auxFunction)
3210 else error(sourceInfo(), 'ALG_STATEMENT NYI'))
3211 let () = System.tmpTickSetIndex(oldIndex,1)
3212 <<
3213 <%modelicaLine(ElementSource.getElementSourceFileInfo(getStatementSource(stmt)))%><%res%>
3214 <%errorCheck(context)%><%endModelicaLine()%>
3215 >>
3216 end algStatement;
3217
3218
3219 78464 template algStmtAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3220 "Generates an assigment algorithm statement."
3221 ::=
3222 match stmt
3223 case STMT_ASSIGN(exp=CALL(path=IDENT(name="fail"))) then
3224 '<%generateThrow()%><%\n%>'
3225 case STMT_ASSIGN(exp1=CREF(componentRef=WILD(__)), exp=e) then
3226 let &preExp = buffer ""
3227 let expPart = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
3228 <<
3229 <%preExp%>
3230 >>
3231 case STMT_ASSIGN(exp1=RSUB(exp=explhs as CREF(ty=t1 as T_METARECORD(__)), fieldName=fieldName))
3232 case STMT_ASSIGN(exp1=RSUB(exp=explhs as CREF(ty=t1 as T_METAUNIONTYPE(__)), fieldName=fieldName))
3233 case STMT_ASSIGN(exp1=explhs as CREF(componentRef=CREF_QUAL(identType=T_METATYPE(ty=t1 as T_METAUNIONTYPE(__)), componentRef=cr2 as CREF_IDENT(ident=fieldName)), ty=t2))
3234 case STMT_ASSIGN(exp1=explhs as CREF(componentRef=CREF_QUAL(identType=T_METATYPE(ty=t1 as T_METARECORD(__)), componentRef=cr2 as CREF_IDENT(ident=fieldName)),ty=t2)) then
3235 let &preExp = buffer ""
3236 let tmp = tempDecl("modelica_metatype",&varDecls, &varFrees)
3237 let varPart = daeExp(explhs, context, &preExp, &varDecls, &varFrees, &auxFunction)
3238 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3239 let indexInRecord = intAdd(1, lookupIndexInMetaRecord(getMetaRecordFields(t1), fieldName))
3240 let len = intAdd(2, listLength(getMetaRecordFields(t1)))
3241 <<
3242 <%preExp%>
3243 <%tmp%> = MMC_TAGPTR(mmc_alloc_words(<%len%>));
3244 memcpy(MMC_UNTAGPTR(<%tmp%>), MMC_UNTAGPTR(<%varPart%>), <%len%>*sizeof(modelica_metatype));
3245 ((modelica_metatype*)MMC_UNTAGPTR(<%tmp%>))[<%indexInRecord%>] = <%expPart%>;
3246 <%varPart%> = <%tmp%>;
3247 >>
3248
3249 case STMT_ASSIGN(exp1=RSUB(__)) then
3250 error(sourceInfo(), 'Code generation not implemented for lhs assignment <%ExpressionDumpTpl.dumpExp(exp1,"\"")%>')
3251
3252 case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_VAR(__)))
3253 case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_FUNC(__))) then
3254 let &preExp = buffer ""
3255 let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3256 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3257 <<
3258 <%preExp%>
3259 <%varPart%> = (modelica_fnptr) <%expPart%>;
3260 >>
3261 case STMT_ASSIGN(exp1=exp1 as ASUB(__),exp=val) then
3262 (match expTypeFromExpShort(exp)
3263 case "string" then
3264 let &preExp = buffer ""
3265 let varPart = daeExpAsub(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
3266 let expPart = daeExp(val, context, &preExp, &varDecls, &varFrees, &auxFunction)
3267 <<
3268 <%preExp%>
3269 omc_string_store(&(<%varPart%>), <%expPart%>);
3270 >>
3271 case "metatype" then
3272 // MetaModelica Array
3273 (match exp1 case ASUB(exp=arr, sub={idx}) then
3274 let &preExp = buffer ""
3275 let arr1 = daeExp(arr, context, &preExp, &varDecls, &varFrees, &auxFunction)
3276 let idx1 = daeSubscript(idx, context, &preExp, &varDecls, &varFrees, &auxFunction)
3277 let val1 = daeExp(val, context, &preExp, &varDecls, &varFrees, &auxFunction)
3278 <<
3279 <%preExp%>
3280 arrayUpdate(<%arr1%>,<%idx1%>,<%val1%>);
3281 >>)
3282 // Modelica Array
3283 else
3284 let &preExp = buffer ""
3285 let varPart = daeExpAsub(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
3286 let expPart = daeExp(val, context, &preExp, &varDecls, &varFrees, &auxFunction)
3287 <<
3288 <%preExp%>
3289 <%varPart%> = <%expPart%>;
3290 >>
3291 )
3292
3293 /* Record assignment */
3294 case STMT_ASSIGN(type_ = ty as T_COMPLEX(complexClassType=RECORD(__))) then
3295 let &preExp = buffer ""
3296 let copy_stmt = algStmtAssignRecord(stmt, context, &preExp, &varDecls, &varFrees, &auxFunction)
3297 <<
3298 <%preExp%>
3299 <%copy_stmt%>;
3300 >>
3301
3302 case STMT_ASSIGN(exp1=CREF(ty=T_STRING(__))) then
3303 let &preExp = buffer ""
3304 let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3305 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3306 <<
3307 <%preExp%>
3308 omc_string_store(&(<%varPart%>), <%expPart%>);
3309 >>
3310 // TODO remove me
3311 case STMT_ASSIGN(exp1=CREF(__)) then
3312 let &preExp = buffer ""
3313 let varPart = daeExpCrefLhs(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3314 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3315 <<
3316 <%preExp%>
3317 <%varPart%> = <%expPart%>;
3318 >>
3319 case STMT_ASSIGN(type_ = T_STRING(__)) then
3320 let &preExp = buffer ""
3321 let expPart1 = daeExp(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
3322 let expPart2 = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3323 <<
3324 <%preExp%>
3325 omc_string_store(&(<%expPart1%>), <%expPart2%>);
3326 >>
3327 case STMT_ASSIGN(__) then
3328 let &preExp = buffer ""
3329 let expPart1 = daeExp(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
3330 let expPart2 = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3331 <<
3332 <%preExp%>
3333 <%expPart1%> = <%expPart2%>;
3334 >>
3335 end algStmtAssign;
3336
3337 2567 template algStmtAssignRecord(DAE.Statement stmt, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3338 "Generates an assigment to record depending on context."
3339 ::=
3340 match stmt
3341 case STMT_ASSIGN(exp1=CREF(), exp=rhs_exp, type_ = ty) then
3342 assignRhsExpToRecordCref(exp1.componentRef, rhs_exp, ty, context, &preExp, &varDecls, &varFrees, &auxFunction)
3343
3344 /*destination is a call! This should not even exist. LHS call assingments should not be
3345 created. But the backend does it (does not even create a record() expression, just a normal call ://).
3346 We treat it here for now.
3347 TODO: */
3348 case STMT_ASSIGN(exp1=CALL(expLst = args), exp=rhs_exp, type_ = ty as T_COMPLEX(complexClassType=RECORD(__))) then
3349 let rec_typename = expTypeShort(ty)
3350 // The right hand side might be a call so we create a tmp var here and assign it. If the rhs is not
3351 // a call this is an uncessary copy. however, we can live with it since it is not a deep copy and the
3352 // c compiler should just be able to optimzie it away.
3353 // let tmp_rec = tempDecl(rec_typename,&varDecls)
3354 // let rhs = daeExp(rhs_exp, context, &preExp, &varDecls, &auxFunction)
3355 // let vars = args |> arg => ( ", &(" + daeExp(arg, context, &preExp, &varDecls, &auxFunction) + ")" )
3356 // <<
3357 // <%tmp_rec%> = <%rhs%>;
3358 // <%rec_typename%>_copy_to_vars(<%tmp_rec%><%vars%>);
3359 // >>
3360 // let rhs_exp_str = daeExp(rhs_exp, context, &preExp, &varDecls, &auxFunction)
3361 // let tmp_rec = tempDecl(rec_typename, &varDecls)
3362 // let assigns = splitRhsForRecordAssignmentToMemberAssignments(args, ty, tmp_rec)
3363 // |> stmt => algStatement(stmt, context, &varDecls, &auxFunction)
3364 // <<
3365 // <%tmp_rec%> = <%rhs_exp_str%>;
3366 // <%assigns%>
3367 // >>
3368 error(sourceInfo(), 'Left hand side of an assignment is a call expression. <%ExpressionDumpTpl.dumpExp(exp1,"\"")%> = <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
3369 case STMT_ASSIGN(exp1=RECORD(), type_ = ty as T_COMPLEX(complexClassType=RECORD(__))) then
3370 error(sourceInfo(), 'Left hand side of an assignment is a record expression. <%ExpressionDumpTpl.dumpExp(exp1,"\"")%>')
3371 case STMT_ASSIGN() then
3372 error(sourceInfo(), 'Unhandled record assignment. <%ExpressionDumpTpl.dumpExp(exp1,"\"")%>')
3373 end algStmtAssignRecord;
3374
3375 2575 template assignRhsExpToRecordCref(ComponentRef lhs_cref, Exp rhs_exp, Type rec_type, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3376 "Generates an assigment to record CREF depending on context."
3377 ::=
3378
3379 match context
3380 case FUNCTION_CONTEXT(__) then
3381 assignRhsExpToRecordCrefFunctionContext(lhs_cref, rhs_exp, rec_type, context, &preExp, &varDecls, &varFrees, &auxFunction)
3382 else
3383 assignRhsExpToRecordCrefSimContext(lhs_cref, rhs_exp, rec_type, context, &preExp, &varDecls, &varFrees, &auxFunction)
3384 end match
3385 end assignRhsExpToRecordCref;
3386
3387 769 template assignRhsExpToRecordCrefSimContext(ComponentRef lhs_cref, Exp rhs_exp, Type rec_type, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3388 "Generates an assigment to record CREF depending."
3389 ::=
3390 let &sub = buffer ""
3391 let lhs = contextCref(lhs_cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3392 let rec_typename = expTypeShort(rec_type)
3393
3394 match rhs_exp
3395 case CREF(componentRef = cr) then
3396 let rhs_exp_str = contextCref(cr, context, &preExp, &varDecls, &varFrees, auxFunction, &sub)
3397 let assigns = splitRecordAssignmentToMemberAssignments(lhs_cref, rec_type, rhs_exp_str)
3398 |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
3399 <<
3400 <%assigns%>
3401 >>
3402 else
3403 let rhs_exp_str = daeExp(rhs_exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3404 let tmp_rec = tempDecl(rec_typename, &varDecls, &varFrees)
3405 let assigns = splitRecordAssignmentToMemberAssignments(lhs_cref, rec_type, tmp_rec)
3406 |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
3407 <<
3408 <%rcAssignRetain(rec_typename, tmp_rec, rhs_exp_str)%><%assigns%>
3409 >>
3410 end match
3411 end assignRhsExpToRecordCrefSimContext;
3412
3413 1806 template assignRhsExpToRecordCrefFunctionContext(ComponentRef lhs_cref, Exp rhs_exp, Type rec_type, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3414 "Generates an assigment to record CREF depending."
3415 ::=
3416 let &sub = buffer ""
3417 let lhs = contextCref(lhs_cref, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3418 let rec_typename = expTypeShort(rec_type)
3419
3420 let rec_typename = expTypeShort(rec_type)
3421 match rhs_exp
3422 case rhs_exp as CREF() then
3423 let rhs = contextCref(rhs_exp.componentRef, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3424 '<%rec_typename%>_copy(<%rhs%>, <%lhs%>);'
3425
3426 else
3427 let tmp_rec = tempDecl(rec_typename,&varDecls, &varFrees)
3428 let rhs = daeExp(rhs_exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3429 <<
3430 <%rcAssignRetain(rec_typename, tmp_rec, rhs)%><%rec_typename%>_copy(<%tmp_rec%>, <%lhs%>);
3431 >>
3432 end match
3433
3434 end assignRhsExpToRecordCrefFunctionContext;
3435
3436
3437
3438 640 template algStmtAssignArr(DAE.Statement stmt, Context context,
3439 Text &varDecls, Text &varFrees, Text &auxFunction)
3440 "Generates an array assigment algorithm statement."
3441 ::=
3442 match stmt
3443 case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=RANGE(__), type_=t) then
3444 fillArrayFromRange(t,exp,cr,context,&varDecls, &varFrees,&auxFunction)
3445
3446 case STMT_ASSIGN_ARR(lhs=lhsexp as CREF(componentRef=cr), exp=e, type_=t) then
3447 let &preExp = buffer ""
3448 let expPart = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
3449 let assign = algStmtAssignArrWithRhsExpStr(lhsexp, expPart, context, &preExp, &varDecls, &varFrees, &auxFunction)
3450 <<
3451 <%preExp%>
3452 <%assign%>
3453 >>
3454 end algStmtAssignArr;
3455
3456 // TODO: Some of these cases are not needed. Or at least should not exist or not be allowed at all.
3457 // remove them and fix what fails in the backend.
3458 2166 template algStmtAssignWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context,
3459 Text &preExp, Text &postExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3460 "Generates an array assigment algorithm statement."
3461 ::=
3462 match lhsexp
3463 case CREF(componentRef=WILD(__)) then
3464 '<%rhsExpStr%>;'
3465 case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then
3466 algStmtAssignArrWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &varFrees, &auxFunction)
3467 case CREF(componentRef = cr, ty=DAE.T_COMPLEX(complexClassType=RECORD(__))) then
3468 algStmtAssignRecordWithRhsExpStr(lhsexp, rhsExpStr, context, &preExp, &varDecls, &varFrees, &auxFunction)
3469 case CREF(ty=T_STRING(__)) then
3470 let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3471 rcAssignRetain("modelica_string", lhsStr, rhsExpStr)
3472 case CREF(__) then
3473 let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3474 '<%lhsStr%> = <%rhsExpStr%>;'
3475
3476 /*This CALL on left hand side case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that
3477 at least it should have been a record_constructor not a normal call. sigh. */
3478 case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then
3479 let tmp = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
3480 /*TODO handle array record members. see algStmtAssign*/
3481 <<
3482 <%preExp%>
3483 <%rcAssignRetain(expTypeModelica(ty), tmp, rhsExpStr)%><% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 =>
3484 let re = daeExpCrefLhs(listGet(expLst,i1), context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3485 rcAssignRetain(expTypeArrayIf(var.ty), re, '<%tmp%>._<%var.name%>')
3486 ; separator="\n"
3487 %>
3488 >>
3489 case RECORD(path=path,exps=expLst,ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then
3490 let tmp = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
3491 /*TODO handle array record members. see algStmtAssign*/
3492 <<
3493 <%preExp%>
3494 <%rcAssignRetain(expTypeModelica(ty), tmp, rhsExpStr)%><% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 =>
3495 let re = daeExpCrefLhs(listGet(expLst,i1), context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3496 rcAssignRetain(expTypeArrayIf(var.ty), re, '<%tmp%>._<%var.name%>')
3497 ; separator="\n"
3498 %>
3499 >>
3500 else
3501 error(sourceInfo(), 'algStmtAssignWithRhsExpStr: Unhandled lhs expression. <%ExpressionDumpTpl.dumpExp(lhsexp,"\"")%>')
3502 end algStmtAssignWithRhsExpStr;
3503
3504 30 template algStmtAssignRecordWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context,
3505 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3506 "Generates an array assigment algorithm statement."
3507 ::=
3508 match lhsexp
3509 case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then
3510 let &sub = buffer ""
3511 let tmp = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
3512 /*TODO handle array record members. see algStmtAssign*/
3513 <<
3514 <%preExp%>
3515 <%rcAssignRetain(expTypeModelica(ty), tmp, rhsExpStr)%><% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 =>
3516 rcAssignRetain(expTypeArrayIf(var.ty), contextCref(appendStringCref(var.name, cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub), '<%tmp%>._<%var.name%>')
3517 ; separator="\n"
3518 %>
3519 >>
3520 end algStmtAssignRecordWithRhsExpStr;
3521
3522 855 template algStmtAssignArrWithRhsExpStr(DAE.Exp lhsexp, Text &rhsExpStr, Context context,
3523 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3524 "Generates an array assigment algorithm statement."
3525 ::=
3526 match lhsexp
3527 case CREF(componentRef=cr, ty = T_ARRAY(ty=basety, dims=dims)) then
3528 let type = expTypeArray(ty)
3529 if crefSubIsScalar(cr) then
3530 let lhsStr = daeExpCrefLhs(lhsexp, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3531 '<%type%>_copy_data(<%rhsExpStr%>, <%lhsStr%>);'
3532 else
3533 indexedAssign(lhsexp, rhsExpStr, context, &preExp, &varDecls, &varFrees, &auxFunction)
3534 end algStmtAssignArrWithRhsExpStr;
3535
3536 3 template fillArrayFromRange(DAE.Type ty, Exp exp, DAE.ComponentRef cr, Context context,
3537 Text &varDecls, Text &varFrees, Text &auxFunction)
3538 "Generates an array assigment to RANGE expressions. (Fills an array from range expresion)"
3539 ::=
3540 let &sub = buffer ""
3541 match exp
3542 case RANGE(__) then
3543 let &preExp = buffer ""
3544 let cref = contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3545 let ty_str = expTypeArray(ty)
3546 let start_exp = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
3547 let stop_exp = daeExp(stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
3548 let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &varFrees, &auxFunction) else "1"
3549 <<
3550 <%preExp%>
3551 fill_<%ty_str%>_from_range(&<%cref%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%>
3552 >>
3553
3554 end fillArrayFromRange;
3555
3556 145 template indexedAssign(DAE.Exp lhs, String exp, Context context,
3557 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
3558 ::=
3559 let &sub = buffer ""
3560 match lhs
3561 case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then
3562 let arrayType = expTypeArray(ty)
3563 match context
3564 case FUNCTION_CONTEXT(__) then
3565 let ispec = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction)
3566 let cref = contextCref(crefStripLastSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3567 'indexed_assign_<%arrayType%>(<%exp%>, &<%cref%>, &<%ispec%>);'
3568 else if contiguousSlice(cr, expTypeShort(aty), context) then
3569 let type = expTypeShort(aty)
3570 let data = contiguousSliceData(cr, type, context, &preExp, &varDecls, &varFrees, &auxFunction)
3571 'simple_array_copy_to(<%exp%>, <%data%>, <%contiguousSliceDims(crefSubs(cr), crefDims(cr)) |> d => d ;separator="*"%>, sizeof(modelica_<%type%>));'
3572 else
3573 let ispec = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction)
3574 let type = expTypeShort(aty)
3575 let wrapperArray = tempDecl(arrayType, &varDecls, &varFrees)
3576 let dimsLenStr = listLength(crefDims(cr))
3577 let dimsValuesStr = (crefDims(cr) |> dim => '(_index_t)<%dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
3578 let arrName = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3579 <<
3580 <%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)&<%arrName%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>
3581 indexed_assign_<%arrayType%>(<%exp%>, &<%wrapperArray%>, &<%ispec%>);
3582 >>
3583 else
3584 error(sourceInfo(), 'indexedAssign simulationContext failed')
3585 end indexedAssign;
3586
3587 2162 template algStmtTupleAssign(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3588 "Generates a tuple assigment algorithm statement."
3589 ::=
3590 match stmt
3591 case STMT_TUPLE_ASSIGN(expExpLst={_}) then
3592 error(sourceInfo(), "A tuple assignment of only one variable is a regular assignment")
3593
3594 case STMT_TUPLE_ASSIGN(expExpLst = firstexp::_, exp = CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ntys)))) then
3595 let &preExp = buffer ""
3596 let &postExp = buffer ""
3597
3598 let lhsCrefs = (listRest(expExpLst) |> e => " ," + tupleReturnVariableUpdates(e, context, varDecls, varFrees, preExp, postExp, &auxFunction))
3599 // The tuple expressions might take fewer variables than the number of outputs. No worries.
3600 let lhsCrefs2 = lhsCrefs + List.fill(", NULL", intMax(0,intSub(listLength(ntys),listLength(expExpLst))))
3601
3602 let call = daeExpCallTuple(unboxFunctionReferenceCall(exp), lhsCrefs2, context, &preExp, &varDecls, &varFrees, &auxFunction)
3603 let callassign = algStmtAssignWithRhsExpStr(firstexp, call, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)
3604 <<
3605 <%preExp%>
3606 <%callassign%>
3607 <%postExp%>
3608 >>
3609
3610 case STMT_TUPLE_ASSIGN(exp=MATCHEXPRESSION(__)) then
3611 let &sub = buffer ""
3612 let &preExp = buffer ""
3613 let prefix = 'tmp<%System.tmpTick()%>'
3614 // get the current index of tmpMeta and reserve N=listLength(inputs) values in it!
3615 let startIndexOutputs = '<%System.tmpTickIndexReserve(1, listLength(expExpLst))%>'
3616 let _ = daeExpMatch2(exp, expExpLst, prefix, startIndexOutputs, context, &preExp, &varDecls, &varFrees, &auxFunction)
3617 let lhsCrefs = (expExpLst |> crefexp as CREF(componentRef = cr) hasindex i0 fromindex 1 =>
3618 let rhsStr = getTempDeclMatchOutputName(expExpLst, prefix, startIndexOutputs, i0)
3619 let lhsStr = contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3620 <<
3621 <%lhsStr%> = <%rhsStr%>;
3622 >>
3623 ;separator="\n"; empty)
3624 <<
3625 <%expExpLst |> crefexp hasindex i0 =>
3626 let typ = expTypeFromExpModelica(crefexp)
3627 let decl = tempDeclMatchOutput(typ, prefix, startIndexOutputs, i0, &varDecls, &varFrees)
3628 ""
3629 ;separator="\n";empty%>
3630 <%preExp%>
3631 <%lhsCrefs%>
3632 >>
3633 else error(sourceInfo(), 'algStmtTupleAssign failed')
3634
3635 end algStmtTupleAssign;
3636
3637 4942 template tupleReturnVariableUpdates(Exp inExp, Context context, Text &varDecls, Text &varFrees, Text &preExp, Text &varCopy, Text &auxFunction)
3638 "Generates code for updating variables returned from fuctions that return tuples.
3639 Generates copies depending on what kind of variable is returned."
3640 ::=
3641 match inExp
3642 case CREF(componentRef=WILD(__)) then
3643 'NULL'
3644 case CREF(componentRef = cr, ty=DAE.T_COMPLEX(varLst = varLst, complexClassType=RECORD(__))) then
3645 let &sub = buffer ""
3646 let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls, &varFrees)
3647 let &varCopy +=
3648 /*TODO handle array record members. see algStmtAssign*/
3649 <<
3650 <%preExp%>
3651 <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 0 =>
3652 rcAssignRetain(expTypeArrayIf(var.ty), contextCref(appendStringCref(var.name, cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub), '<%rhsStr%>._<%var.name%>')
3653 ; separator="\n"
3654 %>
3655 >> /*varCopy end*/
3656 '&<%rhsStr%>'
3657
3658 /*This CALL case shouldn't have been created by the compiler. It only comes because of alias eliminations. On top of that
3659 at least it should have been a record_constractor not a normal call. sigh. */
3660 case CALL(path=path,expLst=expLst,attr=CALL_ATTR(ty=ty as T_COMPLEX(varLst = varLst, complexClassType=RECORD(__)))) then
3661 let &preExp = buffer ""
3662 let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls, &varFrees)
3663 let tmp = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
3664 let &varCopy +=
3665 /*TODO handle array record members. see algStmtAssign*/
3666 <<
3667 <%preExp%>
3668 <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 =>
3669 let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &varFrees, &auxFunction)
3670 rcAssignRetain(expTypeArrayIf(var.ty), re, '<%rhsStr%>._<%var.name%>')
3671 ; separator="\n"
3672 %>
3673 >> /*varCopy end*/
3674 '&<%rhsStr%>'
3675 case RECORD(path=path,exps=expLst,ty=ty as T_COMPLEX(varLst = varLst)) then
3676 let &preExp = buffer ""
3677 let rhsStr = tempDecl(expTypeArrayIf(ty), &varDecls, &varFrees)
3678 let tmp = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
3679 let &varCopy +=
3680 /*TODO handle array record members. see algStmtAssign*/
3681 <<
3682 <%preExp%>
3683 <% varLst |> var as TYPES_VAR(__) hasindex i1 fromindex 1 =>
3684 let re = daeExp(listGet(expLst,i1), context, &preExp, &varDecls, &varFrees, &auxFunction)
3685 rcAssignRetain(expTypeArrayIf(var.ty), re, '<%rhsStr%>._<%var.name%>')
3686 ; separator="\n"
3687 %>
3688 >> /*varCopy end*/
3689 '&<%rhsStr%>'
3690 case CREF(componentRef=cr) then
3691 if not crefSubIsScalar(cr) then
3692 let tmp = tempDecl(expTypeArray(ty), &varDecls, &varFrees)
3693 let &varCopy += '<%indexedAssign(inExp, tmp, context, &preExp, &varDecls, &varFrees, &auxFunction)%><%\n%>'
3694 '&<%tmp%>'
3695 else
3696 let res = daeExpCrefLhs(inExp, context, &preExp, &varDecls, &varFrees, &auxFunction, false)
3697 if isArrayWithUnknownDimension(ty)
3698 then
3699 let &preExp += '<%res%>.dim_size = NULL;<%\n%>'
3700 '&<%res%>'
3701 else '&<%res%>'
3702 else
3703 error(sourceInfo(), 'tupleReturnVariableUpdates: Unhandled expression. <%ExpressionDumpTpl.dumpExp(inExp,"\"")%>')
3704 end tupleReturnVariableUpdates;
3705
3706 4507 template algStmtIf(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3707 "Generates an if algorithm statement."
3708 ::=
3709 match stmt
3710 case STMT_IF(__) then
3711 let &preExp = buffer ""
3712 let condExp = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3713 <<
3714 <%preExp%>
3715 if(<%condExp%>)
3716 {
3717 <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction) ;separator="\n"%>
3718 }
3719 <%elseExpr(else_, context, &varDecls, &varFrees, &auxFunction)%>
3720 >>
3721 end algStmtIf;
3722
3723 ✗ template algStmtParForBody(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3724 "Generates a for algorithm statement."
3725 ::=
3726 match stmt
3727 case s as STMT_PARFOR(range=rng as RANGE(__)) then
3728 algStmtParForRangeBody(s, context, &varDecls, &varFrees, &auxFunction)
3729 case s as STMT_PARFOR(__) then
3730 algStmtForGeneric(s, context, &varDecls, &varFrees, &auxFunction)
3731 end algStmtParForBody;
3732
3733 ✗ template algStmtParForRangeBody(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3734 "Generates a for algorithm statement where range is RANGE."
3735 ::=
3736 match stmt
3737 case STMT_PARFOR(range=rng as RANGE(__)) then
3738 let iterName = contextIteratorName(iter, context)
3739 let identType = expType(type_, iterIsArray)
3740 let identTypeShort = expTypeShort(type_)
3741
3742 let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>'
3743
3744 let &loopVarDecls = buffer ""
3745 let &loopVarFrees = buffer ""
3746 let body = (statementLst |> stmt => algStatement(stmt, context, &loopVarDecls, &loopVarFrees, &auxFunction)
3747 ;separator="\n")
3748
3749 // Reconstruct array arguments to structures in the kernels
3750 let &reconstrucedArrays = buffer ""
3751 let _ = (loopPrlVars |> var =>
3752 reconstructKernelArraysFromLooptupleVars(var, &reconstrucedArrays)
3753 )
3754
3755 let argStr = (loopPrlVars |> var => '<%parFunArgDefinitionFromLooptupleVar(var)%>' ;separator=",\n")
3756
3757 <<
3758
3759 __kernel void <%parforKernelName%>(
3760 modelica_integer loop_start,
3761 modelica_integer loop_step,
3762 modelica_integer loop_end,
3763 <%argStr%>)
3764 {
3765 /* algStmtParForRangeBody : Thread managment for parfor loops */
3766 modelica_integer inner_start = (get_global_id(0) * loop_step) + (loop_start);
3767 modelica_integer stride = get_global_size(0) * loop_step;
3768
3769 for(modelica_integer <%iterName%> = (modelica_integer) inner_start; in_range_integer(<%iterName%>, loop_start, loop_end); <%iterName%> += stride)
3770 {
3771 /* algStmtParForRangeBody : Reconstruct Arrays */
3772 <%reconstrucedArrays%>
3773
3774 /* algStmtParForRangeBody : locals */
3775 <%loopVarDecls%>
3776
3777 <%body%>
3778 }
3779 }
3780 >>
3781 end algStmtParForRangeBody;
3782
3783 ✗ template algStmtParForInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3784 "Generates a for algorithm statement."
3785 ::=
3786 match stmt
3787 case s as STMT_PARFOR(range=rng as RANGE(__)) then
3788 algStmtParForRangeInterface(s, context, &varDecls, &varFrees, &auxFunction)
3789 case s as STMT_PARFOR(__) then
3790 algStmtForGeneric(s, context, &varDecls, &varFrees, &auxFunction)
3791 end algStmtParForInterface;
3792
3793 ✗ template algStmtParForRangeInterface(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3794 "Generates a for algorithm statement where range is RANGE."
3795 ::=
3796 match stmt
3797 case STMT_PARFOR(range=rng as RANGE(__)) then
3798 let identType = expType(type_, iterIsArray)
3799 let identTypeShort = expTypeShort(type_)
3800 let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
3801 ;separator="\n")
3802 algStmtParForRangeInterface_impl(rng, iter, identType, identTypeShort, loopPrlVars, stmtStr, context, &varDecls, &varFrees, &auxFunction)
3803 end algStmtParForRangeInterface;
3804
3805 ✗ template algStmtParForRangeInterface_impl(Exp range, Ident iterator, String type, String shortType, list<tuple<DAE.ComponentRef,builtin.SourceInfo>> loopPrlVars, Text body, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3806 "The implementation of algStmtParForRangeInterface."
3807 ::=
3808 match range
3809 case RANGE(__) then
3810 let iterName = contextIteratorName(iterator, context)
3811 let startVar = tempDecl(type, &varDecls, &varFrees)
3812 let stepVar = tempDecl(type, &varDecls, &varFrees)
3813 let stopVar = tempDecl(type, &varDecls, &varFrees)
3814 let &preExp = buffer ""
3815 let startValue = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
3816 let stepValue = match step case SOME(eo) then
3817 daeExp(eo, context, &preExp, &varDecls, &varFrees, &auxFunction)
3818 else
3819 "(modelica_integer)1"
3820 let stopValue = daeExp(stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
3821
3822 let cl_kernelVar = tempDecl("cl_kernel", &varDecls, &varFrees)
3823
3824 let parforKernelName = 'parfor_<%System.tmpTickIndex(20 /* parfor */)%>'
3825
3826 let kerArgNr = '<%parforKernelName%>_arg_nr'
3827
3828 let &kernelArgSets = buffer ""
3829 let _ = (loopPrlVars |> varTuple =>
3830 setKernelArgFormTupleLoopVars_ith(varTuple, &cl_kernelVar, &kerArgNr, &kernelArgSets, context)
3831 )
3832
3833 // Scoped: this is C++, where a goto to _return may not cross an initialization.
3834 <<
3835 <%preExp%>
3836 <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>;
3837 {
3838 <%cl_kernelVar%> = ocl_create_kernel(omc_ocl_program, "<%parforKernelName%>");
3839 int <%kerArgNr%> = 0;
3840
3841 ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%startVar%>); ++<%kerArgNr%>; <%\n%>
3842 ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stepVar%>); ++<%kerArgNr%>; <%\n%>
3843 ocl_set_kernel_arg(<%cl_kernelVar%>, <%kerArgNr%>, <%stopVar%>); ++<%kerArgNr%>; <%\n%>
3844
3845 <%kernelArgSets%>
3846
3847 ocl_execute_kernel(<%cl_kernelVar%>);
3848 clReleaseKernel(<%cl_kernelVar%>);
3849 }
3850 >> /* else we're looping over a zero-length range */
3851 end algStmtParForRangeInterface_impl;
3852
3853
3854 ✗ template subIterator(tuple<DAE.ComponentRef, array<DAE.Exp>> iter, String parent_iter, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
3855 ::= match iter
3856 case (name, range) then
3857 let type_ = 'modelica_<%crefShortType(name)%>'
3858 let name_ = contextCref(name, contextOther, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
3859 let range_ = (arrayList(range) |> elem => daeExp(elem, context, &preExp, &varDecls, &varFrees, &auxFunction); separator=", ")
3860 let size_ = arrayLength(range)
3861 <<
3862 static const <%type_%> <%name_%>_arr[<%size_%>] = {<%range_%>};
3863 <%type_%> <%name_%> = <%name_%>_arr[<%parent_iter%>-1];
3864 >>
3865 end subIterator;
3866
3867 747 template algStmtFor(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3868 "Generates a for algorithm statement."
3869 ::=
3870 match stmt
3871 case s as STMT_FOR(range=rng as RANGE(__)) then
3872 algStmtForRange(s, context, &varDecls, &varFrees, &auxFunction)
3873 case s as STMT_FOR(__) then
3874 algStmtForGeneric(s, context, &varDecls, &varFrees, &auxFunction)
3875 end algStmtFor;
3876
3877 747 template algStmtForRange(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3878 "Generates a for algorithm statement where range is RANGE."
3879 ::=
3880 match stmt
3881 case STMT_FOR(range=rng as RANGE(__)) then
3882 let identType = expType(type_, iterIsArray)
3883 let identTypeShort = expTypeShort(type_)
3884 let stmtStr = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
3885 ;separator="\n")
3886 let iterName = contextIteratorName(iter, context)
3887 let &preExp_si = buffer ""
3888 let &sub_si = buffer ""
3889 let subIterDecls = (sub_iters |> si => subIterator(si, iterName, context, &preExp_si, &varDecls, &varFrees, &auxFunction, &sub_si); separator="\n")
3890 algStmtForRange_impl(rng, iter, identType, identTypeShort, '<%subIterDecls%><%\n%><%stmtStr%>', context, &varDecls, &varFrees, &auxFunction)
3891 end algStmtForRange;
3892
3893 747 template algStmtForRange_impl(Exp range, Ident iterator, String type, String shortType, Text body, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3894 "The implementation of algStmtForRange, which is also used by daeExpReduction."
3895 ::=
3896 match range
3897 case RANGE(__) then
3898 let iterName = contextIteratorName(iterator, context)
3899 let startVar = tempDecl(type, &varDecls, &varFrees)
3900 let stepVar = tempDecl(type, &varDecls, &varFrees)
3901 let stopVar = tempDecl(type, &varDecls, &varFrees)
3902 let &preExp = buffer ""
3903 let startValue = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
3904 let stepValue = match step case SOME(eo) then
3905 daeExp(eo, context, &preExp, &varDecls, &varFrees, &auxFunction)
3906 else "1"
3907 let stopValue = daeExp(stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
3908 let eqnsindx = match context
3909 case FUNCTION_CONTEXT(__) then ''
3910 else 'equationIndexes, '
3911 let AddionalFuncName = match context
3912 case FUNCTION_CONTEXT(__) then ''
3913 else '_withEquationIndexes'
3914 let stepCheck = match stepValue
3915 case "1"
3916 case "((modelica_integer) 1)"
3917 case "((modelica_integer) -1)" then ''
3918 else 'if(!<%stepVar%>) {<%\n%> omc_assert<%AddionalFuncName%>(threadData, omc_dummyFileInfo, <%eqnsindx%>"assertion range step != 0 failed");<%\n%> <%errorCheck(context)%>} else '
3919 <<
3920 <%preExp%>
3921 <%startVar%> = <%startValue%>; <%stepVar%> = <%stepValue%>; <%stopVar%> = <%stopValue%>;
3922 <%stepCheck%>if(!(((<%stepVar%> > 0) && (<%startVar%> > <%stopVar%>)) || ((<%stepVar%> < 0) && (<%startVar%> < <%stopVar%>))))
3923 {
3924 <%type%> <%iterName%>;
3925 for(<%iterName%> = <%startValue%>; in_range_<%shortType%>(<%iterName%>, <%startVar%>, <%stopVar%>); <%iterName%> += <%stepVar%>)
3926 {
3927 <%body%>
3928 }
3929 }
3930 >> /* else we're looping over a zero-length range */
3931 end algStmtForRange_impl;
3932
3933 256 template algStmtForGeneric(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3934 "Generates a for algorithm statement where range is not RANGE."
3935 ::=
3936 match stmt
3937 case STMT_FOR(__) then
3938 let iterType = match expType(type_, iterIsArray)
3939 case "modelica_string" then "modelica_metatype"
3940 case "modelica_fnptr" then "modelica_metatype"
3941 case s then s
3942 let arrayType = expTypeArray(type_)
3943 let tvar = match iterType
3944 case "modelica_metatype"
3945 then tempDecl("modelica_metatype", &varDecls, &varFrees)
3946 else tempDecl("int", &varDecls, &varFrees)
3947 let stmtStr = (statementLst |> stmt =>
3948 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction) ;separator="\n")
3949 algStmtForGeneric_impl(range, iter, iterType, arrayType, iterIsArray, stmtStr, tvar, context, &varDecls, &varFrees, &auxFunction)
3950 end algStmtForGeneric;
3951
3952 256 template algStmtForGeneric_impl(Exp exp, Ident iterator, String type,
3953 String arrayType, Boolean iterIsArray, Text &body, Text tvar, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
3954 "The implementation of algStmtForGeneric, which is also used by daeExpReduction."
3955 ::=
3956 let iterName = contextIteratorName(iterator, context)
3957 let ivar = tempDecl(type, &varDecls, &varFrees)
3958 let &preExp = buffer ""
3959 let evar = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
3960 <<
3961 <%preExp%>
3962 {
3963 <%type%> <%iterName%>;
3964 <% match type
3965 case "modelica_metatype" then
3966 (match typeof(exp)
3967 case T_METAARRAY(__)
3968 case T_METATYPE(ty=T_METAARRAY(__)) then
3969 let tmp = tempDecl("modelica_integer",&varDecls, &varFrees)
3970 let len = tempDecl("modelica_integer",&varDecls, &varFrees)
3971 <<
3972 for (<%tvar%> = <%evar%>, <%len%> = arrayLength(<%tvar%>), <%tmp%> = 1; <%tmp%> <= <%len%>; <%tmp%>++)
3973 {
3974 <%iterName%> = arrayGet(<%tvar%>,<%tmp%>);
3975 <%body%>
3976 }
3977 >>
3978 case T_METALIST(__)
3979 case T_METATYPE(ty=T_METALIST(__)) then
3980 <<
3981 for (<%tvar%> = <%evar%>; !listEmpty(<%tvar%>); <%tvar%>=MMC_CDR(<%tvar%>))
3982 {
3983 <%iterName%> = MMC_CAR(<%tvar%>);
3984 <%body%>
3985 }
3986 >>
3987 case ty then error(sourceInfo(), '<%unparseType(ty)%> iterator is not supported'))
3988 else
3989 let stmtStuff = if iterIsArray then
3990 'simple_index_alloc_<%type%>1(&<%evar%>, <%tvar%>, &<%ivar%>);'
3991 else
3992 '<%iterName%> = <%arrayType%>_get1(<%evar%>, 1, <%tvar%>);'
3993 <<
3994 for(<%tvar%> = 1; <%tvar%> <= size_of_dimension_base_array(<%evar%>, 1); ++<%tvar%>)
3995 {
3996 <%stmtStuff%>
3997 <%body%>
3998 }
3999 >>
4000 %>
4001 }
4002 >>
4003 end algStmtForGeneric_impl;
4004
4005 250 template algStmtWhile(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4006 "Generates a while algorithm statement."
4007 ::=
4008 match stmt
4009 case STMT_WHILE(__) then
4010 let &preExp = buffer ""
4011 let var = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
4012 <<
4013 while(1)
4014 {
4015 <%preExp%>
4016 if(!<%var%>) break;
4017 <%statementLst |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction) ;separator="\n"%>
4018 }
4019 >>
4020 end algStmtWhile;
4021
4022
4023 33894 template algStmtAssert(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4024 "Generates an assert algorithm statement."
4025 ::=
4026 match stmt
4027 case STMT_ASSERT(source=SOURCE(info=info)) then
4028 assertCommon(cond, List.fill(msg,1), level, context, &varDecls, &varFrees, &auxFunction, info)
4029 end algStmtAssert;
4030
4031 3 template algStmtTerminate(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4032 "Generates an assert algorithm statement."
4033 ::=
4034 match stmt
4035 case STMT_TERMINATE(__) then
4036 let &preExp = buffer ""
4037 let msgVar = daeExp(msg, context, &preExp, &varDecls, &varFrees, &auxFunction)
4038 <<
4039 <%preExp%>
4040 {
4041 FILE_INFO info = {<%infoArgs(ElementSource.getElementSourceFileInfo(source))%>};
4042 omc_terminate(info, omc_string_data(<%msgVar%>));
4043 }
4044 >>
4045 end algStmtTerminate;
4046
4047 5 template algStmtFailure(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4048 "Generates a failure() algorithm statement."
4049 ::=
4050 match stmt
4051 case STMT_FAILURE(__) then
4052 let tmp = tempDecl("modelica_boolean", &varDecls, &varFrees)
4053 let () = codegenPushTryThrowIndex(System.tmpTick())
4054 let goto = 'goto_<%codegenPeekTryThrowIndex()%>'
4055 let stmtBody = (body |> stmt =>
4056 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
4057 ;separator="\n")
4058 <<
4059 <%tmp%> = 0; /* begin failure */
4060 OMC_TRY_INTERNAL(mmc_jumper)
4061 <%stmtBody%>
4062 <%tmp%> = 1;
4063 goto <%goto%>;
4064 <%goto%>:;
4065 OMC_CATCH_INTERNAL(mmc_jumper)<%let()=codegenPopTryThrowIndex() ""%>
4066 if (<%tmp%>) {<%generateThrow()%>;} /* end failure */
4067 >>
4068 end algStmtFailure;
4069
4070 914 template algStmtNoretcall(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4071 "Generates a no return call algorithm statement."
4072 ::=
4073 match stmt
4074 case STMT_NORETCALL(exp=DAE.MATCHEXPRESSION(__)) then
4075 let &preExp = buffer ""
4076 let expPart = daeExpMatch2(exp,listExpLength1,"","",context,&preExp,&varDecls, &varFrees, &auxFunction)
4077 <<
4078 <%preExp%>
4079 <%expPart%>;
4080 >>
4081 case STMT_NORETCALL(__) then
4082 let &preExp = buffer ""
4083 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
4084 <<
4085 <%preExp%>
4086 <% if isCIdentifier(expPart) then "" else '<%expPart%>;' %>
4087 >>
4088 end algStmtNoretcall;
4089
4090 137 template algStmtWhen(DAE.Statement when, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4091 "Generates a when algorithm statement."
4092 ::=
4093 let &sub = buffer ""
4094 match context
4095 case DAE_MODE_CONTEXT(__)
4096 case SIMULATION_CONTEXT(__) then
4097 match when
4098 case STMT_WHEN(__) then
4099 let if_conditions = if not listEmpty(conditions) then (conditions |> e =>
4100 let cond = daeExp(crefExp(e), context, &sub, &varDecls, &varFrees, &auxFunction)
4101 let condPre = daeExp(crefExp(crefPrefixPre(e)), context, &sub, &varDecls, &varFrees, &auxFunction)
4102 '(<%cond%> && !<%condPre%> /* edge */)';separator=" || ") else '0'
4103 let statements = (statementLst |> stmt => algStatement(stmt, context, &varDecls, &varFrees, &auxFunction);separator="\n")
4104 let else_clause = algStatementWhenElse(elseWhen, context, &varDecls, &varFrees, &auxFunction)
4105 <<
4106 if(data->simulationInfo->discreteCall == 1)
4107 {
4108 if(<%if_conditions%>)
4109 {
4110 <%statements%>
4111 }
4112 <%else_clause%>
4113 }
4114 >>
4115 end match
4116 end match
4117 end algStmtWhen;
4118
4119 183 template algStatementWhenElse(Option<DAE.Statement> stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4120 "Helper to algStmtWhen."
4121 ::=
4122 let &sub = buffer ""
4123 match stmt
4124 case SOME(when as STMT_WHEN(__)) then
4125 let else_conditions = if not listEmpty(when.conditions) then (when.conditions |> e =>
4126 let cond = daeExp(crefExp(e), context, &sub, &varDecls, &varFrees, &auxFunction)
4127 let condPre = daeExp(crefExp(crefPrefixPre(e)), context, &sub, &varDecls, &varFrees, &auxFunction)
4128 '(<%cond%> && !<%condPre%> /* edge */)';separator=" || ") else '0'
4129 let statements = (when.statementLst |> stmt => algStatement(stmt, contextSimulationDiscrete, &varDecls, &varFrees, &auxFunction);separator="\n")
4130 let else = algStatementWhenElse(when.elseWhen, context, &varDecls, &varFrees, &auxFunction)
4131 <<
4132 else if(<%else_conditions%>)
4133 {
4134 <%statements%>
4135 }
4136 <%else%>
4137 >>
4138 end algStatementWhenElse;
4139
4140 24 template algStmtReinit(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4141 "Generates an assigment algorithm statement."
4142 ::=
4143 match stmt
4144 case STMT_REINIT(__) then
4145 let &preExp = buffer ""
4146 let expPart1 = daeExp(var, context, &preExp, &varDecls, &varFrees, &auxFunction)
4147 let expPart2 = daeExp(value, context, &preExp, &varDecls, &varFrees, &auxFunction)
4148 <<
4149 <%preExp%>
4150 <%expPart1%> = <%expPart2%>;
4151 infoStreamPrint(OMC_LOG_EVENTS, 0, "reinit <%expPart1%> = %f", <%expPart1%>);
4152 data->simulationInfo->needToIterate = 1;
4153 >>
4154 end algStmtReinit;
4155
4156 3076 template elseExpr(DAE.Else else_, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4157 "Helper to algStmtIf."
4158 ::=
4159 match else_
4160 case NOELSE(__) then
4161 ""
4162 case ELSEIF(__) then
4163 let &preExp = buffer ""
4164 let condExp = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
4165 <<
4166 else
4167 {
4168 <%preExp%>
4169 if(<%condExp%>)
4170 {
4171 <%statementLst |> stmt =>
4172 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
4173 ;separator="\n"%>
4174 }
4175 <%elseExpr(else_, context, &varDecls, &varFrees, &auxFunction)%>
4176 }
4177 >>
4178 case ELSE(__) then
4179
4180 <<
4181 else
4182 {
4183 <%statementLst |> stmt =>
4184 algStatement(stmt, context, &varDecls, &varFrees, &auxFunction)
4185 ;separator="\n"%>
4186 }
4187 >>
4188 end elseExpr;
4189
4190 ✗ template functionsParModelicaKernelsFile(String filePrefix, Option<SimCodeFunction.Function> mainFunction, list<SimCodeFunction.Function> functions)
4191 "Generates the content of the C file for functions in the simulation case."
4192 ::=
4193
4194 /* Reset the parfor loop id counter to 1*/
4195 let()= System.tmpTickResetIndex(0,20) /* parfor index */
4196
4197 <<
4198 #include <ParModelica/explicit/openclrt/OCLRuntimeUtil.cl>
4199
4200 // ParModelica Parallel Function headers.
4201 <%functionHeadersParModelica(filePrefix, functions)%>
4202
4203 // Headers finish here.
4204
4205 <%match mainFunction case SOME(fn) then functionBodyParModelica(fn,true)%>
4206 <%functionBodiesParModelica(functions)%>
4207
4208
4209 >>
4210
4211 end functionsParModelicaKernelsFile;
4212
4213 /* public */ template recordsFile(String filePrefix, list<RecordDeclaration> recordDecls, Boolean isSimulation)
4214 "Generates the content of the C file for functions in the simulation case.
4215 used in Compiler/Template/CodegenFMU.tpl"
4216 ::=
4217 let recDeclsFile = if isSimulation then '<%filePrefix%>_functions.h' else '<%filePrefix%>.h'
4218 <<
4219 /* Additional record code for <%filePrefix%> generated by the OpenModelica Compiler <%getVersionNr()%>. */
4220
4221 #include "omc_simulation_settings.h"
4222 <%if metaModelicaRuntime() then '#include "meta/meta_modelica.h"'%>
4223 #include "<%recDeclsFile%>"
4224
4225 #ifdef __cplusplus
4226 extern "C" {
4227 #endif
4228
4229 <%recordDecls |> rd => recordDeclaration(rd) ;separator="\n\n"%>
4230
4231 #ifdef __cplusplus
4232 }
4233 #endif
4234
4235 >>
4236 /* adpro: leave a newline at the end of file to get rid of warnings! */
4237 end recordsFile;
4238
4239 15574 template literalExpConst(Exp lit, Integer litindex) "These should all be declared static X const"
4240 ::=
4241 let name = '_OMC_LIT<%litindex%>'
4242 let tmp = '_OMC_LIT_STRUCT<%litindex%>'
4243 let meta = 'static modelica_metatype const <%name%>'
4244
4245 match lit
4246 case RECORD(__) then
4247 let &preExp = buffer ""
4248 let &varDecls = buffer ""
4249 let &varFrees = buffer ""
4250 let &auxFunction = buffer ""
4251 let elements = (exps |> e => daeExp(e, contextOther, &preExp, &varDecls, &varFrees, &auxFunction);separator=", ")
4252 <<
4253 #if (defined(__clang__) && __clang_major__ >= 17) || (defined(__GNUC__) && __GNUC__ >= 8)
4254 static const <%expTypeFlag(ty, 2)%> <%name%> = {<%elements%>};
4255 #else
4256 /* handle joke compilers */
4257 #define <%name%> (<%expTypeFlag(ty, 2)%>){<%elements%>}
4258 #endif
4259 >>
4260 case SCONST(__) then
4261 let escstr = Util.escapeModelicaStringToCString(string)
4262 /* TODO: Change this when OMC takes constant input arguments (so we cannot write to them)
4263 The cost of not doing this properly is small (<257 bytes of constants)
4264 match unescapedStringLength(escstr)
4265 case 0 then '#define <%name%> omc_string_empty'
4266 case 1 then '#define <%name%> omc_strings_len1["<%escstr%>"[0]]'
4267 else */
4268 <<
4269 #define <%name%>_data "<%escstr%>"
4270 static const <%litDefString()%>(<%tmp%>,<%unescapedStringLength(escstr)%>,<%name%>_data);
4271 #define <%name%> <%litRefString()%>(<%tmp%>)
4272 >>
4273 case lit as MATRIX(ty=ty as T_ARRAY(__))
4274 case lit as ARRAY(ty=ty as T_ARRAY(__)) then
4275 let ndim = listLength(getDimensionSizes(ty))
4276 let dims = (getDimensionSizes(ty) |> dim => dim ;separator=", ")
4277 let data = flattenArrayExpToList(lit) |> exp => literalExpConstArrayVal(exp) ; separator=", "
4278 // dim_size is released whatever owns_data says, so it carries an immortal count.
4279 <<
4280 static struct { mmc_uint_t rc; _index_t d[<%ndim%>]; } <%name%>_dims_lit = { OMC_RC_IMMORTAL, {<%dims%>} };
4281 #define <%name%>_dims (<%name%>_dims_lit.d)
4282 <% match data case "" then
4283 <<
4284 #if (defined(__clang__) && __clang_major__ >= 17) || (defined(__GNUC__) && __GNUC__ >= 8)
4285 static base_array_t const <%name%> = {
4286 <%ndim%>, <%name%>_dims, (void*) 0, (modelica_boolean) 0
4287 };
4288 #else
4289 /* handle joke compilers */
4290 #define <%name%> (base_array_t){<%ndim%>, <%name%>_dims, (void*) 0, (modelica_boolean) 0}
4291 #endif
4292 >>
4293 else
4294 <<
4295 static const <%expTypeFlag(ty, 2)%> <%name%>_data[] = {<%data%>};
4296 #if (defined(__clang__) && __clang_major__ >= 17) || (defined(__GNUC__) && __GNUC__ >= 8)
4297 static <%expTypeFlag(ty, 4)%> const <%name%> = {
4298 <%ndim%>, <%name%>_dims, (void*) <%name%>_data, (modelica_boolean) 0
4299 };
4300 #else
4301 /* handle joke compilers */
4302 #define <%name%> (base_array_t){<%ndim%>, <%name%>_dims, (void*) <%name%>_data, (modelica_boolean) 0}
4303 #endif
4304 >>
4305 %>
4306 >>
4307 case BOX(exp=exp as ICONST(__)) then
4308 <<
4309 <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%exp.integer%>));
4310 >>
4311 case BOX(exp=exp as BCONST(__)) then
4312 <<
4313 <%meta%> = MMC_IMMEDIATE(MMC_TAGFIXNUM(<%boolStrC(exp.bool)%>));
4314 >>
4315 case BOX(exp=exp as RCONST(__)) then
4316 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4317 <<
4318 static const <%litDefReal()%>(<%tmp%>,<%exp.real%>);
4319 #define <%name%> <%litRefReal()%>(<%tmp%>)
4320 >>
4321 case CONS(__) then
4322 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4323 <<
4324 <% literalExpConstBoxedValPreLit(car, litindex + "_car") %><% literalExpConstBoxedValPreLit(cdr, litindex + "_cdr")
4325 %>static const <%litDefBox()%>(<%tmp%>,2,1) {<%literalExpConstBoxedVal(car,litindex + "_car")%>,<%literalExpConstBoxedVal(cdr, litindex + "_cdr")%>}};
4326 #define <%name%> <%litRefBox()%>(<%tmp%>)
4327 >>
4328 case LIST(__) then
4329 let x = listReverse(valList) |> v hasindex i fromindex 1 =>
4330 /* We need to use #defines to be C-compliant. Yea, total crap :) */
4331 '<%literalExpConstBoxedValPreLit(v,tmp + "_elt_" + i)%>static const <%litDefBox()%>(<%tmp + "_cons_" + i%>,2,1) {<%literalExpConstBoxedVal(v,tmp + "_elt_" + i)%>,<%litRefBox()%>(<% match i case 1 then "mmc_nil" else (tmp + "_cons_" + intSub(i,1))%>)}};<%\n%>'
4332 <<
4333 <%x%>
4334 #define <%name%> <%litRefBox()%>(<%tmp%>_cons_<%listLength(valList)%>)
4335 >>
4336 case META_TUPLE(__) then
4337 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4338 <<
4339 <%listExp |> exp hasindex i0 => literalExpConstBoxedValPreLit(exp,litindex+"_"+i0) ; empty
4340 %>static const <%
4341 if listEmpty(listExp) then 'MMC_DEFSTRUCT0LIT(<%tmp%>,0)' else '<%litDefBox()%>(<%tmp%>,<%listLength(listExp)%>,0)'
4342 %> {<%listExp |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0); separator=","%>}};
4343 #define <%name%> <%litRefBox()%>(<%tmp%>)
4344 >>
4345 case META_OPTION(exp=SOME(exp)) then
4346 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4347 <<
4348 <%literalExpConstBoxedValPreLit(exp,litindex+"_1")
4349 %>static const <%litDefBox()%>(<%tmp%>,1,1) {<%literalExpConstBoxedVal(exp,litindex+"_1")%>}};
4350 #define <%name%> <%litRefBox()%>(<%tmp%>)
4351 >>
4352 case METARECORDCALL(__) then
4353 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4354 let newIndex = getValueCtor(index)
4355 <<
4356 <%args |> exp hasindex i0 => literalExpConstBoxedValPreLit(exp,litindex+"_"+i0) ; empty
4357 %>static const <%litDefBox()%>(<%tmp%>,<%intAdd(1,listLength(args))%>,<%newIndex%>) {&<%underscorePath(path)%>__desc,<%args |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0); separator=","%>}};
4358 #define <%name%> <%litRefBox()%>(<%tmp%>)
4359 >>
4360 case CALL(path=IDENT(name="listArrayLiteral"), expLst={e}) then
4361 /* We need to use #define's to be C-compliant. Yea, total crap :) */
4362 match consToListIgnoreSharedLiteral(e)
4363 case LIST(valList=args) then
4364 <<
4365 <%args |> exp hasindex i0 => literalExpConstBoxedValPreLit(exp,litindex+"_"+i0) ; empty
4366 %>static const <%litDefBox()%>(<%tmp%>,<%listLength(args)%>,<%litArrayTag(listLength(args))%>) {<%args |> exp hasindex i0 => literalExpConstBoxedVal(exp,litindex+"_"+i0); separator=","%>}};
4367 #define <%name%> <%litRefBox()%>(<%tmp%>)
4368 >>
4369 else error(sourceInfo(), 'literalExpConst failed; listArrayLiteral requires a list or cons-cells: <%ExpressionDumpTpl.dumpExp(e,"\"")%>')
4370 else error(sourceInfo(), 'literalExpConst failed: <%ExpressionDumpTpl.dumpExp(lit,"\"")%>')
4371 end literalExpConst;
4372
4373 10416 template literalExpConstBoxedVal(Exp lit, Text index)
4374 ::=
4375 let name = '_OMC_LIT<%index%>'
4376 match lit
4377 case ICONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%integer%>))'
4378 case ENUM_LITERAL(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%index%>))'
4379 case lit as BCONST(__) then 'MMC_IMMEDIATE(MMC_TAGFIXNUM(<%boolStrC(lit.bool)%>))'
4380 case lit as RCONST(__) then name
4381 case LIST(valList={}) then
4382 <<
4383 <%litRefBox()%>(mmc_nil)
4384 >>
4385 case META_OPTION(exp=NONE()) then
4386 <<
4387 <%litRefBox()%>(mmc_none)
4388 >>
4389 case lit as BOX(__) then literalExpConstBoxedVal(lit.exp, index)
4390 case lit as SHARED_LITERAL(__) then '_OMC_LIT<%lit.index%>'
4391 else error(sourceInfo(), 'literalExpConstBoxedVal failed: <%ExpressionDumpTpl.dumpExp(lit,"\"")%>')
4392 end literalExpConstBoxedVal;
4393
4394 1576 template literalExpConstBoxedValPreLit(Exp lit, Text index)
4395 ::=
4396 match lit
4397 case lit as RCONST(__) then
4398 let tmp = '_OMC_LIT_STRUCT<%index%>'
4399 let name = '_OMC_LIT<%index%>'
4400 <<
4401 static const <%litDefReal()%>(<%tmp%>,<%lit.real%>);
4402 #define <%name%> <%litRefReal()%>(<%tmp%>)<%\n%>
4403 >>
4404 case lit as BOX(__) then literalExpConstBoxedValPreLit(lit.exp, index)
4405 end literalExpConstBoxedValPreLit;
4406
4407 50538 template literalExpConstArrayVal(Exp lit)
4408 ::=
4409 match lit
4410 case SCONST(__) then '"<%Util.escapeModelicaStringToCString(string)%>"'
4411 case ICONST(__) then integer
4412 case BCONST(__) then boolStrC(bool)
4413 case RCONST(__) then real
4414 case ENUM_LITERAL(__) then index
4415 case SHARED_LITERAL(__) then '_OMC_LIT<%index%>'
4416 else error(sourceInfo(), 'literalExpConstArrayVal failed: <%ExpressionDumpTpl.dumpExp(lit,"\"")%>')
4417 end literalExpConstArrayVal;
4418
4419
4420 514485 template varType(Variable var)
4421 "Generates type for a variable."
4422 // TODO: mahge: rewrite from here downstream
4423 ::=
4424 match var
4425 case var as VARIABLE(parallelism = NON_PARALLEL()) then
4426 if instDims then
4427 expTypeArray(var.ty)
4428 else
4429 expTypeArrayIf(var.ty)
4430 case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARGLOBAL(__)) then
4431 'device_<%expTypeArray(var.ty)%>'
4432 case var as VARIABLE(parallelism = PARGLOBAL()) then
4433 if instDims then
4434 'device_<%expTypeArray(var.ty)%>'
4435 else
4436 '<%expTypeArrayIf(var.ty)%>'
4437 case var as VARIABLE(ty=T_ARRAY(__), parallelism = PARLOCAL(__)) then
4438 'device_local_<%expTypeArray(var.ty)%>'
4439 case var as VARIABLE(parallelism = PARLOCAL()) then
4440 if instDims then
4441 'device_local_<%expTypeArray(var.ty)%>'
4442 else
4443 expTypeArrayIf(var.ty)
4444 end varType;
4445
4446 21710 template varTypeBoxed(Variable var)
4447 ::=
4448 match var
4449 case VARIABLE(__) then 'modelica_metatype'
4450 case FUNCTION_PTR(__) then 'modelica_fnptr'
4451 end varTypeBoxed;
4452
4453 7881 template retVarType(Variable var)
4454 "The type of the first output as the unboxed prototype returns it: varType has
4455 no FUNCTION_PTR case, so it alone would declare the variable typeless."
4456 ::=
4457 match var
4458 case VARIABLE(__) then varType(var)
4459 case FUNCTION_PTR(__) then 'modelica_fnptr'
4460 end retVarType;
4461
4462
4463 14 template expTypeRW(DAE.Type type)
4464 "Helper to writeOutVarRecordMembers."
4465 ::=
4466 match type
4467 case T_INTEGER(__) then "TYPE_DESC_INT"
4468 case T_REAL(__) then "TYPE_DESC_REAL"
4469 case T_STRING(__) then "TYPE_DESC_STRING"
4470 case T_BOOL(__) then "TYPE_DESC_BOOL"
4471 case T_ENUMERATION(__) then "TYPE_DESC_INT"
4472 case T_ARRAY(__) then '<%expTypeRW(ty)%>_ARRAY'
4473 case T_COMPLEX(complexClassType=RECORD(__))
4474 then "TYPE_DESC_RECORD"
4475 case T_METATYPE(__) case T_METABOXED(__) then "TYPE_DESC_MMC"
4476 end expTypeRW;
4477
4478 127301 template arrayGetSuffix(DAE.Type arrayType, list<DAE.Subscript> subs)
4479 "Picks the fixed-arity element accessor for a fully subscripted 1-D or 2-D array.
4480 The variadic one walks a va_list on every access but is the only one that
4481 expands its subscripts just once."
4482 ::=
4483 match arrayType
4484 case T_ARRAY(dims=dims) then
4485 if boolAnd(intEq(listLength(dims), listLength(subs)),
4486 stringEq(unsafeSubs(subs), "")) then
4487 (match listLength(subs) case 1 then "1" case 2 then "2" else "")
4488 end arrayGetSuffix;
4489
4490 127301 template unsafeSubs(list<DAE.Subscript> subs)
4491 "Non-empty if expanding one of the subscripts more than once would not be safe."
4492 ::=
4493 (subs |> sub => match sub
4494 case INDEX(__) then (if Expression.containsAnyCall(exp) then "x")
4495 else "x")
4496 end unsafeSubs;
4497
4498 1883593 template expTypeShort(DAE.Type type)
4499 "Generate type helper."
4500 ::=
4501 match type
4502 case T_INTEGER(__) then "integer"
4503 case T_REAL(__) then "real"
4504 case T_STRING(__) then "string"
4505 case T_BOOL(__) then "boolean"
4506 case T_ENUMERATION(__) then "integer"
4507 case T_SUBTYPE_BASIC(__) then expTypeShort(complexType)
4508 case T_ARRAY(__) then expTypeShort(ty)
4509 case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then "complex"
4510 case T_COMPLEX(__) then '<%underscorePath(ClassInfUtil.getStateName(complexClassType))%>'
4511 case T_METAUNIONTYPE(__)
4512 case T_METAARRAY(__)
4513 case T_METALIST(__)
4514 case T_METATUPLE(__)
4515 case T_METAOPTION(__)
4516 case T_METAPOLYMORPHIC(__)
4517 case T_METATYPE(__)
4518 case T_METABOXED(__) then "metatype"
4519 case T_FUNCTION(__)
4520 case T_FUNCTION_REFERENCE_FUNC(__)
4521 case T_FUNCTION_REFERENCE_VAR(__) then "fnptr"
4522 case T_UNKNOWN(__) then if metaModelicaRuntime() /* TODO: Don't do this to me! */
4523 then "complex /* assuming void* for unknown type! when -g=MetaModelica */ "
4524 else "real /* assuming real for unknown type! */"
4525 case T_ANYTYPE(__) then "complex" /* TODO: Don't do this to me! */
4526 else error(sourceInfo(),'expTypeShort: <%unparseType(type)%>')
4527 end expTypeShort;
4528
4529 71722 template mmcTypeShort(DAE.Type type)
4530 ::=
4531 match type
4532 case T_INTEGER(__) then "integer"
4533 case T_REAL(__) then "real"
4534 case T_STRING(__) then "string"
4535 case T_BOOL(__) then "integer"
4536 case T_ENUMERATION(__) then "integer"
4537 case T_ARRAY(__) then "array"
4538 case T_METAUNIONTYPE(__)
4539 case T_METATYPE(__)
4540 case T_METALIST(__)
4541 case T_METAARRAY(__)
4542 case T_METAPOLYMORPHIC(__)
4543 case T_METAOPTION(__)
4544 case T_METATUPLE(__)
4545 case T_METABOXED(__) then "metatype"
4546 case T_FUNCTION_REFERENCE_VAR(__) then "fnptr"
4547
4548 case T_COMPLEX(__) then "metatype"
4549 else error(sourceInfo(), 'mmcTypeShort:ERROR <%unparseType(type)%>')
4550 end mmcTypeShort;
4551
4552
4553 1003 template expType(DAE.Type ty, Boolean array)
4554 "Generate type helper."
4555 ::=
4556 match array
4557 case true then expTypeArray(ty)
4558 case false then expTypeModelica(ty)
4559 end expType;
4560
4561
4562 234874 template expTypeModelica(DAE.Type ty)
4563 "Generate type helper."
4564 ::=
4565 expTypeFlag(ty, 2)
4566 end expTypeModelica;
4567
4568
4569 10124 template expTypeArray(DAE.Type ty)
4570 "Generate type helper."
4571 ::=
4572 expTypeFlag(ty, 3)
4573 end expTypeArray;
4574
4575
4576 639272 template expTypeArrayIf(DAE.Type ty)
4577 "Generate type helper."
4578 ::=
4579 expTypeFlag(ty, 4)
4580 end expTypeArrayIf;
4581
4582
4583 2925 template expTypeFromExpShort(Exp exp)
4584 "Generate type helper."
4585 ::=
4586 expTypeFromExpFlag(exp, 1)
4587 end expTypeFromExpShort;
4588
4589
4590 185000 template expTypeFromExpModelica(Exp exp)
4591 "Generate type helper."
4592 ::=
4593 expTypeFromExpFlag(exp, 2)
4594 end expTypeFromExpModelica;
4595
4596
4597 475 template expTypeFromExpArray(Exp exp)
4598 "Generate type helper."
4599 ::=
4600 expTypeFromExpFlag(exp, 3)
4601 end expTypeFromExpArray;
4602
4603 51789 template expTypeFromExpArrayIf(Exp exp)
4604 "Generate type helper."
4605 ::=
4606 expTypeFromExpFlag(exp, 4)
4607 end expTypeFromExpArrayIf;
4608
4609 1485003 template expTypeFlag(DAE.Type ty, Integer flag)
4610 "Generate type helper."
4611 ::=
4612 match flag
4613 case 1 then
4614 // we want the short type
4615 expTypeShort(ty)
4616 case 2 then
4617 // we want the "modelica type"
4618 match ty case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then
4619 'modelica_<%expTypeShort(ty)%>'
4620 else match ty case T_COMPLEX(__) then
4621 '<%underscorePath(ClassInfUtil.getStateName(complexClassType))%>'
4622 else match ty case T_ARRAY(ty = t as T_COMPLEX(__)) then
4623 expTypeShort(t)
4624 else
4625 'modelica_<%expTypeShort(ty)%>'
4626 case 3 then
4627 // we want the "array type"
4628 '<%expTypeShort(ty)%>_array'
4629 case 4 then
4630 // we want the "array type" only if type is array, otherwise "modelica type"
4631 (match ty
4632 case T_ARRAY(__) then '<%expTypeShort(ty)%>_array'
4633 else expTypeFlag(ty, 2))
4634 case 8 then
4635 (match ty
4636 case T_ARRAY(__) then '<%expTypeFlag(ty,8)%>*'
4637 case T_INTEGER(__) then 'int'
4638 case T_BOOL(__) then 'int'
4639 case T_REAL(__) then 'double'
4640 case T_STRING(__) then 'const char*'
4641 case T_SUBTYPE_BASIC(__) then '<%expTypeFlag(complexType,8)%>*'
4642 else error(sourceInfo(),'I do not know the external type of <%unparseType(ty)%>'))
4643 end expTypeFlag;
4644
4645 131471 template expTypeFromExpFlag(Exp exp, Integer flag)
4646 "Generate type helper."
4647 ::=
4648 match exp
4649 case ICONST(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer"
4650 case RCONST(__) then match flag case 1 then "real" else "modelica_real"
4651 case SCONST(__) then match flag case 1 then "string" else "modelica_string"
4652 case BCONST(__) then match flag case 1 then "boolean" else "modelica_boolean"
4653 case ENUM_LITERAL(__) then match flag case 8 then "int" case 1 then "integer" else "modelica_integer"
4654 case e as BINARY(__)
4655 case e as UNARY(__)
4656 case e as LBINARY(__)
4657 case e as LUNARY(__) then expTypeFromOpFlag(e.operator, flag)
4658 case e as RELATION(__) then match flag case 1 then "boolean" else "modelica_boolean"
4659 case IFEXP(__) then expTypeFromExpFlag(expThen, flag)
4660 case CALL(attr=CALL_ATTR(__)) then expTypeFlag(attr.ty, flag)
4661 case c as RECORD(__) then expTypeFlag(c.ty, flag)
4662 case c as ARRAY(__)
4663 case c as MATRIX(__)
4664 case c as RANGE(__)
4665 case c as CAST(__)
4666 case c as TSUB(__)
4667 case c as CREF(__)
4668 case c as CODE(__) then expTypeFlag(c.ty, flag)
4669 case c as ASUB(__) then expTypeFlag(typeof(c), flag)
4670 case REDUCTION(__) then expTypeFlag(typeof(exp), flag)
4671 case e as CONS(__)
4672 case e as LIST(__)
4673 case e as SIZE(__) then expTypeFlag(typeof(e), flag)
4674 case c as RSUB(ix=-1) then expTypeFlag(c.ty, flag)
4675
4676 case META_TUPLE(__)
4677 case META_OPTION(__)
4678 case MATCHEXPRESSION(__)
4679 case METARECORDCALL(__)
4680 case RSUB(__)
4681 case BOX(__) then match flag case 1 then "metatype" else "modelica_metatype"
4682 case c as UNBOX(__) then expTypeFlag(c.ty, flag)
4683 case c as SHARED_LITERAL(__) then expTypeFromExpFlag(c.exp, flag)
4684 else error(sourceInfo(), 'expTypeFromExpFlag(flag=<%flag%>):<%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
4685 end expTypeFromExpFlag;
4686
4687
4688 2150 template expTypeFromOpFlag(Operator op, Integer flag)
4689 "Generate type helper."
4690 ::=
4691 match op
4692 case o as ADD(__)
4693 case o as SUB(__)
4694 case o as MUL(__)
4695 case o as DIV(__)
4696 case o as POW(__)
4697
4698 case o as UMINUS(__)
4699 case o as UMINUS_ARR(__)
4700 case o as ADD_ARR(__)
4701 case o as SUB_ARR(__)
4702 case o as MUL_ARR(__)
4703 case o as DIV_ARR(__)
4704 case o as MUL_ARRAY_SCALAR(__)
4705 case o as ADD_ARRAY_SCALAR(__)
4706 case o as SUB_SCALAR_ARRAY(__)
4707 case o as MUL_SCALAR_PRODUCT(__)
4708 case o as MUL_MATRIX_PRODUCT(__)
4709 case o as DIV_ARRAY_SCALAR(__)
4710 case o as DIV_SCALAR_ARRAY(__)
4711 case o as POW_ARRAY_SCALAR(__)
4712 case o as POW_SCALAR_ARRAY(__)
4713 case o as POW_ARR(__)
4714 case o as POW_ARR2(__)
4715 case o as LESS(__)
4716 case o as LESSEQ(__)
4717 case o as GREATER(__)
4718 case o as GREATEREQ(__)
4719 case o as EQUAL(__)
4720 case o as NEQUAL(__) then
4721 expTypeFlag(o.ty, flag)
4722 case o as AND(__)
4723 case o as OR(__)
4724 case o as NOT(__) then
4725 match flag case 1 then "boolean" else "modelica_boolean"
4726 else error(sourceInfo(), 'expTypeFromOpFlag:ERROR')
4727 end expTypeFromOpFlag;
4728
4729 15751 template dimension(Dimension d, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
4730 ::=
4731 match d
4732 case DAE.DIM_BOOLEAN(__) then '2'
4733 case DAE.DIM_ENUM(__) then size
4734 case DAE.DIM_EXP(exp=e) then daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
4735 case DAE.DIM_INTEGER(__) then
4736 if intEq(integer, -1) then
4737 error(sourceInfo(),"Negeative dimension(unknown dimensions) may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.")
4738 else
4739 integer
4740 case DAE.DIM_UNKNOWN(__) then error(sourceInfo(),"Unknown dimensions may not be part of generated code. This is most likely an error on the part of OpenModelica. Please submit a detailed bug-report.")
4741 else error(sourceInfo(), 'dimension: INVALID_DIMENSION')
4742 end dimension;
4743
4744 636 template algStmtAssignPattern(DAE.Statement stmt, Context context, Text &varDecls, Text &varFrees, Text &auxFunction)
4745 "Generates an assigment algorithm statement."
4746 ::=
4747 match stmt
4748 case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_CALL_TUPLE(patterns=pat::patterns)),exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=ty::tys)))) then
4749 let &preExp = buffer ""
4750 let &assignments1 = buffer ""
4751 let &assignments = buffer ""
4752 let &additionalOutputs = buffer ""
4753 let &matchPhase = buffer ""
4754 let _ = List.zip(patterns,tys) |> (pat,ty) => match pat
4755 case PAT_WILD(__) then
4756 let &additionalOutputs += ", NULL"
4757 ""
4758 else
4759 let v = tempDecl(expTypeArrayIf(ty), &varDecls, &varFrees)
4760 let &additionalOutputs += ', &<%v%>'
4761 let &matchPhase += patternMatch(pat,v,generateThrow(),&varDecls, &varFrees,&assignments)
4762 ""
4763 let expPart = daeExpCallTuple(s.exp,additionalOutputs,context, &preExp, &varDecls, &varFrees, &auxFunction)
4764 match pat
4765 case PAT_WILD(__) then '/* Pattern-matching tuple assignment, wild first pattern */<%\n%><%preExp%><%expPart%>;<%\n%><%matchPhase%><%assignments%>'
4766 else
4767 let v = tempDecl(expTypeArrayIf(ty), &varDecls, &varFrees)
4768 let res = patternMatch(pat,v,generateThrow(),&varDecls, &varFrees,&assignments1)
4769 <<
4770 /* Pattern-matching tuple assignment */
4771 <%preExp%>
4772 <%v%> = <%expPart%>;
4773 <%res%><%assignments1%><%matchPhase%><%assignments%>
4774 >>
4775 case s as STMT_ASSIGN(exp1=lhs as PATTERN(pattern=PAT_WILD(__))) then
4776 error(sourceInfo(),'Improve simplifcation, got pattern assignment _ = <%ExpressionDumpTpl.dumpExp(exp,"\"")%>, expected NORETCALL')
4777 case s as STMT_ASSIGN(exp1=lhs as PATTERN(__)) then
4778 let &preExp = buffer ""
4779 let &assignments = buffer ""
4780 let expPart = daeExp(s.exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
4781 let v = tempDecl(expTypeFromExpModelica(s.exp), &varDecls, &varFrees)
4782 <<
4783 /* Pattern-matching assignment */
4784 <%preExp%>
4785 <%v%> = <%expPart%>;
4786 <%patternMatch(lhs.pattern,v,generateThrow(),&varDecls, &varFrees,&assignments)%><%assignments%>
4787 >>
4788 end algStmtAssignPattern;
4789
4790 8084 template patternMatch(Pattern pat, Text rhs, Text onPatternFail, Text &varDecls, Text &varFrees, Text &assignments)
4791 ::=
4792 match pat
4793 case PAT_WILD(__) then ""
4794 case p as PAT_CONSTANT(__)
4795 then
4796 let &unboxBuf = buffer ""
4797 let urhs = (match p.ty
4798 case SOME(et) then unboxVariable(rhs, et, &unboxBuf, &varDecls, &varFrees)
4799 else rhs
4800 )
4801 <<<%unboxBuf%><%match p.exp
4802 case c as ICONST(__) then 'if (<%c.integer%> != <%urhs%>) <%onPatternFail%>;<%\n%>'
4803 case c as RCONST(__) then 'if (<%c.real%> != <%urhs%>) <%onPatternFail%>;<%\n%>'
4804 case c as SCONST(__) then
4805 let escstr = Util.escapeModelicaStringToCString(c.string)
4806 'if (<%unescapedStringLength(escstr)%> != omc_string_len(<%urhs%>) || strcmp("<%escstr%>", omc_string_data(<%urhs%>)) != 0) <%onPatternFail%>;<%\n%>'
4807 case c as SHARED_LITERAL(exp=d as SCONST(__)) then
4808 let escstr = Util.escapeModelicaStringToCString(d.string)
4809 'if (<%unescapedStringLength(escstr)%> != omc_string_len(<%urhs%>) || strcmp(omc_string_data(_OMC_LIT<%c.index%>), omc_string_data(<%urhs%>)) != 0) <%onPatternFail%>;<%\n%>'
4810 case c as BCONST(__) then 'if (<%boolStrC(c.bool)%> != <%urhs%>) <%onPatternFail%>;<%\n%>'
4811 case c as LIST(valList = {}) then 'if (!listEmpty(<%urhs%>)) <%onPatternFail%>;<%\n%>'
4812 case c as META_OPTION(exp = NONE()) then 'if (!optionNone(<%urhs%>)) <%onPatternFail%>;<%\n%>'
4813 case c as ENUM_LITERAL() then 'if (<%c.index%> != <%urhs%>) <%onPatternFail%>;<%\n%>'
4814 case c as SHARED_LITERAL() then 'if (!valueEq(_OMC_LIT<%c.index%>, <%urhs%>)) <%onPatternFail%>;<%\n%>'
4815 else error(sourceInfo(), 'UNKNOWN_CONSTANT_PATTERN <%ExpressionDumpTpl.dumpExp(p.exp,"\"")%>')
4816 %>>>
4817 case p as PAT_SOME(__) then
4818 let tvar = tempDecl("modelica_metatype", &varDecls, &varFrees)
4819 <<if (optionNone(<%rhs%>)) <%onPatternFail%>;
4820 <%tvar%> = OMC_BOX_FIELD(<%rhs%>, 1);
4821 <%patternMatch(p.pat,tvar,onPatternFail,&varDecls, &varFrees,&assignments)%>>>
4822 case PAT_CONS(__) then
4823 let tvarHead = tempDecl("modelica_metatype", &varDecls, &varFrees)
4824 let tvarTail = tempDecl("modelica_metatype", &varDecls, &varFrees)
4825 <<if (listEmpty(<%rhs%>)) <%onPatternFail%>;
4826 <%tvarHead%> = MMC_CAR(<%rhs%>);
4827 <%tvarTail%> = MMC_CDR(<%rhs%>);
4828 <%patternMatch(head,tvarHead,onPatternFail,&varDecls, &varFrees,&assignments)%><%patternMatch(tail,tvarTail,onPatternFail,&varDecls, &varFrees,&assignments)%>>>
4829 case PAT_META_TUPLE(__)
4830 then
4831 (patterns |> p hasindex i1 fromindex 1 =>
4832 match p
4833 case PAT_WILD(__) then ""
4834 else
4835 let tvar = tempDecl("modelica_metatype", &varDecls, &varFrees)
4836 <<<%tvar%> = OMC_BOX_FIELD(<%rhs%>, <%i1%>);
4837 <%patternMatch(p,tvar,onPatternFail,&varDecls, &varFrees,&assignments)%>
4838 >>; empty /* increase the counter even if no output is produced */)
4839 case PAT_CALL_TUPLE(__)
4840 then
4841 // misnomer. Call expressions no longer return tuples using these structs. match-expressions and if-expressions converted to Modelica tuples do
4842 (patterns |> p hasindex i1 fromindex 1 =>
4843 match p
4844 case PAT_WILD(__) then ""
4845 else
4846 let nrhs = '<%rhs%>.c<%i1%>'
4847 patternMatch(p,nrhs,onPatternFail,&varDecls, &varFrees,&assignments)
4848 ; empty /* increase the counter even if no output is produced */
4849 )
4850 case PAT_CALL_NAMED(__)
4851 then
4852 <<<%patterns |> (p,n,t) =>
4853 match p
4854 case PAT_WILD(__) then ""
4855 else
4856 let tvar = tempDecl(expTypeArrayIf(t), &varDecls, &varFrees)
4857 <<<%rcAssignRetain(expTypeArrayIf(t), tvar, '<%rhs%>._<%n%>')%><%patternMatch(p,tvar,onPatternFail,&varDecls, &varFrees,&assignments)%>
4858 >>%>
4859 >>
4860 case PAT_CALL(__)
4861 then
4862 <<<%if not knownSingleton then 'if (mmc__uniontype__metarecord__typedef__equal(<%rhs%>,<%index%>,<%listLength(patterns)%>) == 0) <%onPatternFail%>;<%\n%>'%><%
4863 (patterns |> p hasindex i2 fromindex 2 =>
4864 match p
4865 case PAT_WILD(__) then ""
4866 else
4867 let tvar = tempDecl("modelica_metatype", &varDecls, &varFrees)
4868 <<<%tvar%> = OMC_BOX_FIELD(<%rhs%>, <%i2%>);
4869 <%patternMatch(p,tvar,onPatternFail,&varDecls, &varFrees,&assignments)%>
4870 >> ;empty) /* increase the counter even if no output is produced */
4871 %>
4872 >>
4873 case p as PAT_AS_FUNC_PTR(__) then
4874 let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>'
4875 <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls, &varFrees,&assignments)%>
4876 >>
4877 case p as PAT_AS(ty = NONE()) then
4878 let &assignments += '_<%p.id%> = <%rhs%>;<%\n%>'
4879 <<<%patternMatch(p.pat,rhs,onPatternFail,&varDecls, &varFrees,&assignments)%>
4880 >>
4881 case p as PAT_AS(ty = SOME(et)) then
4882 let &unboxBuf = buffer ""
4883 let &assignments += '_<%p.id%> = <%unboxVariable(rhs, et, &unboxBuf, &varDecls, &varFrees)%> /* pattern as ty=<%unparseType(et)%> */;<%\n%>'
4884 <<<%&unboxBuf%>
4885 <%patternMatch(p.pat,rhs,onPatternFail,&varDecls, &varFrees,&assignments)%>
4886 >>
4887 else error(sourceInfo(), 'UNKNOWN_PATTERN /* rhs: <%rhs%> */<%\n%>')
4888 end patternMatch;
4889
4890 72416 template infoArgs(SourceInfo info)
4891 ::=
4892 match info
4893 case SOURCEINFO(__) then '"<%Util.escapeModelicaStringToCString(Testsuite.friendly(fileName))%>",<%lineNumberStart%>,<%columnNumberStart%>,<%lineNumberEnd%>,<%columnNumberEnd%>,<%if isReadOnly then 1 else 0%>'
4894 end infoArgs;
4895
4896 33907 template assertCommon(Exp condition, list<Exp> messages, Exp level, Context context, Text &varDecls, Text &varFrees, Text &auxFunction, builtin.SourceInfo info)
4897 ::=
4898 let &preExpCond = buffer ""
4899 let condVar = daeExp(condition, context, &preExpCond, &varDecls, &varFrees, &auxFunction)
4900 let &preExpMsg = buffer ""
4901 let msgVar = messages |> message => expToFormatString(message,context,&preExpMsg,&varDecls, &varFrees,&auxFunction) ; separator = ", "
4902 let AddionalFuncName = match context
4903 case FUNCTION_CONTEXT(__) then ''
4904 else '_withEquationIndexes'
4905 let assertExpStr = Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(condition,"\""))
4906 /* Note that our error/log functions split the message on new lines and indent it. So it is better to have one long string
4907 and send it to them instead of calling them repeatedlly (avoids the 'assert', 'warning' labels printed for each call.) */
4908 let infoTextContext = '"The following assertion has been violated %sat time %f\n(%s) --> \"%s\"", initial() ? "during initialization " : "", data->localData[0]->timeValue, assert_cond, <%msgVar%>'
4909 let omcAssertFunc = match level case ENUM_LITERAL(index=1) then 'omc_assert_warning<%AddionalFuncName%>(' else 'omc_assert<%AddionalFuncName%>(threadData, '
4910 let rethrow = match level case ENUM_LITERAL(index=1) then '' else '<%\n%>data->simulationInfo->needToReThrow = 1;'
4911 // A violated assert leaves the frame; a warning carries on.
4912 let assertCheck = match level case ENUM_LITERAL(index=1) then '' else errorCheck(context)
4913 let assertCode = match context case FUNCTION_CONTEXT(__) then
4914 <<
4915 FILE_INFO info = {<%infoArgs(info)%>};
4916 <%omcAssertFunc%>info, <%msgVar%>);
4917 <%assertCheck%>
4918 >>
4919 else
4920 <<
4921 const char* assert_cond = "(<%assertExpStr%>)";
4922 if (data->simulationInfo->noThrowAsserts) {
4923 FILE_INFO info = {<%infoArgs(info)%>};
4924 infoStreamPrintWithEquationIndexes(OMC_LOG_ASSERT, info, 0, equationIndexes, <%infoTextContext%>);<%rethrow%>
4925 } else {
4926 FILE_INFO info = {<%infoArgs(info)%>};
4927 <%omcAssertFunc%>info, equationIndexes, <%infoTextContext%>);
4928 <%assertCheck%>
4929 }
4930 >>
4931 let warningTriggered = tempDeclZero("static int", &varDecls, &varFrees)
4932 let TriggerIf = match level case ENUM_LITERAL(index=1) then 'if(!<%warningTriggered%>)<%\n%>' else ''
4933 let TriggerVarSet = match level case ENUM_LITERAL(index=1) then '<%warningTriggered%> = 1;<%\n%>' else ''
4934 <<
4935 <%TriggerIf%>
4936 {
4937 <%preExpCond%>
4938 if(!<%condVar%>)
4939 {
4940 <%preExpMsg%>
4941 {
4942 <%assertCode%>
4943 }
4944 <%TriggerVarSet%>
4945 }
4946 }<%\n%>
4947 >>
4948 end assertCommon;
4949
4950 33907 template expToFormatString(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
4951 ::=
4952 'omc_string_data(<%daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)'
4953 end expToFormatString;
4954
4955 3584 template assertCommonVar(Text condVar, Text msgVar, Context context, Text &varDecls, Text &varFrees, builtin.SourceInfo info)
4956 ::=
4957 match context
4958 // OpenCL does not have support for variadic args. So message should be just a single string.
4959 case FUNCTION_CONTEXT(is_parallel = true) then
4960 <<
4961 if(!(<%condVar%>))
4962 {
4963 omc_assert(threadData, omc_dummyFileInfo, "Common assertion failed");
4964 }
4965 >>
4966 case FUNCTION_CONTEXT(__) then
4967 <<
4968 if(!(<%condVar%>))
4969 {
4970 FILE_INFO info = {<%infoArgs(info)%>};
4971 omc_assert(threadData, info, <%msgVar%>);
4972 <%errorCheck(context)%>
4973 }
4974 >>
4975 else
4976 <<
4977 if(!(<%condVar%>))
4978 {
4979 if (data->simulationInfo->noThrowAsserts) {
4980 FILE_INFO info = {<%infoArgs(info)%>};
4981 infoStreamPrintWithEquationIndexes(OMC_LOG_ASSERT, info, 0, equationIndexes, "The following assertion has been violated %sat time %f", initial() ? "during initialization " : "", data->localData[0]->timeValue);
4982 data->simulationInfo->needToReThrow = 1;
4983 } else {
4984 FILE_INFO info = {<%infoArgs(info)%>};
4985 omc_assert_warning(info, "The following assertion has been violated %sat time %f", initial() ? "during initialization " : "", data->localData[0]->timeValue);
4986 raiseStreamPrintWithEquationIndexes(threadData, info, equationIndexes, <%msgVar%>);
4987 <%errorCheck(context)%>
4988 }
4989 }
4990 >>
4991 end assertCommonVar;
4992
4993 898293 template contextCrefNoPrevExp(ComponentRef cr, Context context, Text &auxFunction)
4994 "mahge: A convenience function to use instead of contextCref when you are sure that
4995 your cref will not generate any previous expression or does not need any auxilary variable
4996 decalrations. This basically means that the cref is either a path (has no subscripts)
4997 or the subscripts are simple expressions that can be generated inline."
4998 ::=
4999 let &preExp = buffer ""
5000 let &varDecls = buffer ""
5001 let &varFrees = buffer ""
5002 let &sub = buffer ""
5003 contextCref(cr, context, &preExp, &varDecls, &varFrees, auxFunction, &sub)
5004 end contextCrefNoPrevExp;
5005
5006 2119324 template contextCref(ComponentRef cr, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction, Text &sub)
5007 "Generates code for a component reference depending on which context we're in."
5008 ::=
5009 match context
5010 case FUNCTION_CONTEXT(__) then
5011 // get the current cref prefix that is set in the context.
5012 let cur_pref = getCurrentCrefPrefix(context)
5013 functionContextCref(cr, context, cur_pref, &preExp, &varDecls, &varFrees, auxFunction)
5014 case JACOBIAN_CONTEXT(jacHT=SOME(_)) then jacCrefs(cr, context, 0, &sub)
5015 else
5016 // varArrayNameValues inlines the constant but has no buffer for a
5017 // literal. The guarded crefs are the ones cref2simvar cannot look up.
5018 (match cr
5019 case CREF_IDENT(ident = "time")
5020 case CREF_IDENT(ident = "$DAE_CJ") then cref(cr, &sub)
5021 case CREF_QUAL(ident = "$PRE")
5022 case CREF_QUAL(ident = "$START") then cref(cr, &sub)
5023 else
5024 (match cref2simvar(cr, getSimCode())
5025 case SIMVAR(varKind = CONST(), initialValue = SOME(SCONST(string = str))) then
5026 stringConstLiteral(str, &auxFunction)
5027 else cref(cr, &sub)))
5028 end contextCref;
5029
5030 1 template stringConstLiteral(String str, Text &auxFunction)
5031 "A constant has no storage, so its value is inlined; here that value is an
5032 object with a header, and immortal."
5033 ::=
5034 let esc = Util.escapeModelicaStringToCString(str)
5035 let name = '_OMC_SCONST<%System.tmpTick()%>'
5036 let &auxFunction += 'static const <%litDefString()%>(<%name%>,<%unescapedStringLength(esc)%>,"<%esc%>");<%\n%>'
5037 '<%litRefString()%>(<%name%>)'
5038 end stringConstLiteral;
5039
5040 1336783 template functionContextCref(ComponentRef cr, Context context, Text& pref, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5041 "Generates code for a component reference for function contexts. Handles qualified names properly.
5042 This will underscore all idents. See functionContextCrefFirstIdentNoUnderscore as well."
5043 ::=
5044 match cr
5045 case cr as CREF_QUAL(identType = T_ARRAY(), subscriptLst = _::_) then
5046 let typeName = expTypeShort(identType)
5047 let dimsLenStr = listLength(cr.subscriptLst)
5048 let dimsValuesStr = (cr.subscriptLst |> sub => daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction) ; separator=", ")
5049
5050 let fullname = pref + '_' + System.unquoteIdentifier(cr.ident)
5051 let fullname_i = '<%typeName%>_array_get<%arrayGetSuffix(identType, cr.subscriptLst)%>(<%fullname%>, <%dimsLenStr%>, <%dimsValuesStr%>)'
5052 let newpref = fullname_i + '.'
5053 functionContextCref(cr.componentRef, context, newpref, &preExp, &varDecls, &varFrees, &auxFunction)
5054
5055 case cr as CREF_QUAL(identType = T_ARRAY(), subscriptLst = {}) then
5056 // Array-type prefix with no subscripts: access as a whole-array field in function context.
5057 // OpenModelica flattens record arrays to per-field arrays in C function parameters,
5058 // so the component name is used as a prefix just like the non-array case.
5059 let fullname = pref + '_' + System.unquoteIdentifier(cr.ident)
5060 let newpref = fullname + '.'
5061 functionContextCref(cr.componentRef, context, newpref, &preExp, &varDecls, &varFrees, &auxFunction)
5062
5063 case cr as CREF_QUAL() then
5064 let fullname = pref + '_' + System.unquoteIdentifier(cr.ident)
5065 let newpref = fullname + '.'
5066 functionContextCref(cr.componentRef, context, newpref, &preExp, &varDecls, &varFrees, &auxFunction)
5067
5068 case cr as CREF_IDENT(identType = T_ARRAY(), subscriptLst = _::_) then
5069 let typeName = expTypeShort(identType)
5070 let dimsLenStr = listLength(cr.subscriptLst)
5071 let dimsValuesStr = (cr.subscriptLst |> sub => daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction) ; separator=", ")
5072
5073 let fullname = pref + '_' + System.unquoteIdentifier(cr.ident)
5074 let fullname_i = '<%typeName%>_array_get<%arrayGetSuffix(identType, cr.subscriptLst)%>(<%fullname%>, <%dimsLenStr%>, <%dimsValuesStr%>)'
5075 fullname_i
5076
5077 case cr as CREF_IDENT() then
5078 let fullname = pref + '_' + System.unquoteIdentifier(cr.ident)
5079 fullname
5080
5081 else
5082 error(sourceInfo(), 'functionContextCref got a cref it does not know how to handle <%crefStrNoUnderscore(cr)%>')
5083 end match
5084 end functionContextCref;
5085
5086 15206 template functionContextCrefFirstIdentNoUnderscore(ComponentRef cr, Context context, Text& pref, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5087 "The only difference between this and functionContextCref is that this will
5088 not prefix the first ident with underscore."
5089 ::=
5090 match cr
5091 case cr as CREF_QUAL(identType = T_ARRAY(), subscriptLst = _::_) then
5092
5093 let typeName = expTypeShort(identType)
5094 let dimsLenStr = listLength(cr.subscriptLst)
5095 let dimsValuesStr = (cr.subscriptLst |> sub => daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction) ; separator=", ")
5096
5097 let fullname = pref + System.unquoteIdentifier(cr.ident)
5098 let fullname_i = '<%typeName%>_array_get<%arrayGetSuffix(identType, cr.subscriptLst)%>(<%fullname%>, <%dimsLenStr%>, <%dimsValuesStr%>)'
5099 let newpref = fullname_i + '.'
5100 functionContextCref(cr.componentRef, context, newpref, &preExp, &varDecls, &varFrees, &auxFunction)
5101
5102 case cr as CREF_QUAL() then
5103 let fullname = pref + System.unquoteIdentifier(cr.ident)
5104 let newpref = fullname + '.'
5105 functionContextCref(cr.componentRef, context, newpref, &preExp, &varDecls, &varFrees, &auxFunction)
5106
5107 case cr as CREF_IDENT(identType = T_ARRAY(), subscriptLst = _::_) then
5108
5109 let typeName = expTypeShort(identType)
5110 let dimsLenStr = listLength(cr.subscriptLst)
5111 let dimsValuesStr = (cr.subscriptLst |> sub => daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction) ; separator=", ")
5112
5113 let fullname = pref + System.unquoteIdentifier(cr.ident)
5114 let fullname_i = '<%typeName%>_array_get<%arrayGetSuffix(identType, cr.subscriptLst)%>(<%fullname%>, <%dimsLenStr%>, <%dimsValuesStr%>)'
5115 fullname_i
5116
5117 case cr as CREF_IDENT() then
5118 let fullname = pref + System.unquoteIdentifier(cr.ident)
5119 fullname
5120
5121 else
5122 error(sourceInfo(), 'crefNonSimVar got a cref it does not know how to handle <%crefStrNoUnderscore(cr)%>')
5123 end match
5124 end functionContextCrefFirstIdentNoUnderscore;
5125
5126
5127 7338 template contextCrefOld(ComponentRef cr, Context context, Text &auxFunction, Integer ix)
5128 "TODO: Deprecated. Remove me!. Generates code for a component reference depending on which context we're in."
5129 ::=
5130 match context
5131 case FUNCTION_CONTEXT(__) then
5132 (match cr
5133 case CREF_QUAL(identType = T_ARRAY(ty = T_COMPLEX(complexClassType = record_state))) then
5134 let &preExp = buffer ""
5135 let &varDecls = buffer ""
5136 let &varFrees = buffer ""
5137 let rec_name = '<%underscorePath(ClassInfUtil.getStateName(record_state))%>'
5138 let recPtr = tempDecl(rec_name + "*", &varDecls, &varFrees)
5139 let dimsLenStr = listLength(crefSubs(cr))
5140 let dimsValuesStr = (crefSubs(cr) |> INDEX(__) => daeSubscriptExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction) ; separator=", ")
5141 <<
5142 <%rec_name%>_array_get(_<%ident%>, <%dimsLenStr%>, <%dimsValuesStr%>)-><%contextCrefNoPrevExp(componentRef, context, &auxFunction)%>
5143 >>
5144 else "_" + System.unquoteIdentifier(CodegenUtil.crefStr(cr))
5145 )
5146 case JACOBIAN_CONTEXT(jacHT=SOME(_)) then
5147 let &sub = buffer ""
5148 jacCrefs(cr, context, ix, &sub)
5149 else crefOld(cr, ix)
5150 end contextCrefOld;
5151
5152 2101 template isJacobianElementVar(ComponentRef cr, Context context)
5153 "true if the subscripted cr is a variable of the Jacobian on its own, not an
5154 element of an array variable"
5155 ::=
5156 match context
5157 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
5158 match simVarExactFromHT(cr, jacHT)
5159 case SOME(_) then "true"
5160 else ""
5161 else ""
5162 end isJacobianElementVar;
5163
5164 75787 template jacobianVarIndex(SimVar var, Context context)
5165 "The position of a Jacobian variable in its seed, tmp or result array, an
5166 expression of the structural parameters if a variable before it has a size
5167 only known at runtime (resizable arrays), see jacobianIndexExp."
5168 ::=
5169 match context
5170 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
5171 match jacobianIndexExp(var, jacHT)
5172 case ICONST(__) then integer
5173 case e then
5174 let &preExp = buffer ""
5175 let &varDecls = buffer ""
5176 let &varFrees = buffer ""
5177 let &auxFunction = buffer ""
5178 '(<%daeExp(e, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)%>)'
5179 else match var case SIMVAR(__) then index
5180 end jacobianVarIndex;
5181
5182 82382 template jacCrefs(ComponentRef cr, Context context, Integer ix, Text &sub)
5183 "Generates code for jacobian variables."
5184 ::=
5185 match context
5186 case JACOBIAN_CONTEXT(name=jacName, jacHT=SOME(jacHT)) then
5187 match simVarFromHT(cr, jacHT)
5188 case v as SIMVAR(varKind=BackendDAE.JAC_VAR()) then
5189 if stringEq(sub, "") then 'jacobian->resultVars[<%jacobianVarIndex(v, context)%>]<%crefCCommentWithVariability(v)%>'
5190 else '(&(jacobian->resultVars[<%jacobianVarIndex(v, context)%>]))<%&sub%><%crefCCommentWithVariability(v)%>'
5191 case v as SIMVAR(varKind=BackendDAE.JAC_TMP_VAR()) then
5192 if stringEq(sub, "") then 'jacobian->tmpVars[<%jacobianVarIndex(v, context)%>]<%crefCCommentWithVariability(v)%>'
5193 else '(&(jacobian->tmpVars[<%jacobianVarIndex(v, context)%>]))<%&sub%><%crefCCommentWithVariability(v)%>'
5194 case v as SIMVAR(varKind=BackendDAE.SEED_VAR()) then
5195 if stringEq(sub, "") then 'jacobian->seedVars[<%jacobianVarIndex(v, context)%>]<%crefCCommentWithVariability(v)%>'
5196 else '(&(jacobian->seedVars[<%jacobianVarIndex(v, context)%>]))<%&sub%><%crefCCommentWithVariability(v)%>'
5197 case SIMVAR(index=-2) then
5198 if boolAnd(stringEq(sub, ""), isJacobianColumnCref(cr)) then '0.0' else
5199 // Subscripted seed cref not in jac_map (e.g. a cross-Jacobian seed
5200 // reference, or a whole-array seed accessed with a dynamic subscript).
5201 // Retry with the subscripts stripped: if the base cref resolves to a
5202 // SEED_VAR, use ITS index (not the original -2) so the subscript
5203 // (still carried separately in &sub) addresses the right seed array.
5204 // Otherwise fall through to crefOld for actual values / loop iterators.
5205 match simVarFromHT(crefStripSubs(cr), jacHT)
5206 case v as SIMVAR(varKind=BackendDAE.SEED_VAR()) then
5207 if stringEq(sub, "") then 'jacobian->seedVars[<%jacobianVarIndex(v, context)%>]<%crefCCommentWithVariability(v)%>'
5208 else '(&(jacobian->seedVars[<%jacobianVarIndex(v, context)%>]))<%&sub%><%crefCCommentWithVariability(v)%>'
5209 else
5210 // Still not found: seed cached under a different Jacobian's name. Retry with the root renamed to this Jacobian.
5211 match simVarFromHT(crefRenameSeedRoot(crefStripSubs(cr), jacName), jacHT)
5212 case v as SIMVAR(varKind=BackendDAE.SEED_VAR()) then
5213 if stringEq(sub, "") then 'jacobian->seedVars[<%jacobianVarIndex(v, context)%>]<%crefCCommentWithVariability(v)%>'
5214 else '(&(jacobian->seedVars[<%jacobianVarIndex(v, context)%>]))<%&sub%><%crefCCommentWithVariability(v)%>'
5215 else crefOldSub(cr, ix, &sub)
5216 end jacCrefs;
5217
5218 ✗ template jacSparsityIndex(ComponentRef cr, Context context)
5219 ::=
5220 match context
5221 case JACOBIAN_CONTEXT(jacHT=SOME(jacHT)) then
5222 match simVarFromHT(cr, jacHT)
5223 case v as SIMVAR(varKind=BackendDAE.JAC_VAR()) then 'ROW <%index%> (<%crefCComment(v, crefStrNoUnderscore(name))%>)'
5224 case v as SIMVAR(varKind=BackendDAE.JAC_TMP_VAR()) then 'ROW TMP <%index%> (<%crefCComment(v, crefStrNoUnderscore(name))%>)'
5225 case v as SIMVAR(varKind=BackendDAE.SEED_VAR()) then 'SEED <%index%> (<%crefCComment(v, crefStrNoUnderscore(name))%>)'
5226 else 'NOT FOUND'
5227 end jacSparsityIndex;
5228
5229 18185 template contextCrefIsPre(ComponentRef cr, Context context, Text &auxFunction, Boolean isPre)
5230 "Generates code for a component reference depending on which context we're in."
5231 ::=
5232 if isPre then
5233 crefPre(cr)
5234 else contextCrefNoPrevExp(cr, context, auxFunction)
5235 end contextCrefIsPre;
5236
5237 2012 template contextIteratorName(Ident name, Context context)
5238 "Generates code for an iterator variable."
5239 ::=
5240 match context
5241 case FUNCTION_CONTEXT(__) then "_" + System.unquoteIdentifier(name)
5242 else System.unquoteIdentifier(name)
5243 end contextIteratorName;
5244
5245 /* public */ template cref(ComponentRef cr, Text &sub)
5246 "Generates C equivalent name for component reference.
5247 used in Compiler/Template/CodegenFMU.tpl"
5248 ::=
5249 match cr
5250 case CREF_IDENT(ident = "xloc") then CodegenUtil.crefStr(cr)
5251 case CREF_IDENT(ident = "time") then "data->localData[0]->timeValue"
5252 case CREF_IDENT(ident = "__OMC_DT") then "data->simulationInfo->inlineData->dt"
5253 case CREF_IDENT(ident = "__HOM_LAMBDA") then "data->simulationInfo->lambda"
5254 case WILD(__) then ''
5255 else crefToCStr(cr, 0, false, false, &sub)
5256 end cref;
5257
5258 /* public */ template crefOld(ComponentRef cr, Integer ix)
5259 "Generates C equivalent name for component reference.
5260 used in Compiler/Template/CodegenFMU.tpl"
5261 ::=
5262 let &sub = buffer ""
5263 crefOldSub(cr, ix, &sub)
5264 end crefOld;
5265
5266 35945 template crefOldSub(ComponentRef cr, Integer ix, Text &sub)
5267 "crefOld for a cref whose subscripts the caller already peeled off into &sub."
5268 ::=
5269 match cr
5270 case CREF_IDENT(ident = "xloc") then CodegenUtil.crefStr(cr)
5271 case CREF_IDENT(ident = "time") then 'data->localData[<%ix%>]->timeValue'
5272 case CREF_IDENT(ident = "__OMC_DT") then "data->simulationInfo->inlineData->dt"
5273 case CREF_IDENT(ident = "__HOM_LAMBDA") then "data->simulationInfo->lambda"
5274 case WILD(__) then ''
5275 else crefToCStr(cr, ix, false, false, &sub)
5276 end crefOldSub;
5277
5278 /* public */ template crefPre(ComponentRef cr)
5279 "Generates C equivalent name for component reference.
5280 used in Compiler/Template/CodegenFMU.tpl"
5281 ::=
5282 let &sub = buffer ""
5283 match cr
5284 case CREF_IDENT(ident = "time") then "data->localData[0]->timeValueOld" // ??? Should
5285 else crefToCStr(cr, 0, true, false, &sub)
5286 end crefPre;
5287
5288 /* public */ template crefDefine(ComponentRef cr)
5289 "Generates C equivalent name for component reference.
5290 used in Compiler/Template/CodegenFMU.tpl"
5291 ::=
5292 match cr
5293 case CREF_IDENT(ident = "xloc") then CodegenUtil.crefStr(cr)
5294 case CREF_IDENT(ident = "time") then "data->localData[0]->timeValue"
5295 case WILD(__) then ''
5296 else System.unquoteIdentifier(crefStrNoUnderscore(cr))
5297 end crefDefine;
5298
5299 15206 template crefNonSimVar(ComponentRef cr)
5300 "Generates code for a cref that is used in simulation context
5301 but is not part of SIMVARs.
5302 This happens for example if the cerf is a temporary we created
5303 during codegen. E.g. when expanding record assignments in simulation
5304 context we create a tmp record cref and then expand it.
5305
5306 We use functionContextCrefFirstIdentNoUnderscore to generate these."
5307 ::=
5308 // TODO: The correct context should reach here. Since the subscripts can be valid
5309 // simvars. Make sure to pass context around in these cref generation functions.
5310 let &preExp = buffer ""
5311 let &varDecls = buffer ""
5312 let &varFrees = buffer ""
5313 let &auxFunction = buffer ""
5314 functionContextCrefFirstIdentNoUnderscore(cr, contextFunction, "", &preExp, &varDecls, &varFrees, &auxFunction)
5315 end crefNonSimVar;
5316
5317 934889 template crefToCStr(ComponentRef cr, Integer ix, Boolean isPre, Boolean isStart, Text &sub)
5318 "Helper function to cref."
5319 ::=
5320 match cr
5321 case CREF_IDENT(ident = "time") then "data->localData[0]->timeValue"
5322 case CREF_IDENT(ident = "$DAE_CJ") then "jacobian->dae_cj"
5323 case CREF_QUAL(ident = "$PRE", subscriptLst = {}) then
5324 (if isPre then error(sourceInfo(), 'Got $PRE for something that is already pre: <%crefStrNoUnderscore(cr)%>')
5325 else crefToCStr(componentRef, ix, true, isStart, &sub))
5326 case CREF_QUAL(ident = "$START") then
5327 crefToCStr(componentRef, ix, isPre, true, &sub)
5328 else if boolAnd(boolAnd(Flags.getConfigBool(Flags.NEW_BACKEND), boolNot(Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE))),
5329 boolAnd(boolAnd(crefIsScalarWithAllConstSubs(cr), stringEq(&sub, "")),
5330 boolAnd(boolNot(listEmpty(crefSubs(crefArrayGetFirstCref(cr)))),
5331 intEq(listLength(crefDims(cr)), listLength(crefSubs(crefArrayGetFirstCref(cr))))))) then
5332 // without scalarization cref2simvar resolves an element to its array, add the offset
5333 let &preExp = buffer ""
5334 let &varDecls = buffer ""
5335 let &varFrees = buffer ""
5336 let &auxFunction = buffer ""
5337 let &elemSub = buffer '<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), contextOther, &preExp, &varDecls, &varFrees, &auxFunction)%>'
5338 crefToCStr(crefStripSubs(cr), ix, isPre, isStart, &elemSub)
5339 else match cref2simvar(cr, getSimCode())
5340 case SIMVAR(varKind = ALG_STATE_OLD(), index = index) then '(data->simulationInfo->inlineData->algOldVars[<%index%>])<%&sub%>'
5341 case SIMVAR(aliasvar = ALIAS(varName = varName)) then crefToCStr(varName, ix, isPre, isStart, &sub)
5342 case SIMVAR(aliasvar = NEGATEDALIAS(varName = varName), type_=T_BOOL()) then '!(<%crefToCStr(varName, ix, isPre, isStart, &sub)%>)'
5343 case SIMVAR(aliasvar = NEGATEDALIAS(varName = varName)) then '-(<%crefToCStr(varName, ix, isPre, isStart, &sub)%>)'
5344 case v as SIMVAR(varKind = JAC_VAR()) then '(parentJacobian->resultVars[<%index%>])<%&sub%><%crefCCommentWithVariability(v)%>'
5345 case v as SIMVAR(varKind = JAC_TMP_VAR()) then '(parentJacobian->tmpVars[<%index%>])<%&sub%><%crefCCommentWithVariability(v)%>'
5346 case v as SIMVAR(varKind = SEED_VAR()) then '(parentJacobian->seedVars[<%index%>])<%&sub%><%crefCCommentWithVariability(v)%>'
5347 case v as SIMVAR(varKind = DAE_RESIDUAL_VAR()) then '(data->simulationInfo->daeModeData->residualVars[<%index%>])<%&sub%><%crefCCommentWithVariability(v)%>'
5348 case v as SIMVAR(varKind = DAE_AUX_VAR()) then '(data->simulationInfo->daeModeData->auxiliaryVars[<%index%>])<%&sub%><%crefCCommentWithVariability(v)%>'
5349 case SIMVAR(index = -2) then
5350 (let s = (if isPre then crefNonSimVar(crefPrefixPre(cr)) else crefNonSimVar(cr))
5351 if intEq(ix,0) then s
5352 else '_<%s%>(<%ix%>)')
5353 case SIMVAR(index = -1) then error(sourceInfo(), 'crefToCStr got index=-1 for <%variabilityString(varKind)%> <%crefStrNoUnderscore(name)%>')
5354 case v as SIMVAR(__) then varArrayNameValues(v, ix, isPre, isStart, &sub)
5355 else "CREF_NOT_IDENT_OR_QUAL"
5356 end crefToCStr;
5357
5358 13073 template crefToIndex(ComponentRef cr)
5359 "Helper function to cref."
5360 ::=
5361 match cref2simvar(cr, getSimCode())
5362 case SIMVAR(index=index)
5363 then
5364 '<%index%>'
5365 else "CREF_NOT_FOUND"
5366 end crefToIndex;
5367
5368 ✗ template contextArrayCref(ComponentRef cr, Context context)
5369 "Generates code for an array component reference depending on the context."
5370 ::=
5371 let &sub = buffer ""
5372 match context
5373 case FUNCTION_CONTEXT(__) then "_" + arrayCrefStr(cr)
5374 else crefToCStr(cr, 0, false, false, &sub)
5375 end contextArrayCref;
5376
5377 ✗ template arrayCrefStr(ComponentRef cr)
5378 ::=
5379 match cr
5380 case CREF_IDENT(__) then System.unquoteIdentifier(ident)
5381 case CREF_QUAL(__) then '<%System.unquoteIdentifier(ident)%>._<%arrayCrefStr(componentRef)%>'
5382 else "CREF_NOT_IDENT_OR_QUAL"
5383 end arrayCrefStr;
5384
5385 354 template crefFunctionName(ComponentRef cr)
5386 ::=
5387 match cr
5388 case CREF_IDENT(__) then
5389 System.stringReplace(unquoteIdentifier(ident), "_", "__")
5390 case CREF_QUAL(__) then
5391 '<%System.stringReplace(unquoteIdentifier(ident), "_", "__")%>_<%crefFunctionName(componentRef)%>'
5392 end crefFunctionName;
5393
5394 235427 template addRootsTempArray()
5395 ::=
5396 match System.tmpTickMaximum(1)
5397 case 0 then ""
5398 case i then /* TODO: Find out where we add tmpIndex but discard its use causing us to generate unused tmpMeta with size 1 */
5399 <<
5400 modelica_metatype tmpMeta[<%i%>] __attribute__((unused)) = {0};
5401 >>
5402 end addRootsTempArray;
5403
5404 272480 template modelicaLine(builtin.SourceInfo info)
5405 ::=
5406 match info
5407 case SOURCEINFO(fileName="") then ""
5408 else if Flags.isSet(Flags.GEN_DEBUG_SYMBOLS)
5409 then (if Flags.isSet(OMC_RECORD_ALLOC_WORDS)
5410 then '/*#modelicaLine <%infoStr(info)%>*/<%\n%><% match info case SOURCEINFO() then (if intEq(-1, stringFind(fileName,".interface.mo")) then 'mmc_set_current_pos("<%infoStr(info)%>");<%\n%>') %>'
5411 else '/*#modelicaLine <%infoStr(info)%>*/<%\n%>'
5412 )
5413 end modelicaLine;
5414
5415 315631 template endModelicaLine()
5416 ::=
5417 if Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then '/*#endModelicaLine*/<%\n%>'
5418 end endModelicaLine;
5419
5420 428466 template tempDecl(String ty, Text &varDecls, Text &varFrees)
5421 "Declares a temporary variable in varDecls and returns the name."
5422 ::=
5423 let newVar =
5424 match ty /* TODO! FIXME! UGLY! UGLY! hack! */
5425 case "modelica_metatype"
5426 case "metamodelica_string"
5427 case "metamodelica_string_const" then
5428 let newVarIx = 'tmpMeta<%System.tmpTick()%>'
5429 let &varDecls += 'modelica_metatype <%newVarIx%>;<%\n%>'
5430 newVarIx
5431 else
5432 let newVarIx = 'tmp<%System.tmpTick()%>'
5433 let &varDecls += '<%ty%> <%newVarIx%><%rcZeroInit(ty)%>;<%\n%>'
5434 let &varFrees += rcRelease(ty, newVarIx)
5435 newVarIx
5436 newVar
5437 end tempDecl;
5438
5439 1754349 template metaModelicaRuntime()
5440 "Whether the C is compiled against the MetaModelica runtime. Not the grammar: a
5441 simulation links the counted runtime even when the model is MetaModelica."
5442 ::= if isSimulationCodegen() then "" else (if Config.acceptMetaModelicaGrammar() then "x")
5443 end metaModelicaRuntime;
5444
5445 215401 template errorCheck(Context context)
5446 "MetaModelica throws instead. A parallel body (an OpenCL kernel) has no
5447 _return: to jump to."
5448 ::=
5449 match context
5450 case FUNCTION_CONTEXT(is_parallel = true) then ""
5451 else if metaModelicaRuntime() then "" else 'OMC_ERROR_CHECK();<%\n%>'
5452 end errorCheck;
5453
5454 24 template raiseOrThrow()
5455 "MetaModelica unwinds by jumping; everything else raises for the caller to check."
5456 ::= if metaModelicaRuntime() then "throwStreamPrint" else "raiseStreamPrint"
5457 end raiseOrThrow;
5458
5459 46218 template litDefString()
5460 ::= if metaModelicaRuntime() then "MMC_DEFSTRINGLIT" else "OMC_DEFSTRINGLIT"
5461 end litDefString;
5462
5463 46218 template litRefString()
5464 ::= if metaModelicaRuntime() then "MMC_REFSTRINGLIT" else "OMC_REFSTRINGLIT"
5465 end litRefString;
5466
5467 17618 template litDefBox()
5468 ::= if metaModelicaRuntime() then "MMC_DEFSTRUCTLIT" else "OMC_DEFBOXLIT"
5469 end litDefBox;
5470
5471 19036 template litRefBox()
5472 ::= if metaModelicaRuntime() then "MMC_REFSTRUCTLIT" else "OMC_REFBOXLIT"
5473 end litRefBox;
5474
5475 66 template litDefReal()
5476 ::= if metaModelicaRuntime() then "MMC_DEFREALLIT" else "OMC_DEFREALLIT"
5477 end litDefReal;
5478
5479 66 template litRefReal()
5480 ::= if metaModelicaRuntime() then "MMC_REFREALLIT" else "OMC_REFREALLIT"
5481 end litRefReal;
5482
5483 1204 template litArrayTag(Integer nslots)
5484 "The constructor word of an array box. A MetaModelica header records the slot
5485 count, a counted box does not, so there it goes above the tag."
5486 ::= if metaModelicaRuntime() then "MMC_ARRAY_TAG" else 'OMC_BOX_ARRAY_TAG(<%nslots%>)'
5487 end litArrayTag;
5488
5489 954179 template rcKindCounted(String ty)
5490 "How a temporary of this C type is released, or \"\" for one that owns nothing.
5491 An array is always safe: base_array_s.owns_data answers at run time whether the
5492 buffer is its own. modelica_metatype is not: the slot may hold an immediate or
5493 a borrowed reference."
5494 ::=
5495 match ty
5496 case "modelica_string" then "string"
5497 case "string_array" then "stringArray"
5498 case "real_array"
5499 case "integer_array"
5500 case "boolean_array"
5501 case "base_array_t" then "array"
5502 case "index_spec_t" then "indexSpec"
5503 // A record array is a base_array_t too, but its elements own what their
5504 // members own. No suffix test in the template language, so this is one.
5505 // ParModelica's device arrays are OpenCL buffers, not counted.
5506 else if intEq(0, System.stringFind(ty, "device_")) then ""
5507 else if stringEq(ty, System.stringReplace(ty, "_array", "") + "_array")
5508 then (if SimCodeFunctionUtil.isTrivialRecord(System.stringReplace(ty, "_array", "")) then "array" else "recordArray")
5509 else if SimCodeFunctionUtil.isTrivialRecord(ty) then ""
5510 else if isRecordCType(ty) then "record" else ""
5511 end rcKindCounted;
5512
5513 878173 template isRecordCType(String ty)
5514 "A record's C type is the underscorePath of its Modelica path. Everything else
5515 the generator declares is modelica_*, a ParModelica array or a C
5516 spelling with a space, a star or angle brackets. recordCreateFromVarsDef asks
5517 the same question before it writes a counted member."
5518 ::=
5519 if boolNot(stringEq(ty, System.stringReplace(ty, "modelica_", ""))) then ""
5520 else if boolNot(stringEq(ty, System.stringReplace(ty, "device_", ""))) then ""
5521 else if boolNot(stringEq(ty, System.stringReplace(ty, "local_", ""))) then ""
5522 else if boolNot(stringEq(ty, System.stringReplace(ty, " ", ""))) then ""
5523 else if boolNot(stringEq(ty, System.stringReplace(ty, "*", ""))) then ""
5524 else if boolNot(stringEq(ty, System.stringReplace(ty, "<", ""))) then ""
5525 else if boolNot(stringEq(ty, System.stringReplace(ty, ":", ""))) then ""
5526 else match ty
5527 case "int"
5528 case "bool"
5529 case "double"
5530 case "string"
5531 case "state"
5532 case "cl_kernel"
5533 case "index_spec_t" then ""
5534 else "x"
5535 end isRecordCType;
5536
5537 1344524 template rcKind(String ty)
5538 "Nothing is counted under MetaModelica: the collector owns every slot, so the
5539 whole retain/release vocabulary below collapses to plain assignment."
5540 ::= if metaModelicaRuntime() then "" else rcKindCounted(ty)
5541 end rcKind;
5542
5543 551522 template rcRelease(String ty, Text name)
5544 "Emitted into varFrees at the declaration and replayed at _return:."
5545 ::=
5546 match rcKind(ty)
5547 case "string" then 'omc_string_move(&<%name%>, NULL);<%\n%>'
5548 case "stringArray" then 'omc_string_array_release(&<%name%>);<%\n%>'
5549 case "array" then 'omc_array_release(&<%name%>);<%\n%>'
5550 case "indexSpec" then 'omc_index_spec_release(&<%name%>);<%\n%>'
5551 case "record"
5552 case "recordArray" then '<%ty%>_release(<%name%>);<%\n%>'
5553 else ""
5554 end rcRelease;
5555
5556 51565 template rcRetain(String ty, Text name)
5557 "One more owner of what the slot holds."
5558 ::=
5559 match rcKind(ty)
5560 case "string" then 'omc_string_retain(<%name%>);<%\n%>'
5561 case "stringArray"
5562 case "array"
5563 case "recordArray" then 'omc_array_retain(&<%name%>);<%\n%>'
5564 case "record" then '<%ty%>_retain(<%name%>);<%\n%>'
5565 else ""
5566 end rcRetain;
5567
5568 40720 template rcDisown(String ty, Text name)
5569 "Hands what the slot holds to whoever took it, so the release finds nothing."
5570 ::=
5571 match rcKind(ty)
5572 case "string" then 'omc_string_disown(<%name%>);<%\n%>'
5573 case "stringArray"
5574 case "array"
5575 case "recordArray" then 'omc_array_disown(&<%name%>);<%\n%>'
5576 case "record" then '<%ty%>_disown(<%name%>);<%\n%>'
5577 else ""
5578 end rcDisown;
5579
5580 14 template rcArrayRetain(String ty, Text name)
5581 ::=
5582 match rcKind(ty)
5583 case "stringArray"
5584 case "array"
5585 case "recordArray" then '<%\n%>omc_array_retain(&<%name%>);'
5586 else ""
5587 end rcArrayRetain;
5588
5589 7881 template rcRetainOut(Variable var)
5590 "The caller takes the output, so clear the local before the frees run."
5591 ::=
5592 match var
5593 case v as VARIABLE(__) then rcDisown(varType(v), funArgName(v))
5594 else ""
5595 end rcRetainOut;
5596
5597 67056 template deviceCallResult()
5598 "ParModelica's parallel functions return a device array, which no temporary
5599 declared from the Modelica type can hold, so a call result is left in place."
5600 ::= if Config.acceptParModelicaGrammar() then "x" else ""
5601 end deviceCallResult;
5602
5603 51175 template rcCallResultType(Type ty)
5604 "The C type of a call result that carries a reference, else \"\"."
5605 ::=
5606 match ty
5607 case T_TUPLE(types=t::_) then rcCallResultType(t)
5608 case T_STRING(__) then if rcKind("modelica_string") then "modelica_string"
5609 case T_COMPLEX(complexClassType=RECORD(__)) then
5610 let recTy = expTypeModelica(ty)
5611 if rcKind(recTy) then recTy else ""
5612 else
5613 if isArrayType(ty) then
5614 let arrTy = expTypeArray(ty)
5615 if rcKind(arrTy) then arrTy else ""
5616 else ""
5617 end rcCallResultType;
5618
5619 181269 template rcAssignRetain(String ty, Text lhs, Text rhs)
5620 "lhs takes a reference to rhs, which the frame that produced it still owns. A
5621 record shares its members here; <R>_copy is the value copy."
5622 ::=
5623 match rcKind(ty)
5624 case "string" then 'omc_string_store(&<%lhs%>, <%rhs%>);<%\n%>'
5625 case "stringArray"
5626 case "array"
5627 case "recordArray"
5628 case "record" then '<%rcRelease(ty, lhs)%><%lhs%> = <%rhs%>;<%\n%><%rcRetain(ty, lhs)%>'
5629 else '<%lhs%> = <%rhs%>;<%\n%>'
5630 end rcAssignRetain;
5631
5632 76055 template rcReleaseBefore(String ty, Text name)
5633 "A temporary in a loop is re-evaluated each pass but declared once, so what it
5634 held has to go before it is built over. Only valid on a zeroed tempDecl."
5635 ::=
5636 rcRelease(ty, name)
5637 end rcReleaseBefore;
5638
5639 427 template rcSpillArray(String ty, Text call, Text &preExp, Text &varDecls, Text &varFrees)
5640 "An array built as an rvalue would have no owner to release it."
5641 ::=
5642 let tvar = tempDecl(ty, &varDecls, &varFrees)
5643 let &preExp += '<%rcReleaseBefore(ty, tvar)%><%tvar%> = <%call%>;<%\n%>'
5644 tvar
5645 end rcSpillArray;
5646
5647 377027 template rcZeroInit(String ty)
5648 "Released on every exit path, including one taken before it is assigned."
5649 ::=
5650 match rcKind(ty)
5651 case "" then ""
5652 case "string" then " = NULL"
5653 // a record without members is an aggregate with no elements, where {0} is an error
5654 case "record" then " = {}"
5655 else " = {0}"
5656 end rcZeroInit;
5657
5658 32481 template rcZeroAssign(String ty, Text name)
5659 "rcZeroInit as a statement, for a slot that is declared elsewhere."
5660 ::=
5661 match rcKind(ty)
5662 case "string" then '<%name%> = NULL;<%\n%>'
5663 else ""
5664 end rcZeroAssign;
5665
5666 ✗ template tempDeclArray(String ty, Text len, Text elts, Text &varDecls, Text &varFrees)
5667 "Declares a temporary variable in varDecls and returns the name."
5668 ::=
5669 let newVarIx = 'tmp<%System.tmpTick()%>'
5670 let &varDecls += '<%ty%> <%newVarIx%>[<%len%>] = {<%elts%>};<%\n%>'
5671 newVarIx
5672 end tempDeclArray;
5673
5674 34930 template tempDeclZero(String ty, Text &varDecls, Text &varFrees)
5675 "Declares a temporary variable initialized to zero in varDecls and returns the name."
5676 ::=
5677 let newVar
5678 =
5679 match ty /* TODO! FIXME! UGLY! UGLY! hack! */
5680 case "modelica_metatype"
5681 case "metamodelica_string"
5682 case "metamodelica_string_const" then
5683 let newVarIx = 'tmpMeta<%System.tmpTick()%>'
5684 let &varDecls += 'modelica_metatype <%newVarIx%>;<%\n%>'
5685 newVarIx
5686 else
5687 let newVarIx = 'tmp<%System.tmpTick()%>'
5688 let &varDecls += '<%ty%> <%newVarIx%> = 0;<%\n%>'
5689 newVarIx
5690 newVar
5691
5692 end tempDeclZero;
5693
5694 2032 template tempDeclMatchInput(MatchType matchTy, String ty, String startIndex, String index, Text &varDecls, Text &varFrees)
5695 "Declares a temporary variable in varDecls for variables in match input list and returns the name."
5696 ::=
5697 // Note: We use volatile variables in matchcontinue to avoid problems with optimizing compilers
5698 let ix = 'tmp<%startIndex%>_<%index%>'
5699 let &varDecls += '<% match matchTy case MATCHCONTINUE(__) then 'volatile '%><%ty%> <%ix%>;'
5700 ix
5701 end tempDeclMatchInput;
5702
5703 9732 template getTempDeclMatchInputName(String startIndex, Integer index)
5704 "Returns the name of the temporary variable from the match input list."
5705 ::=
5706 'tmp<%startIndex%>_<%index%>'
5707 end getTempDeclMatchInputName;
5708
5709 213 template tempDeclMatchOutput(String ty, String prefix, String startIndex, String index, Text &varDecls, Text &varFrees)
5710 "Declares a temporary variable in varDecls for variables in match output list and returns the name."
5711 ::=
5712 let newVar
5713 =
5714 match ty /* TODO! FIXME! UGLY! UGLY! hack! */
5715 case "modelica_metatype"
5716 case "metamodelica_string"
5717 case "metamodelica_string_const"
5718 then 'tmpMeta[<%startIndex%>+<%index%>]'
5719 else
5720 let newVarIx = '<%prefix%>_c<%index%>'
5721 let &varDecls += '<%ty%> <%newVarIx%> __attribute__((unused)) = 0;<%\n%>'
5722 newVarIx
5723 newVar
5724 end tempDeclMatchOutput;
5725
5726 1290 template getTempDeclMatchOutputName(list<Exp> outputs, String prefix, String startIndex, Integer index)
5727 "Returns the name of the temporary variable from the match input list."
5728 ::=
5729 let typ = '<%expTypeFromExpModelica(listGet(outputs, index))%>'
5730 let newVar =
5731 match typ /* TODO! FIXME! UGLY! UGLY! hack! */
5732 case "modelica_metatype"
5733 case "metamodelica_string"
5734 case "metamodelica_string_const"
5735 then 'tmpMeta[<%startIndex%>+<%intSub(index, 1)%>]'
5736 else
5737 let newVarIx = '<%prefix%>_c<%intSub(index, 1)%>'
5738 newVarIx
5739 newVar
5740 end getTempDeclMatchOutputName;
5741
5742 /* public */ template daeExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5743 "Generates code for an expression.
5744 used in Compiler/Template/CodegenQSS.tpl"
5745 ::=
5746 match codegenExpSanityCheck(exp, context)
5747 case e as ICONST(__)
5748 case e as RCONST(__)
5749 case e as BCONST(__)
5750 case e as ENUM_LITERAL(__) then daeExpSimpleLiteral(exp)
5751 case e as SCONST(__) then daeExpSconst(string, &preExp, &varDecls, &varFrees)
5752 case e as CREF(__) then daeExpCrefRhs(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5753 case e as BINARY(__) then daeExpBinary(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5754 case e as UNARY(__) then daeExpUnary(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5755 case e as LBINARY(__) then daeExpLbinary(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5756 case e as LUNARY(__) then daeExpLunary(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5757 case e as RELATION(__) then daeExpRelation(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5758 case e as IFEXP(__) then daeExpIf(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5759 case e as CALL(__) then daeExpCall(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5760 case e as RECORD(__) then daeExpRecord(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5761 case e as PARTEVALFUNCTION(__)then daeExpPartEvalFunction(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5762 case e as ARRAY(__) then daeExpArray(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5763 case e as MATRIX(__) then daeExpMatrix(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5764 case e as RANGE(__) then daeExpRange(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5765 case e as CAST(__) then daeExpCast(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5766 case e as ASUB(__) then daeExpAsub(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5767 case e as TSUB(__) then daeExpTsub(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5768 case e as RSUB(__) then daeExpRsub(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5769 case e as SIZE(__) then daeExpSize(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5770 case e as REDUCTION(__) then daeExpReduction(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5771 case e as TUPLE(__) then daeExpTuple(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5772 case e as LIST(__) then daeExpList(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5773 case e as CONS(__) then daeExpCons(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5774 case e as META_TUPLE(__) then daeExpMetaTuple(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5775 case e as META_OPTION(__) then daeExpMetaOption(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5776 case e as METARECORDCALL(__) then daeExpMetarecordcall(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5777 case e as MATCHEXPRESSION(__) then daeExpMatch(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5778 case e as BOX(__) then daeExpBox(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5779 case e as UNBOX(__) then daeExpUnbox(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5780 case e as SHARED_LITERAL(__) then daeExpSharedLiteral(e)
5781 case e as CLKCONST(__) then '#error "<%ExpressionDumpTpl.dumpExp(e,"\"")%>"'
5782 else error(sourceInfo(), 'Unknown expression: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
5783 end daeExp;
5784
5785 /* public */ template daeExpSimpleLiteral(Exp exp)
5786 "Generates code for a simple literal expression."
5787 ::=
5788 match exp
5789 case e as ICONST(__) then
5790 '((modelica_integer) <%integer%>)' /* Yes, we need to cast int to long on 64-bit arch... */
5791 case e as RCONST(__) then real
5792 case e as BCONST(__) then boolStrC(bool)
5793 case e as SCONST(__) then '"<%Util.escapeModelicaStringToCString(string)%>"'
5794 case e as ENUM_LITERAL(__) then index
5795 else error(sourceInfo(), 'Not a simple literal expression: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
5796 end daeExpSimpleLiteral;
5797
5798 /* public */ template daeExpAsLValue(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5799 "Generates code for an expression. Makes sure that the output is an lvalue (so you can take the address of it)."
5800 ::=
5801 let res1 = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
5802 if isCIdentifier(res1)
5803 then res1
5804 else
5805 let tmp = tempDecl(expTypeFromExpArrayIf(exp),&varDecls, &varFrees)
5806 let &preExp += rcAssignRetain(expTypeFromExpArrayIf(exp), tmp, res1)
5807 tmp
5808 end daeExpAsLValue;
5809
5810
5811 52 template daeExternalCExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5812 "Like daeExp, but also converts the type to external C"
5813 ::=
5814 match typeof(exp)
5815 case T_ARRAY(__) then // Array-expressions
5816 let shortTypeStr = expTypeShort(typeof(exp))
5817 '(<%extType(typeof(exp),true,true,false)%>) data_of_<%shortTypeStr%>_array(<%daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)'
5818 case T_STRING(__) then
5819 let mstr = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
5820 'omc_string_data(<%mstr%>)'
5821 else daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
5822 end daeExternalCExp;
5823
5824 ✗ template daeExternalF77Exp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5825 "Like daeExp, but also converts the type to external Fortran"
5826 ::=
5827 match typeof(exp)
5828 case T_ARRAY(__) then // Array-expressions
5829 let shortTypeStr = expTypeShort(typeof(exp))
5830 '(<%extType(typeof(exp),true,true,false)%>) data_of_<%shortTypeStr%>_array(<%daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)'
5831 case T_STRING(__) then
5832 let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
5833 let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls, &varFrees)
5834 let &preExp += '<%tvar%> = omc_string_data(<%texp%>);<%\n%>'
5835 '&<%tvar%>'
5836 else
5837 let texp = daeExp(exp, contextFunction, &preExp, &varDecls, &varFrees, &auxFunction)
5838 let tvar = tempDecl(expTypeFromExpFlag(exp,8),&varDecls, &varFrees)
5839 let &preExp += '<%tvar%> = <%texp%>;<%\n%>'
5840 '&<%tvar%>'
5841 end daeExternalF77Exp;
5842
5843 30386 template daeExpSconst(String string, Text &preExp, Text &varDecls, Text &varFrees)
5844 "Generates code for a string constant."
5845 ::=
5846 let escstr = Util.escapeModelicaStringToCString(string)
5847 match stringLength(string)
5848 case 0 then "(modelica_string) omc_string_empty"
5849 case 1 then '(modelica_string) omc_strings_len1[<%stringGet(string, 1)%>]'
5850 else
5851 let tmp = 'tmp<%System.tmpTick()%>'
5852 let &varDecls += 'static const <%litDefString()%>(<%tmp%>,<%unescapedStringLength(escstr)%>,"<%escstr%>");<%\n%>'
5853 '<%litRefString()%>(<%tmp%>)'
5854 end daeExpSconst;
5855
5856 619 template daeExpList(Exp exp, Context context, Text &preExp,
5857 Text &varDecls, Text &varFrees, Text &auxFunction)
5858 "Generates code for a meta modelica list expression."
5859 ::=
5860 match exp
5861 case LIST(__) then
5862 let tmp = tempDecl("modelica_metatype", &varDecls, &varFrees)
5863 let expPart = daeExpListToCons(valList, context, &preExp, &varDecls, &varFrees, &auxFunction)
5864 let &preExp += '<%tmp%> = <%expPart%>;<%\n%>'
5865 tmp
5866 end daeExpList;
5867
5868
5869 619 template daeExpListToCons(list<Exp> listItems, Context context, Text &preExp,
5870 Text &varDecls, Text &varFrees, Text &auxFunction)
5871 "Helper to daeExpList."
5872 ::=
5873 match listItems
5874 case e :: rest then
5875 let expPart = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5876 let restList = daeExpListToCons(rest, context, &preExp, &varDecls, &varFrees, &auxFunction)
5877 <<
5878 mmc_mk_cons(<%expPart%>, <%restList%>)
5879 >>
5880 else '<%litRefBox()%>(mmc_nil)'
5881 end daeExpListToCons;
5882
5883
5884 276 template daeExpCons(Exp exp, Context context, Text &preExp,
5885 Text &varDecls, Text &varFrees, Text &auxFunction)
5886 "Generates code for a meta modelica cons expression."
5887 ::=
5888 match exp
5889 case CONS(__) then
5890 let tmp = tempDecl("modelica_metatype", &varDecls, &varFrees)
5891 let carExp = daeExp(car, context, &preExp, &varDecls, &varFrees, &auxFunction)
5892
5893 let cdrExp = daeExp(cdr, context, &preExp, &varDecls, &varFrees, &auxFunction)
5894 let &preExp += '<%tmp%> = mmc_mk_cons(<%carExp%>, <%cdrExp%>);<%\n%>'
5895 tmp
5896 end daeExpCons;
5897
5898 6260 template tempDeclTuple(DAE.Type inType, Text &varDecls, Text &varFrees)
5899 ::=
5900 match inType
5901 case T_TUPLE(__) then
5902 let tmpVar = 'tmp<%System.tmpTick()%>'
5903 let &varDecls +=
5904 <<
5905 struct {
5906 <%types |> ty hasindex i1 fromindex 1 => '<%expTypeModelica(ty)%> c<%i1%>;<%\n%>'%>
5907 } <%tmpVar%>;
5908 >>
5909 tmpVar
5910 else tempDecl(expTypeArrayIf(inType),&varDecls, &varFrees)
5911 end tempDeclTuple;
5912
5913 ✗ template daeExpTuple(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5914 "Generates code for a meta modelica tuple expression."
5915 ::=
5916 match exp
5917 case TUPLE(__) then
5918 let tmpVar = tempDeclTuple(typeof(exp),&varDecls, &varFrees)
5919 let tmp = (PR |> e hasindex i1 fromindex 1 => '<%tmpVar%>.c<%i1%> = <%daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)%>;<%\n%>')
5920 let &preExp += tmp
5921 tmpVar
5922 end daeExpTuple;
5923
5924 99 template daeExpMetaTuple(Exp exp, Context context, Text &preExp,
5925 Text &varDecls, Text &varFrees, Text &auxFunction)
5926 "Generates code for a meta modelica tuple expression."
5927 ::=
5928 match exp
5929 case META_TUPLE(__) then
5930 let start = daeExpMetaHelperBoxStart(listLength(listExp))
5931 let args = (listExp |> e => daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5932 ;separator=", ")
5933 let tmp = tempDecl("modelica_metatype", &varDecls, &varFrees)
5934 let &preExp += '<%tmp%> = omc_mk_box<%start%>0<%if args then ", "%><%args%>);<%\n%>'
5935 tmp
5936 end daeExpMetaTuple;
5937
5938
5939 53 template daeExpMetaOption(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5940 "Generates code for a meta modelica option expression."
5941 ::=
5942 match exp
5943 case META_OPTION(exp=NONE()) then
5944 "mmc_mk_none()"
5945 case META_OPTION(exp=SOME(e)) then
5946 let expPart = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
5947 'mmc_mk_some(<%expPart%>)'
5948 end daeExpMetaOption;
5949
5950
5951 1491 template daeExpMetarecordcall(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
5952 "Generates code for a meta modelica record call expression."
5953 ::=
5954 match exp
5955 case METARECORDCALL(__) then
5956 let newIndex = getValueCtor(index)
5957 let argsStr = if args then
5958 ', <%args |> exp =>
5959 daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
5960 ;separator=", "%>'
5961 else
5962 ""
5963 let box = 'omc_mk_box<%daeExpMetaHelperBoxStart(incrementInt(listLength(args), 1))%><%newIndex%>, &<%underscorePath(path)%>__desc<%argsStr%>)'
5964 let tmp = tempDecl("modelica_metatype", &varDecls, &varFrees)
5965 let &preExp += '<%tmp%> = <%box%>;<%\n%>'
5966 tmp
5967 end daeExpMetarecordcall;
5968
5969 6928 template daeExpMetaHelperBoxStart(Integer numVariables)
5970 "Helper to determine how omc_mk_box should be called."
5971 ::=
5972 if intGt(numVariables,20) then '(<%numVariables%>, ' else '<%numVariables%>('
5973 end daeExpMetaHelperBoxStart;
5974
5975 3021 template crefToMStr(ComponentRef cr)
5976 "Helper function to crefM."
5977 ::=
5978 match cr
5979 case CREF_IDENT(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>'
5980 case CREF_QUAL(__) then '<%unquoteIdentifier(ident)%><%subscriptsToMStr(subscriptLst)%>P<%crefToMStr(componentRef)%>'
5981 else "CREF_NOT_IDENT_OR_QUAL"
5982 end crefToMStr;
5983
5984 ✗ template subscriptsToMStr(list<DAE.Subscript> subscripts)
5985 ::=
5986 if subscripts then
5987 'lB<%subscripts |> s => subscriptToMStr(s) ;separator="c"%>rB'
5988 end subscriptsToMStr;
5989
5990 ✗ template subscriptToMStr(DAE.Subscript subscript)
5991 ::=
5992 match subscript
5993 case SLICE(exp=ICONST(integer=i)) then i
5994 case SLICE(__) then error(sourceInfo(), "Unknown slice " + ExpressionDumpTpl.dumpExp(exp,"\""))
5995 case WHOLEDIM(__) then "WHOLEDIM"
5996 case WHOLE_NONEXP(__) then "WHOLE_NONEXP"
5997 case INDEX(__) then
5998 match exp
5999 case ICONST(integer=i) then i
6000 case BCONST(bool=i) then i
6001 case ENUM_LITERAL(index=i) then i
6002 else
6003 let &varDecls = buffer ""
6004 let &varFrees = buffer ""
6005 let &preExp = buffer ""
6006 let &auxFunction = buffer ""
6007 daeExp(exp, contextOther, &preExp, &varDecls, &varFrees, &auxFunction)
6008 end match
6009 else error(sourceInfo(), "UNKNOWN_SUBSCRIPT")
6010 end subscriptToMStr;
6011
6012 2238 template generateThrow()
6013 ::=
6014 match codegenPeekTryThrowIndex()
6015 case -1 then "OMC_THROW_INTERNAL()"
6016 case i then 'goto goto_<%i%>'
6017 end generateThrow;
6018
6019 955253 template daeExpCrefRhs(Exp exp, Context context, Text &preExp,
6020 Text &varDecls, Text &varFrees, Text &auxFunction)
6021 "Generates code for a component reference on the right hand side of an
6022 expression."
6023 ::=
6024 match exp
6025 case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then
6026 'boxvar_<%crefFunctionName(cr)%>'
6027 case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then
6028 '((modelica_fnptr) _<%CodegenUtil.crefStr(cr)%>)'
6029 case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METAUNIONTYPE(__)), componentRef=cri as CREF_IDENT(__)))
6030 case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METARECORD(__)), componentRef=cri as CREF_IDENT(__))) then
6031 let offset = intAdd(findVarIndex(cri.ident,getMetaRecordFields(ty)),2) // 0-based
6032 '(OMC_BOX_FIELD(_<%cr.ident%>, <%offset%>))'
6033 else
6034 match context
6035 case FUNCTION_CONTEXT(is_parallel = true) then daeExpCrefRhsFunContextParallel(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6036 case FUNCTION_CONTEXT(__) then daeExpCrefRhsFunContext(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6037 else daeExpCrefRhsSimContext(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6038 end daeExpCrefRhs;
6039
6040 2241 template constVarOrDaeExp(DAE.Var var, DAE.ComponentRef cr, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6041 ::=
6042 match var
6043 case DAE.TYPES_VAR(attributes = DAE.ATTR(variability = CONST()), binding = DAE.EQBOUND()) then
6044 daeExp(binding.exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6045 case DAE.TYPES_VAR(attributes = DAE.ATTR(variability = CONST()), binding = DAE.VALBOUND()) then
6046 error(sourceInfo(), 'constVarOrDaeExp failed; Constant variable <%name%> is value bound. Not yet implemented')
6047 case DAE.TYPES_VAR(attributes = DAE.ATTR(variability = CONST()), binding = DAE.UNBOUND()) then
6048 error(sourceInfo(), 'constVarOrDaeExp failed; Constant variable <%name%> has no binding. This indicates a problem in the lowering from Frontend to old Backend')
6049 else
6050 daeExp(makeCrefRecordExp(cr,var), context, &preExp, &varDecls, &varFrees, &auxFunction)
6051 end constVarOrDaeExp;
6052
6053 641860 template daeExpCrefRhsSimContext(Exp ecr, Context context, Text &preExp,
6054 Text &varDecls, Text &varFrees, Text &auxFunction)
6055 "Generates code for a component reference in simulation context."
6056 ::=
6057 match ecr
6058 case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then
6059 let &sub = buffer ""
6060 '<%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6061
6062 case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then
6063 let vars = var_lst |> v => (", " + constVarOrDaeExp(v, cr, context, &preExp, &varDecls, &varFrees, &auxFunction))
6064 let record_type_name = underscorePath(ClassInfUtil.getStateName(record_state))
6065 let tmpRec = tempDecl(record_type_name, &varDecls, &varFrees)
6066 let &preExp += '<%record_type_name%>_wrap_vars(threadData,<%tmpRec%><%vars%>);<%\n%>'
6067 '<%tmpRec%>'
6068
6069 case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then
6070 let type = expTypeShort(aty)
6071 let arrayType = type + "_array"
6072 let wrapperArray = tempDecl(arrayType, &varDecls, &varFrees)
6073 if crefSubIsScalar(cr) then
6074 let dimsLenStr = listLength(dims)
6075 let dimsValuesStr = (dims |> dim => '(_index_t)<%dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
6076 let t = if boolAnd(isStartCref(cr), boolNot(hasZeroDimension(dims))) then
6077 startArrayGather(cr, type, wrapperArray, dimsLenStr, dimsValuesStr, &varDecls, &varFrees)
6078 else
6079 // Workaround for https://github.com/OpenModelica/OpenModelica/issues/14470
6080 let arrayData = if hasZeroDimension(dims) then
6081 'NULL'
6082 else if Flags.getConfigBool(Flags.NEW_BACKEND) then
6083 let &sub = buffer '<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
6084 let nosubname = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6085 '((modelica_<%type%>*)&(<%nosubname%>))'
6086 else if isContiguousArrayCref(cr, context) then
6087 let &sub = buffer ""
6088 let nosubname = contextCref(crefArrayGetFirstCref(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6089 '((modelica_<%type%>*)&(<%nosubname%>))'
6090 else
6091 '((modelica_<%type%>*)<%daeExpCrefRhsArrayElems(cr, type, context, &preExp, &varDecls, &varFrees, &auxFunction)%>.data)'
6092 '<%type%>_array_create(&<%wrapperArray%>, <%arrayData%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>'
6093 let &preExp += t
6094 wrapperArray
6095 else if contiguousSlice(cr, type, context) then
6096 let data = contiguousSliceData(cr, type, context, &preExp, &varDecls, &varFrees, &auxFunction)
6097 let &preExp += '<%type%>_array_create(&<%wrapperArray%>, <%data%>, <%listLength(contiguousSliceDims(crefSubs(cr), crefDims(cr)))%>, <%contiguousSliceDims(crefSubs(cr), crefDims(cr)) |> d => '(_index_t)<%d%>' ;separator=", "%>);<%\n%>'
6098 wrapperArray
6099 else
6100 let &sub = buffer ""
6101 let dimsLenStr = listLength(crefDims(cr))
6102 let dimsValuesStr = (crefDims(cr) |> dim => '(_index_t)<%dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
6103 let arrData = if isContiguousArrayCref(crefStripSubs(cr), context) then
6104 '&<%contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6105 else
6106 '<%daeExpCrefRhsArrayElems(crefStripSubs(cr), type, context, &preExp, &varDecls, &varFrees, &auxFunction)%>.data'
6107 let &preExp += '<%type%>_array_create(&<%wrapperArray%>, (modelica_<%type%>*)<%arrData%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>'
6108 let slicedArray = tempDecl(arrayType, &varDecls, &varFrees)
6109 let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction)
6110 let &preExp += '<%rcReleaseBefore(arrayType, slicedArray)%>index_alloc_<%type%>_array(&<%wrapperArray%>, &<%spec1%>, &<%slicedArray%>);<%\n%>'
6111 slicedArray
6112
6113 case ecr as CREF(componentRef=cr, ty=ty) then
6114 if crefIsScalarWithVariableSubs(cr) then
6115 if isContiguousArrayCref(crefStripSubs(cr), context) then
6116 let &sub = buffer '<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
6117 let nosubname = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6118 '<%nosubname%>'
6119 else
6120 let type = expTypeShort(ty)
6121 let elems = daeExpCrefRhsArrayElems(crefStripSubs(cr), type, context, &preExp, &varDecls, &varFrees, &auxFunction)
6122 let flat = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(cr))), listReverse(crefSubs(crefArrayGetFirstCref(cr))), context, &preExp, &varDecls, &varFrees, &auxFunction)
6123 '<%type%>_get(<%elems%>, <%flat%>)'
6124 else if boolAnd(Flags.getConfigBool(Flags.NEW_BACKEND), boolNot(Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE))) then
6125 // Without sim code scalarization array elements like arr[2] are not
6126 // standalone simvars and have to be addressed relative to the first
6127 // element of the array using a flattened index. $START crefs address the
6128 // (array valued) start attribute and the flattened index selects the
6129 // matching start element (see varArrayNameValues).
6130 // Jacobians can have standalone variables for single elements, e.g. the seed
6131 // $SEED.n[1].T of a linear system that only solves n[1].T.
6132 if isJacobianElementVar(cr, context) then
6133 let &sub = buffer ""
6134 '<%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6135 else match crefSubs(crefArrayGetFirstCref(cr))
6136 case {} then
6137 let &sub = buffer ""
6138 '<%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6139 else
6140 let &sub = buffer '<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
6141 let nosubname = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6142 '<%nosubname%>'
6143 else if crefIsScalarWithAllConstSubs(cr) then
6144 // let cast = typeCastContextInt(context, ty)
6145 let &sub = buffer ""
6146 '<%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6147 else
6148 error(sourceInfo(),'daeExpCrefRhsSimContext: UNHANDLED CREF: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6149 end daeExpCrefRhsSimContext;
6150
6151 1 template daeExpCrefRhsArrayElems(ComponentRef cr, String type, Context context,
6152 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6153 "A fresh 1-D array of the elements of array cref cr, for elements that are not
6154 consecutive in the variable arrays (a state beside an algebraic, an alias)."
6155 ::=
6156 let elems = (expandCref(cr, true) |> e =>
6157 let &sub = buffer ""
6158 contextCref(e, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6159 ;separator=", ")
6160 let tmp = tempDecl(type + "_array", &varDecls, &varFrees)
6161 let &preExp += '<%rcReleaseBefore(type + "_array", tmp)%>array_alloc_scalar_<%type%>_array(&<%tmp%>, <%listLength(expandCref(cr, true))%>, <%elems%>);<%\n%>'
6162 tmp
6163 end daeExpCrefRhsArrayElems;
6164
6165 310633 template daeExpCrefRhsFunContext(Exp ecr, Context context, Text &preExp,
6166 Text &varDecls, Text &varFrees, Text &auxFunction)
6167 "Generates code for a component reference."
6168 ::=
6169 let &sub = buffer ""
6170 match ecr
6171 case ecr as CREF(componentRef=cr, ty=ty) then
6172 if boolNot(isArrayType(ty)) then
6173 let cast = typeCastContextInt(context, ty)
6174 '<%cast%><%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6175 else if crefSubIsScalar(cr) then
6176 // The array subscript results in a scalar
6177 let cast = typeCastContextInt(context, ty)
6178 '<%cast%><%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6179 else
6180 match context
6181 case FUNCTION_CONTEXT(__) then
6182 // The array subscript denotes a slice
6183 // let &preExp += '/* daeExpCrefRhsFunContext SLICE(<%ExpressionDumpTpl.dumpExp(ecr,"\"")%>) preExp */<%\n%>'
6184 let arrName = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6185 let arrayType = expTypeArray(ty)
6186 let tmp = tempDecl(arrayType, &varDecls, &varFrees)
6187 let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction)
6188 let &preExp += '<%rcReleaseBefore(arrayType, tmp)%>index_alloc_<%arrayType%>(&<%arrName%>, &<%spec1%>, &<%tmp%>);<%\n%>'
6189 tmp
6190 else
6191 error(sourceInfo(),'daeExpCrefRhsFunContext: Slice in simulation context: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6192 case ecr then
6193 error(sourceInfo(),'daeExpCrefRhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6194 end daeExpCrefRhsFunContext;
6195
6196 ✗ template daeExpCrefRhsFunContextParallel(Exp ecr, Context context, Text &preExp,
6197 Text &varDecls, Text &varFrees, Text &auxFunction)
6198 "Generates code for a component reference."
6199 ::=
6200 let &sub = buffer ""
6201 match ecr
6202 case ecr as CREF(componentRef=cr, ty=ty) then
6203 if crefIsScalar(cr, context) then
6204 let cast = typeCastContextInt(context, ty)
6205 '<%cast%><%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6206 else if crefSubIsScalar(cr) then
6207 // The array subscript results in a scalar
6208 let arrName = contextCref(crefStripLastSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6209 let arrayType = expTypeArray(ty)
6210 let subsLenStr = listLength(crefSubs(cr))
6211 let subsValuesStr = (crefSubs(cr) |> INDEX(__) =>
6212 daeSubscriptExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6213 ;separator=", ")
6214 <<
6215 (*<%arrayType%>_element_addr_c99_<%subsLenStr%>(&<%arrName%>, <%subsLenStr%>, <%subsValuesStr%>))
6216 >>
6217 else
6218 // The array subscript denotes a slice
6219 // let &preExp += '/* daeExpCrefRhsFunContext SLICE(<%ExpressionDumpTpl.dumpExp(ecr,"\"")%>) preExp */<%\n%>'
6220 let arrName = contextCref(crefStripLastSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6221 let arrayType = expTypeArray(ty)
6222 let tmp = tempDecl(arrayType, &varDecls, &varFrees)
6223 let spec1 = daeExpCrefIndexSpec(crefSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction)
6224 let &preExp += 'index_alloc_<%arrayType%>(&<%arrName%>, &<%spec1%>, &<%tmp%>);<%\n%>'
6225 tmp
6226 case ecr then
6227 error(sourceInfo(),'daeExpCrefRhsFunContext: UNHANDLED EXPRESSION: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6228 end daeExpCrefRhsFunContextParallel;
6229
6230 // TODO: Optimize as in Codegen
6231 // TODO: Use this function in other places where almost the same thing is hard
6232 // coded
6233 ✗ template arrayScalarRhs(Type ty, list<Exp> subs, String arrName, Context context,
6234 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6235 "Helper to daeExpAsub."
6236 ::=
6237 let arrayType = expTypeArray(ty)
6238 let subsLenStr = listLength(subs)
6239 let subsValuesStr = (subs |> exp =>
6240 daeSubscriptExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
6241
6242 match arrayType
6243 case "metatype_array" then
6244 'arrayGet(<%arrName%>,<%subsValuesStr%>) /*arrayScalarRhs*/'
6245 else
6246 match context
6247 case FUNCTION_CONTEXT(is_parallel = true) then
6248 <<
6249 (*<%arrayType%>_element_addr_c99_<%subsLenStr%>(&<%arrName%>, <%subsLenStr%>, <%subsValuesStr%>))
6250 >>
6251 else
6252 <<
6253 <%arrayType%>_get<%if intLt(listLength(subs), 3) then listLength(subs)%>(<%arrName%>, <%subsLenStr%>, <%subsValuesStr%>)
6254 >>
6255 end arrayScalarRhs;
6256
6257 90214 template daeExpCrefLhs(Exp exp, Context context, Text &preExp,
6258 Text &varDecls, Text &varFrees, Text &auxFunction, Boolean isPre)
6259 "Generates code for a component reference on the left hand side of an expression."
6260 ::=
6261 match exp
6262 case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_FUNC(__)) then
6263 '((modelica_fnptr)boxptr_<%crefFunctionName(cr)%>)'
6264 case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then
6265 '_<%CodegenUtil.crefStr(cr)%>'
6266 else
6267 match context
6268 case FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContext(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6269 else daeExpCrefLhsSimContext(exp, context, &preExp, &varDecls, &varFrees, &auxFunction, isPre)
6270 end daeExpCrefLhs;
6271
6272 18185 template daeExpCrefLhsSimContext(Exp ecr, Context context, Text &preExp,
6273 Text &varDecls, Text &varFrees, Text &auxFunction, Boolean isPre)
6274 "Generates code for a component reference in simulation context."
6275 ::=
6276 match ecr
6277 case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = EXTERNAL_OBJ(__))) then
6278 contextCrefIsPre(cr, context, &auxFunction, isPre)
6279
6280 // If you need to allow this, this is how it should be until simvars has some structure.
6281 // For a record lhs in simulation context we return the list of (pointers to) simvars
6282 // which correspond to the record members. The caller should handle it apropriately.
6283 // Right now this happens in assignment statements and it is handled specially there.
6284 // We can do it here but it is just confusing to follow.
6285 case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then
6286 // let vars = var_lst |> v => (", &" + daeExp(makeCrefRecordExp(cr,v), context, &preExp, &varDecls, &auxFunction))
6287 // '<%mem_simvars%>'
6288 error(sourceInfo(), 'daeExpCrefLhsSimContext got record <%crefStrNoUnderscore(cr)%>. This does not make sense. Assigning to records is handled in a different way in the code generator, and reaching here is probably an error...') // '<%ret_var%>.c1'
6289
6290 case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then
6291 let type = expTypeShort(aty)
6292 let arrayType = type + "_array"
6293 let wrapperArray = tempDecl(arrayType, &varDecls, &varFrees)
6294 if crefSubIsScalar(cr) then
6295 let dimsLenStr = listLength(dims)
6296 let dimsValuesStr = (dims |> dim => '(_index_t)<%dimension(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
6297 // Workaround for https://github.com/OpenModelica/OpenModelica/issues/14470
6298 let arrayData = if hasZeroDimension(dims) then
6299 'NULL'
6300 else if Flags.getConfigBool(Flags.NEW_BACKEND) then
6301 let &sub = buffer '<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
6302 let nosubname = if isPre then
6303 contextCref(crefPrefixPre(crefStripSubs(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6304 else
6305 contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6306 '((modelica_<%type%>*)&(<%nosubname%>))'
6307 else
6308 let &sub = buffer ""
6309 let nosubname = if isPre then
6310 contextCref(crefPrefixPre(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6311 else
6312 contextCref(crefArrayGetFirstCref(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6313 '((modelica_<%type%>*)&(<%nosubname%>))'
6314 let t = '<%type%>_array_create(&<%wrapperArray%>, <%arrayData%>, <%dimsLenStr%>, <%dimsValuesStr%>);<%\n%>'
6315 let &preExp += t
6316 wrapperArray
6317 else
6318 error(sourceInfo(),'daeExpCrefLhsSimContext: This should have been handled in indexed assign and should not have gotten here <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6319
6320 case ecr as CREF(componentRef=cr, ty=ty) then
6321 if crefIsScalarWithAllConstSubs(cr) then
6322 contextCrefIsPre(cr,context, &auxFunction, isPre)
6323 else if crefIsScalarWithVariableSubs(cr) then
6324 '(&<%contextCrefIsPre(crefStripSubs(cr),context, &auxFunction, isPre)%>)<%indexSubs(crefDims(cr), crefSubs(crefArrayGetFirstCref(cr)), context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
6325 else
6326 error(sourceInfo(),'daeExpCrefLhsSimContext: UNHANDLED CREF: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6327 end daeExpCrefLhsSimContext;
6328
6329 4061 template indexSubs(list<Dimension> dims, list<DAE.Subscript> subs, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6330 ::=
6331 if intNe(listLength(dims),listLength(subs)) then
6332 error(sourceInfo(),'indexSubs got different number of dimensions(' + intString(listLength(dims)) + ') and subscripts(' + intString(listLength(subs)) + ')')
6333 else '[<%indexSubRecursive(listReverse(List.restOrEmpty(dims)), listReverse(subs), context, preExp, varDecls, varFrees, auxFunction)%>]'
6334 end indexSubs;
6335
6336 6236 template indexSubRecursive(list<Dimension> dims, list<DAE.Subscript> subs, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6337 " computes the offset for subscripted dimensions to flattened dimensions.
6338 needs to have the last dimension stripped and
6339 subscripts and dimensions in reverse order"
6340 ::=
6341 match subs
6342 case {sub} then
6343 '<%daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction)%> - 1'
6344 case sub :: sub_rest then
6345 let recurse = indexSubRecursive(List.restOrEmpty(dims), sub_rest, context, preExp, varDecls, varFrees, auxFunction)
6346 let dim1 = dimension(listHead(dims), context, &preExp, &varDecls, &varFrees, &auxFunction)
6347 let sub1 = daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction)
6348 '(<%recurse%>) * (<%dim1%>) + (<%sub1%>-1)'
6349 end indexSubRecursive;
6350
6351 70884 template daeExpCrefLhsFunContext(Exp ecr, Context context, Text &preExp,
6352 Text &varDecls, Text &varFrees, Text &auxFunction)
6353 "Generates code for a component reference on the left hand side!"
6354 ::=
6355 match context
6356 case FUNCTION_CONTEXT(is_parallel=true) then daeExpCrefLhsFunContextParModExpl(ecr, context, &preExp, &varDecls, &varFrees, &auxFunction)
6357 case FUNCTION_CONTEXT(__) then daeExpCrefLhsFunContextNormal(ecr, context, &preExp, &varDecls, &varFrees, &auxFunction)
6358 else
6359 error(sourceInfo(),'This should have been handled in the new daeExpCrefLhsSimContext function. <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6360 end daeExpCrefLhsFunContext;
6361
6362 70884 template daeExpCrefLhsFunContextNormal(Exp ecr, Context context, Text &preExp,
6363 Text &varDecls, Text &varFrees, Text &auxFunction)
6364 "Generates code for a component reference on the left hand side!
6365 For a normal function."
6366 ::=
6367 match ecr
6368 case ecr as CREF(componentRef=cr, ty=ty) then
6369 let &sub = buffer ""
6370 if crefIsScalar(cr, context) then
6371 contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6372 else if crefSubIsScalar(cr) then
6373 contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6374 else
6375 error(sourceInfo(),'This should have been handled in indexed assign and should not have gotten here. <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6376
6377 case ecr then
6378 error(sourceInfo(), 'SimCodeC.tpl template: daeExpCrefLhsFunContextNormal: UNHANDLED EXPRESSION: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6379 end daeExpCrefLhsFunContextNormal;
6380
6381 // TODO: Needs revision
6382 ✗ template daeExpCrefLhsFunContextParModExpl(Exp ecr, Context context, Text &preExp,
6383 Text &varDecls, Text &varFrees, Text &auxFunction)
6384 "Generates code for a component reference on the left hand side!
6385 For a parmodelica explicit parallel function."
6386 ::=
6387 match ecr
6388 case ecr as CREF(componentRef=cr, ty=ty) then
6389 if crefIsScalar(cr, context) then
6390 let &sub = buffer ""
6391 '<%contextCref(cr, context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)%>'
6392 else
6393 if crefSubIsScalar(cr) then
6394 // The array subscript results in a scalar
6395 let &sub = buffer ""
6396 let arrName = contextCref(crefStripLastSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
6397 let arrayType = expTypeArray(ty)
6398 let subsLenStr = listLength(crefSubs(cr))
6399 let subsValuesStr = (crefSubs(cr) |> INDEX(__) =>
6400 daeSubscriptExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6401 ;separator=", ")
6402 <<
6403 (*<%arrayType%>_element_addr_c99_<%subsLenStr%>(&<%arrName%>, <%subsLenStr%>, <%subsValuesStr%>))
6404 >>
6405 else
6406 error(sourceInfo(),'This should have been handled in indexed assign and should not have gotten here. <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6407
6408 case ecr then
6409 error(sourceInfo(), 'SimCodeC.tpl template: daeExpCrefLhsFunContextParModExpl: UNHANDLED EXPRESSION: <%ExpressionDumpTpl.dumpExp(ecr,"\"")%>')
6410 end daeExpCrefLhsFunContextParModExpl;
6411
6412 357 template daeExpCrefIndexSpec(list<DAE.Subscript> subs, Context context,
6413 Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6414 "Generates index lists for crefs involving slices"
6415 ::=
6416 let nridx_str = listLength(subs)
6417 let idx_str = (subs |> sub =>
6418 match sub
6419 case INDEX(__) then
6420 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6421 let str = <<(modelica_integer)(0), make_index_array(1, (modelica_integer) <%expPart%>), 'S'>>
6422 str
6423 case WHOLEDIM(__) then
6424 let str = <<(modelica_integer)(1), (int*)0, 'W'>>
6425 str
6426 case SLICE(__) then
6427 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6428 let tmp = tempDecl("modelica_integer", &varDecls, &varFrees)
6429 let &preExp += '<%tmp%> = size_of_dimension_base_array(<%expPart%>, 1);<%\n%>'
6430 let str = <<<%tmp%>, integer_array_make_index_array(<%expPart%>), 'A'>>
6431 str
6432 ;separator=", ")
6433 let tmp = tempDecl("index_spec_t", &varDecls, &varFrees)
6434 let &preExp += '<%rcReleaseBefore("index_spec_t", tmp)%>create_index_spec(&<%tmp%>, <%nridx_str%>, <%idx_str%>);<%\n%>'
6435 tmp
6436 end daeExpCrefIndexSpec;
6437
6438 913777 template daeExpOperand(Exp exp, Text expText, Type ty, Text &preExp, Text &varDecls, Text &varFrees)
6439 "Parenthesizes an operand, or spills it to a temporary when deeply nested."
6440 ::=
6441 if Expression.isDeeperThan(exp, 64) then
6442 let tmp = tempDecl(expTypeModelica(ty), &varDecls, &varFrees)
6443 let &preExp += '<%tmp%> = <%expText%>;<%\n%>'
6444 tmp
6445 else '(<%expText%>)'
6446 end daeExpOperand;
6447
6448 783163 template daeExpBinary(Exp exp, Context context, Text &preExp,
6449 Text &varDecls, Text &varFrees, Text &auxFunction)
6450 "Generates code for a binary expression."
6451 ::=
6452
6453 match exp
6454 case BINARY(__) then
6455 let e1 = daeExp(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
6456 let e2 = daeExp(exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6457 match operator
6458 case ADD(ty = T_STRING(__)) then
6459 let tmpStr = tempDecl("modelica_string", &varDecls, &varFrees)
6460 let &preExp += '<%rcReleaseBefore("modelica_string", tmpStr)%><%tmpStr%> = stringAppend(<%e1%>,<%e2%>);<%\n%>'
6461 tmpStr
6462 case ADD(ty = ty) then
6463 if isAtomic(exp2)
6464 then '<%e1%> + <%e2%>'
6465 else '<%e1%> + <%daeExpOperand(exp2, e2, ty, &preExp, &varDecls, &varFrees)%>'
6466 case SUB(ty = ty) then
6467 if isAtomic(exp2)
6468 then '<%e1%> - <%e2%>'
6469 else '<%e1%> - <%daeExpOperand(exp2, e2, ty, &preExp, &varDecls, &varFrees)%>'
6470 case MUL(ty = ty) then '<%daeExpOperand(exp1, e1, ty, &preExp, &varDecls, &varFrees)%> * <%daeExpOperand(exp2, e2, ty, &preExp, &varDecls, &varFrees)%>'
6471 case DIV(ty = ty) then
6472 (match context
6473 case FUNCTION_CONTEXT(__) then
6474 let tvar = tempDecl(expTypeModelica(ty),&varDecls, &varFrees)
6475 let &preExp += '<%tvar%> = <%e2%>;<%\n%><%errorCheck(context)%>'
6476 let &preExp += if metaModelicaRuntime() then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>'
6477 else 'if (<%tvar%> == 0) {raiseStreamPrint(threadData, "Division by zero %s in function context", "<%Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp,"\""))%>"); <%errorCheck(context)%>}<%\n%>'
6478 '(<%e1%>) / <%tvar%>'
6479 case SIMULATION_CONTEXT() then
6480 let e2str = Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp2,"\""))
6481 'DIVISION_SIM(<%e1%>,<%e2%>,"<%e2str%>",equationIndexes)'
6482 else
6483 let e2str = Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp2,"\""))
6484 'DIVISION(<%e1%>,<%e2%>,"<%e2str%>")'
6485 )
6486
6487 case POW(__) then
6488 if isHalf(exp2) then
6489 let tmp = tempDecl(expTypeFromExpModelica(exp1),&varDecls, &varFrees)
6490 let cstr = ExpressionDumpTpl.dumpExp(exp1,"\"")
6491 let &preExp +=
6492 <<
6493 <%tmp%> = <%e1%>;
6494 if(<%tmp%> < 0.0) {
6495 <%if metaModelicaRuntime()
6496 then '<%generateThrow()%>;<%\n%>'
6497 else 'raiseStreamPrint(threadData, "%s:%d: Invalid root: (%g)^(%g)", __FILE__, __LINE__, <%tmp%>, 0.5);<%\n%>'%>
6498 }
6499 >>
6500 'sqrt(<%tmp%>)'
6501 else match realExpIntLit(exp2)
6502 case SOME(2) then
6503 let tmp = tempDecl("modelica_real", &varDecls, &varFrees)
6504 let &preExp += '<%tmp%> = <%e1%>;<%\n%>'
6505 '(<%tmp%> * <%tmp%>)'
6506 case SOME(3) then
6507 let tmp = tempDecl("modelica_real", &varDecls, &varFrees)
6508 let &preExp += '<%tmp%> = <%e1%>;<%\n%>'
6509 '(<%tmp%> * <%tmp%> * <%tmp%>)'
6510 case SOME(4) then
6511 let tmp = tempDecl("modelica_real", &varDecls, &varFrees)
6512 let &preExp +=
6513 <<
6514 <%tmp%> = <%e1%>;<%\n%>
6515 <%tmp%> *= <%tmp%>;
6516 >>
6517 '(<%tmp%> * <%tmp%>)'
6518 case SOME(i) then 'real_int_pow(threadData, <%e1%>, <%i%>)'
6519 else
6520 let tmp1 = tempDecl("modelica_real", &varDecls, &varFrees)
6521 let tmp2 = tempDecl("modelica_real", &varDecls, &varFrees)
6522 let tmp3 = tempDecl("modelica_real", &varDecls, &varFrees)
6523 let tmp4 = tempDecl("modelica_real", &varDecls, &varFrees) //fractpart
6524 let tmp5 = tempDecl("modelica_real", &varDecls, &varFrees) //intpart
6525 let tmp6 = tempDecl("modelica_real", &varDecls, &varFrees) //intpart
6526 let tmp7 = tempDecl("modelica_real", &varDecls, &varFrees) //fractpart
6527 let &preExp +=
6528 <<
6529 <%tmp1%> = <%e1%>;
6530 <%tmp2%> = <%e2%>;
6531 if(<%tmp1%> < 0.0 && <%tmp2%> != 0.0)
6532 {
6533 <%tmp4%> = modf(<%tmp2%>, &<%tmp5%>);
6534
6535 if(<%tmp4%> > 0.5)
6536 {
6537 <%tmp4%> -= 1.0;
6538 <%tmp5%> += 1.0;
6539 }
6540 else if(<%tmp4%> < -0.5)
6541 {
6542 <%tmp4%> += 1.0;
6543 <%tmp5%> -= 1.0;
6544 }
6545
6546 if(fabs(<%tmp4%>) < 1e-10)
6547 <%tmp3%> = pow(<%tmp1%>, <%tmp5%>);
6548 else
6549 {
6550 <%tmp7%> = modf(1.0/<%tmp2%>, &<%tmp6%>);
6551 if(<%tmp7%> > 0.5)
6552 {
6553 <%tmp7%> -= 1.0;
6554 <%tmp6%> += 1.0;
6555 }
6556 else if(<%tmp7%> < -0.5)
6557 {
6558 <%tmp7%> += 1.0;
6559 <%tmp6%> -= 1.0;
6560 }
6561 if(fabs(<%tmp7%>) < 1e-10 && ((unsigned long)<%tmp6%> & 1))
6562 {
6563 <%tmp3%> = -pow(-<%tmp1%>, <%tmp4%>)*pow(<%tmp1%>, <%tmp5%>);
6564 }
6565 else
6566 {
6567 <%if metaModelicaRuntime()
6568 then '<%generateThrow()%>;<%\n%>'
6569 else 'raiseStreamPrint(threadData, "%s:%d: Invalid root: (%g)^(%g)", __FILE__, __LINE__, <%tmp1%>, <%tmp2%>);<%\n%>'%>
6570 }
6571 }
6572 }
6573 else
6574 {
6575 <%tmp3%> = pow(<%tmp1%>, <%tmp2%>);
6576 }
6577 if(isnan(<%tmp3%>) || isinf(<%tmp3%>))
6578 {
6579 <%if metaModelicaRuntime()
6580 then '<%generateThrow()%>;<%\n%>'
6581 else 'raiseStreamPrint(threadData, "%s:%d: Invalid root: (%g)^(%g)", __FILE__, __LINE__, <%tmp1%>, <%tmp2%>);<%\n%>'%>
6582 }
6583 >>
6584 '<%tmp3%>'
6585
6586 case UMINUS(__) then daeExpUnary(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6587 case ADD_ARR(__) then
6588 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6589 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6590 else "real_array"
6591 rcSpillArray(type, 'add_alloc_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6592 case SUB_ARR(__) then
6593 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6594 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6595 else "real_array"
6596 rcSpillArray(type, 'sub_alloc_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6597 case MUL_ARR(__) then
6598 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6599 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6600 else "real_array"
6601 rcSpillArray(type, 'mul_alloc_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6602 case DIV_ARR(__) then
6603 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6604 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6605 else "real_array"
6606 rcSpillArray(type, 'div_alloc_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6607 case MUL_ARRAY_SCALAR(__) then
6608 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6609 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6610 else "real_array"
6611 if isArrayType(typeof(exp1)) then
6612 rcSpillArray(type, 'mul_alloc_<%type%>_scalar(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6613 else
6614 rcSpillArray(type, 'mul_alloc_<%type%>_scalar(<%e2%>, <%e1%>)', &preExp, &varDecls, &varFrees)
6615 case ADD_ARRAY_SCALAR(__) then
6616 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6617 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6618 else "real_array"
6619 if isArrayType(typeof(exp1)) then
6620 rcSpillArray(type, 'add_alloc_<%type%>_scalar(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6621 else
6622 rcSpillArray(type, 'add_alloc_<%type%>_scalar(<%e2%>, <%e1%>)', &preExp, &varDecls, &varFrees)
6623 case SUB_SCALAR_ARRAY(__) then
6624 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6625 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6626 else "real_array"
6627 // There is no SUB_ARRAY_SCALAR e.g. (a - 1). Instead it will be ADD_ARRAY_SCALAR(arr, NEG(scalar)) (a + -1)
6628 rcSpillArray(type, 'sub_alloc_scalar_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6629 case MUL_SCALAR_PRODUCT(__) then
6630 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_scalar"
6631 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_scalar"
6632 case T_INTEGER(__) then "integer_scalar"
6633 case T_ENUMERATION(__) then "integer_scalar"
6634 else "real_scalar"
6635 'mul_<%type%>_product(<%e1%>, <%e2%>)'
6636 case MUL_MATRIX_PRODUCT(__) then
6637 let typeShort = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer"
6638 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer"
6639 else "real"
6640 let type = '<%typeShort%>_array'
6641 rcSpillArray(type, 'mul_alloc_<%typeShort%>_matrix_product_smart(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6642 case DIV_ARRAY_SCALAR(__) then
6643 let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
6644 case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
6645 else "real_array"
6646 let e2str = Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp2,"\""))
6647 (match context
6648 case FUNCTION_CONTEXT(__) then
6649 rcSpillArray(type, 'div_alloc_<%type%>_scalar(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6650 // same checks as DIVISION_SIM, e.g. 0/0 is 0 during initialization
6651 case SIMULATION_CONTEXT() then
6652 if stringEq(type, "real_array") then
6653 rcSpillArray(type, 'division_alloc_real_array_scalar_sim(threadData,<%e1%>,<%e2%>,"<%e2str%>",equationIndexes,data->simulationInfo->noThrowDivZero,data->localData[0]->timeValue,initial())', &preExp, &varDecls, &varFrees)
6654 else
6655 rcSpillArray(type, 'division_alloc_<%type%>_scalar(threadData,<%e1%>,<%e2%>,"<%e2str%>")', &preExp, &varDecls, &varFrees)
6656 else
6657 rcSpillArray(type, 'division_alloc_<%type%>_scalar(threadData,<%e1%>,<%e2%>,"<%e2str%>")', &preExp, &varDecls, &varFrees)
6658 )
6659
6660 case DIV_SCALAR_ARRAY(__) then
6661 let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array"
6662 case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array"
6663 else "real_array"
6664 rcSpillArray(type, 'div_alloc_scalar_<%type%>(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6665 case POW_ARRAY_SCALAR(__) then
6666 let type = match ty case T_ARRAY(ty = T_INTEGER(__)) then "integer_array"
6667 case T_ARRAY(ty = T_ENUMERATION(__)) then "integer_array"
6668 else "real_array"
6669 rcSpillArray(type, 'pow_alloc_<%type%>_scalar(<%e1%>, <%e2%>)', &preExp, &varDecls, &varFrees)
6670 case POW_ARRAY_SCALAR(__) then error(sourceInfo(),"daeExpBinary:ERR for POW_ARRAY_SCALAR not implemented")
6671 case POW_SCALAR_ARRAY(__) then error(sourceInfo(),"daeExpBinary:ERR for POW_SCALAR_ARRAY not implemented")
6672 case POW_ARR(__) then error(sourceInfo(),"daeExpBinary:ERR for POW_ARR not implemented")
6673 case POW_ARR2(__) then error(sourceInfo(),"daeExpBinary:ERR for POW_ARR2 not implemented")
6674 else error(sourceInfo(), 'daeExpBinary:ERR')
6675 end daeExpBinary;
6676
6677
6678 34222 template daeExpUnary(Exp exp, Context context, Text &preExp,
6679 Text &varDecls, Text &varFrees, Text &auxFunction)
6680 "Generates code for a unary expression."
6681 ::=
6682 match exp
6683 case UNARY(__) then
6684 let e = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6685 match operator
6686 case UMINUS(__) then
6687 if isAtomic(exp)
6688 then '(-<%e%>)'
6689 else '(-(<%e%>))'
6690 case UMINUS_ARR(ty=T_ARRAY(ty=T_REAL(__))) then
6691 let var = tempDecl("real_array", &varDecls, &varFrees)
6692 let &preExp += '<%rcReleaseBefore("real_array", var)%>usub_alloc_real_array(<%e%>,&<%var%>);<%\n%>'
6693 '<%var%>'
6694 case UMINUS_ARR(ty=T_ARRAY(ty=T_INTEGER(__))) then
6695 let var = tempDecl("integer_array", &varDecls, &varFrees)
6696 let &preExp += '<%rcReleaseBefore("integer_array", var)%>usub_alloc_integer_array(<%e%>,&<%var%>);<%\n%>'
6697 '<%var%>'
6698 case UMINUS_ARR(__) then error(sourceInfo(),"unary minus for non-real arrays not implemented")
6699 else error(sourceInfo(),"daeExpUnary:ERR")
6700 end daeExpUnary;
6701
6702
6703 23301 template daeExpLbinary(Exp exp, Context context, Text &preExp,
6704 Text &varDecls, Text &varFrees, Text &auxFunction)
6705 "Generates code for a logical binary expression."
6706 ::=
6707 match exp
6708 case LBINARY(__) then
6709 let e1 = daeExp(exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
6710 let e2 = daeExp(exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6711 match operator
6712 case AND(ty = T_ARRAY(__)) then
6713 let var = tempDecl("boolean_array", &varDecls, &varFrees)
6714 let &preExp += 'and_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>'
6715 '<%var%>'
6716 case AND(__) then
6717 '(<%e1%> && <%e2%>)'
6718 case OR(ty = T_ARRAY(__)) then
6719 let var = tempDecl("boolean_array", &varDecls, &varFrees)
6720 let &preExp += 'or_boolean_array(&<%e1%>,&<%e2%>,&<%var%>);<%\n%>'
6721 '<%var%>'
6722 case OR(__) then
6723 '(<%e1%> || <%e2%>)'
6724 else error(sourceInfo(),"daeExpLbinary:ERR")
6725 end daeExpLbinary;
6726
6727
6728 1841 template daeExpLunary(Exp exp, Context context, Text &preExp,
6729 Text &varDecls, Text &varFrees, Text &auxFunction)
6730 "Generates code for a logical unary expression."
6731 ::=
6732 match exp
6733 case LUNARY(__) then
6734 let e = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6735 match operator
6736 case NOT(ty = T_ARRAY(__)) then
6737 let var = tempDecl("boolean_array", &varDecls, &varFrees)
6738 let &preExp += 'not_boolean_array(<%e%>,&<%var%>);<%\n%>'
6739 '<%var%>'
6740 else
6741 '(!<%e%>)'
6742 end daeExpLunary;
6743
6744
6745 77372 template daeExpRelation(Exp exp, Context context, Text &preExp,
6746 Text &varDecls, Text &varFrees, Text &auxFunction)
6747 "Generates code for a relation expression."
6748 ::=
6749 match exp
6750 case rel as RELATION(__) then
6751 let &varDecls2 = buffer ""
6752 let &varFrees2 = buffer ""
6753 let &preExp2 = buffer ""
6754 let simRel = daeExpRelationSim(rel, context, &preExp2, &varDecls2, &varFrees2, &auxFunction)
6755 if simRel then
6756 /* Don't add the allocated temp-var unless it is used */
6757 let &varDecls += varDecls2
6758 let &varFrees += varFrees2
6759 let &preExp += preExp2
6760 simRel
6761 else
6762 let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
6763 let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6764 match rel.operator
6765
6766 case LESS(ty = T_BOOL(__)) then '(!<%e1%> && <%e2%>)'
6767 case LESS(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) < 0)'
6768 case LESS(ty = T_INTEGER(__)) then '(<%e1%> < <%e2%>)'
6769 case LESS(ty = T_REAL(__)) then '(<%e1%> < <%e2%>)'
6770 case LESS(ty = T_ENUMERATION(__)) then '(<%e1%> < <%e2%>)'
6771
6772 case GREATER(ty = T_BOOL(__)) then '(<%e1%> && !<%e2%>)'
6773 case GREATER(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) > 0)'
6774 case GREATER(ty = T_INTEGER(__)) then '(<%e1%> > <%e2%>)'
6775 case GREATER(ty = T_REAL(__)) then '(<%e1%> > <%e2%>)'
6776 case GREATER(ty = T_ENUMERATION(__)) then '(<%e1%> > <%e2%>)'
6777
6778 case LESSEQ(ty = T_BOOL(__)) then '(!<%e1%> || <%e2%>)'
6779 case LESSEQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) <= 0)'
6780 case LESSEQ(ty = T_INTEGER(__)) then '(<%e1%> <= <%e2%>)'
6781 case LESSEQ(ty = T_REAL(__)) then '(<%e1%> <= <%e2%>)'
6782 case LESSEQ(ty = T_ENUMERATION(__)) then '(<%e1%> <= <%e2%>)'
6783
6784 case GREATEREQ(ty = T_BOOL(__)) then '(<%e1%> || !<%e2%>)'
6785 case GREATEREQ(ty = T_STRING(__)) then '(stringCompare(<%e1%>, <%e2%>) >= 0)'
6786 case GREATEREQ(ty = T_INTEGER(__)) then '(<%e1%> >= <%e2%>)'
6787 case GREATEREQ(ty = T_REAL(__)) then '(<%e1%> >= <%e2%>)'
6788 case GREATEREQ(ty = T_ENUMERATION(__)) then '(<%e1%> >= <%e2%>)'
6789
6790 case EQUAL(ty = T_BOOL(__)) then '(!<%e1%> == !<%e2%>)' /* the ! converts to bool if not already */
6791 case EQUAL(ty = T_STRING(__)) then '(stringEqual(<%e1%>, <%e2%>))'
6792 case EQUAL(ty = T_INTEGER(__)) then '(<%e1%> == <%e2%>)'
6793 case EQUAL(ty = T_REAL(__)) then '(<%e1%> == <%e2%>)'
6794 case EQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> == <%e2%>)'
6795 //case EQUAL(ty = T_ARRAY(__)) then '<%e2%>' /* Used for Boolean array. Called from daeExpLunary. */
6796 case EQUAL(ty = T_ARRAY(__)) then '(<%e1%> == <%e2%>)'
6797
6798 case NEQUAL(ty = T_BOOL(__)) then '(!<%e1%> != !<%e2%>)' /* the ! converts to bool if not already */
6799 case NEQUAL(ty = T_STRING(__)) then '(!stringEqual(<%e1%>, <%e2%>))'
6800 case NEQUAL(ty = T_INTEGER(__)) then '(<%e1%> != <%e2%>)'
6801 case NEQUAL(ty = T_REAL(__)) then '(<%e1%> != <%e2%>)'
6802 case NEQUAL(ty = T_ENUMERATION(__)) then '(<%e1%> != <%e2%>)'
6803
6804 else error(sourceInfo(), 'daeExpRelation <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
6805 else error(sourceInfo(), 'daeExpRelation: Input expression not a DAE.RELATION ')
6806 end match
6807 end daeExpRelation;
6808
6809
6810
6811 77372 template daeExpRelationSim(Exp exp, Context context, Text &preExp,
6812 Text &varDecls, Text &varFrees, Text &auxFunction)
6813 "Helper to daeExpRelation."
6814 ::=
6815 match exp
6816 case rel as RELATION(__) then
6817 match context
6818 case JACOBIAN_CONTEXT(__)
6819 case DAE_MODE_CONTEXT(__)
6820 case SIMULATION_CONTEXT(__) then
6821 let rel_f = match rel.operator
6822 case LESS(__) then 'Less'
6823 case LESSEQ(__) then 'LessEq'
6824 case GREATER(__) then 'Greater'
6825 case GREATEREQ(__) then 'GreaterEq'
6826 end match
6827 if rel_f then
6828 let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
6829 let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6830 let res = tempDecl("modelica_boolean", &varDecls, &varFrees)
6831 if intEq(rel.index,-1) then
6832 let &preExp += '<%res%> = <%rel_f%>(<%e1%>,<%e2%>);<%\n%>'
6833 res
6834 else
6835 let isReal = if isTimeEventRelation(exp) then '' else if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else ''
6836 match rel.optionExpisASUB
6837 case NONE() then
6838 if isReal then
6839 let tmp1 = tempDecl("modelica_real", &varDecls, &varFrees)
6840 let tmp2 = tempDecl("modelica_real", &varDecls, &varFrees)
6841 let nominalTmp = daeExpNominalTmp(tmp1, tmp2, rel.exp1, rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6842 let &preExp += '<%nominalTmp%><%\n%>'
6843 let &preExp += 'relationhysteresis(data, &<%res%>, <%e1%>, <%e2%>, <%tmp1%>, <%tmp2%>, <%rel.index%>, <%rel_f%>, <%rel_f%>ZC);<%\n%>'
6844 res
6845 else
6846 let &preExp += 'relation(data, &<%res%>, <%e1%>, <%e2%>, <%rel.index%>, <%rel_f%>);<%\n%>'
6847 res
6848 case SOME((exp,i,j)) then
6849 let iterator = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6850 if isReal then
6851 let tmp1 = tempDecl("modelica_real", &varDecls, &varFrees)
6852 let tmp2 = tempDecl("modelica_real", &varDecls, &varFrees)
6853 let nominalTmp = daeExpNominalTmp(tmp1, tmp2, rel.exp1, rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6854 let &preExp += '<%nominalTmp%><%\n%>'
6855 let &preExp += 'relationhysteresis(data, &<%res%>, <%e1%>, <%e2%>, <%tmp1%>, <%tmp2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, <%rel_f%>, <%rel_f%>ZC);<%\n%>'
6856 res
6857 else
6858 let &preExp += 'relation(data, &<%res%>, <%e1%>, <%e2%>, <%rel.index%> + (<%iterator%> - <%i%>)/<%j%>, <%rel_f%>);<%\n%>'
6859 res
6860 end match
6861 case ZEROCROSSINGS_CONTEXT(__) then
6862 let rel_f = match rel.operator
6863 case LESS(__) then 'Less'
6864 case LESSEQ(__) then 'LessEq'
6865 case GREATER(__) then 'Greater'
6866 case GREATEREQ(__) then 'GreaterEq'
6867 end match
6868 if rel_f then
6869 let e1 = daeExp(rel.exp1, context, &preExp, &varDecls, &varFrees, &auxFunction)
6870 let e2 = daeExp(rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6871 let res = tempDecl("modelica_boolean", &varDecls, &varFrees)
6872 if intEq(rel.index,-1) then
6873 let &preExp += '<%res%> = <%rel_f%>(<%e1%>,<%e2%>);<%\n%>'
6874 res
6875 else
6876 let isReal = if isTimeEventRelation(exp) then '' else if isRealType(typeof(rel.exp1)) then (if isRealType(typeof(rel.exp2)) then 'true' else '') else ''
6877 match rel.optionExpisASUB
6878 case NONE() then
6879 if isTimeEventRelation(exp) then
6880 let &preExp += '<%res%> = data->simulationInfo->storedRelations[<%rel.index%>];<%\n%>'
6881 res
6882 else if isReal then
6883 let tmp1 = tempDecl("modelica_real", &varDecls, &varFrees)
6884 let tmp2 = tempDecl("modelica_real", &varDecls, &varFrees)
6885 let nominalTmp = daeExpNominalTmp(tmp1, tmp2, rel.exp1, rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6886 let &preExp += '<%nominalTmp%><%\n%>'
6887 let &preExp += '<%res%> = <%rel_f%>ZC(<%e1%>, <%e2%>, <%tmp1%>, <%tmp2%>, data->simulationInfo->storedRelations[<%rel.index%>]);<%\n%>'
6888 res
6889 else
6890 let &preExp += '<%res%> = <%rel_f%>(<%e1%>,<%e2%>);<%\n%>'
6891 res
6892 case SOME((exp,i,j)) then
6893 if isReal then
6894 let iterator = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6895 let tmp1 = tempDecl("modelica_real", &varDecls, &varFrees)
6896 let tmp2 = tempDecl("modelica_real", &varDecls, &varFrees)
6897 let nominalTmp = daeExpNominalTmp(tmp1, tmp2, rel.exp1, rel.exp2, context, &preExp, &varDecls, &varFrees, &auxFunction)
6898 let &preExp += '<%nominalTmp%><%\n%>'
6899 let &preExp += '<%res%> = <%rel_f%>ZC(<%e1%>, <%e2%>, <%tmp1%>, <%tmp2%>, data->simulationInfo->storedRelations[<%rel.index%> + (<%iterator%> - <%i%>)/<%j%>]);<%\n%>'
6900 res
6901 else
6902 let &preExp += '<%res%> = <%rel_f%>(<%e1%>,<%e2%>);<%\n%>'
6903 res
6904 end match
6905 end match
6906 end match
6907 end daeExpRelationSim;
6908
6909 3270 template daeExpNominalTmp(String tmp1, String tmp2, Exp exp1, Exp exp2, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6910 "Generates assignments for nominal values of expression into tmp var"
6911 ::=
6912 <<
6913 <%tmp1%> = <%daeExp(getExpNominal(exp1), context, &preExp, &varDecls, &varFrees, &auxFunction)%>;
6914 <%tmp2%> = <%daeExp(getExpNominal(exp2), context, &preExp, &varDecls, &varFrees, &auxFunction)%>;
6915 >>
6916 end daeExpNominalTmp;
6917
6918 13584 template daeExpIf(Exp exp, Context context, Text &preExp,
6919 Text &varDecls, Text &varFrees, Text &auxFunction)
6920 "Generates code for an if expression."
6921 ::=
6922 match exp
6923 case IFEXP(__) then
6924 let condExp = daeExp(expCond, context, &preExp, &varDecls, &varFrees, &auxFunction)
6925 let &preExpThen = buffer ""
6926 let eThen = daeExp(expThen, context, &preExpThen, &varDecls, &varFrees, &auxFunction)
6927 let &preExpElse = buffer ""
6928 let eElse = daeExp(expElse, context, &preExpElse, &varDecls, &varFrees, &auxFunction)
6929 let shortIfExp = if preExpThen then "" else if preExpElse then "" else if isArrayType(typeof(exp)) then "" else if isRecordType(typeof(exp)) then "" else "x"
6930 (if shortIfExp then
6931 // Safe to do if eThen and eElse don't emit pre-expressions
6932 '(<%condExp%>?<%eThen%>:<%eElse%>)'
6933 else
6934 let condVar = tempDecl("modelica_boolean", &varDecls, &varFrees)
6935 let resVar = tempDeclTuple(typeof(exp), &varDecls, &varFrees)
6936 let &preExp +=
6937 <<
6938 <%condVar%> = (modelica_boolean)<%condExp%>;
6939 if(<%condVar%>)
6940 {
6941 <%preExpThen%>
6942 <%if eThen then resultVarAssignment(typeof(exp),resVar,eThen)%>
6943 }
6944 else
6945 {
6946 <%preExpElse%>
6947 <%if eElse then resultVarAssignment(typeof(exp),resVar,eElse)%>
6948 }<%\n%>
6949 >>
6950 resVar
6951 )
6952 end daeExpIf;
6953
6954 ✗ template iteratedCrefStr(ComponentRef cref)
6955 ::=
6956 System.unquoteIdentifier(crefStrNoUnderscore(cref))
6957 end iteratedCrefStr;
6958
6959 12468 template resultVarAssignment(DAE.Type ty, Text lhs, Text rhs) "Tuple need to be considered"
6960 ::=
6961 // The copy takes its own reference, or both sides release the same blocks.
6962 match ty
6963 case T_TUPLE(__) then
6964 (types |> t hasindex i1 fromindex 1 => rcAssignRetain(expTypeArrayIf(t), '<%lhs%>.c<%i1%>', '<%rhs%>.c<%i1%>') ; separator="")
6965 else
6966 rcAssignRetain(expTypeArrayIf(ty), lhs, rhs)
6967 end resultVarAssignment;
6968
6969 3546 template daeExpRecord(Exp rec, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6970 ::=
6971 match rec
6972 case RECORD(__) then
6973 let name = tempDecl(underscorePath(path), &varDecls, &varFrees)
6974 // The record is released like any other temporary, so it takes its own
6975 // reference to what the members are built from.
6976 let ass = List.zip(exps,comp) |> (exp,compn) =>
6977 rcAssignRetain(expTypeFromExpArrayIf(exp), '<%name%>._<%System.unquoteIdentifier(compn)%>', daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction))
6978 let &preExp += ass
6979 name
6980 end daeExpRecord;
6981
6982 175 template daeExpPartEvalFunction(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6983 ::=
6984 if unboxedFunctionReferences()
6985 then daeExpClosure(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6986 else daeExpPartEvalFunctionBoxed(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
6987 end daeExpPartEvalFunction;
6988
6989 151 template daeExpClosure(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
6990 "The closure and what it captured are locals of the frame that makes it, and
6991 borrow what they hold from it."
6992 ::=
6993 match exp
6994 case PARTEVALFUNCTION(ty=T_FUNCTION_REFERENCE_VAR(functionType = t as T_FUNCTION(__)),origType=T_FUNCTION_REFERENCE_VAR(functionType = orig as T_FUNCTION(functionAttributes=attr as FUNCTION_ATTRIBUTES(__), path=name))) then
6995 let func = 'closure<%System.tmpTickIndex(2/*auxFunction*/)%>_<%underscorePath(name)%>'
6996 let ret = functionReferenceReturnType(t.funcResultType)
6997 let return = match t.funcResultType case T_NORETCALL(__) then "" else "return "
6998 let &outArgs = buffer ""
6999 let outParams = match t.funcResultType
7000 case T_TUPLE(types=_::tys) then
7001 (tys |> ty hasindex i1 fromindex 2 =>
7002 let &outArgs += ', out<%i1%>'
7003 ', <%expTypeArrayIf(ty)%> *out<%i1%>')
7004 let args = (orig.funcArg |> a as FUNCARG(__) => ', _<%System.unquoteIdentifier(a.name)%>')
7005 let env = 'tmp<%System.tmpTick()%>'
7006 let &varDecls += 'struct <%func%>_env <%env%>;<%\n%>'
7007 let captured = (expList |> e hasindex i1 fromindex 1 =>
7008 '<%env%>.f<%i1%> = <%daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)%>;<%\n%>')
7009 let &preExp += captured
7010 let &preExp += if attr.isFunctionPointer then '<%env%>.fn = _<%underscorePath(name)%>;<%\n%>'
7011 let clo = 'tmp<%System.tmpTick()%>'
7012 let &varDecls += 'omc_closure <%clo%>;<%\n%>'
7013 let &preExp += '<%clo%>.fn = (void*) <%func%>;<%\n%><%clo%>.env = &<%env%>;<%\n%>'
7014 let &auxFunction +=
7015 <<
7016 struct <%func%>_env {
7017 <%setDifference(orig.funcArg,t.funcArg) |> a as FUNCARG(__) hasindex i1 fromindex 1 => '<%expTypeArrayIf(a.ty)%> f<%i1%>;' ;separator="\n"%>
7018 <%if attr.isFunctionPointer then "modelica_fnptr fn;" else if listEmpty(expList) then "char unused;"%>
7019 };
7020 static <%ret%> <%func%>(threadData_t *threadData, void *env<%t.funcArg |> a as FUNCARG(__) => ', <%expTypeArrayIf(a.ty)%> _<%System.unquoteIdentifier(a.name)%>'%><%outParams%>)
7021 {
7022 struct <%func%>_env *closure = (struct <%func%>_env*) env;
7023 <%setDifference(orig.funcArg,t.funcArg) |> a as FUNCARG(__) hasindex i1 fromindex 1 => '<%expTypeArrayIf(a.ty)%> _<%System.unquoteIdentifier(a.name)%> = closure->f<%i1%>;' ;separator="\n"%>
7024 <%if attr.isFunctionPointer then
7025 let tys = (orig.funcArg |> a as FUNCARG(__) => ', <%expTypeArrayIf(a.ty)%>') + functionReferenceOutputTypes(t.funcResultType)
7026 <<
7027 modelica_fnptr fn = closure->fn;
7028 <%return%>OMC_BOX_FIELD(fn, 2)
7029 ? ((<%ret%>(*)(threadData_t*, void*<%tys%>)) OMC_BOX_FIELD(fn, 1))(threadData, OMC_BOX_FIELD(fn, 2)<%args%><%outArgs%>)
7030 : ((<%ret%>(*)(threadData_t*<%tys%>)) OMC_BOX_FIELD(fn, 1))(threadData<%args%><%outArgs%>);
7031 >>
7032 else
7033 '<%return%>omc_<%underscorePath(name)%>(threadData<%args%><%outArgs%>);'%>
7034 }
7035 >>
7036 '(modelica_fnptr) &<%clo%>'
7037 case PARTEVALFUNCTION(__) then
7038 error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>')
7039 end daeExpClosure;
7040
7041 24 template daeExpPartEvalFunctionBoxed(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7042 ::=
7043 match exp
7044 case PARTEVALFUNCTION(ty=T_FUNCTION_REFERENCE_VAR(functionType = t as T_FUNCTION(__)),origType=T_FUNCTION_REFERENCE_VAR(functionType = orig as T_FUNCTION(functionAttributes=attr as FUNCTION_ATTRIBUTES(__), path=name))) then
7045 let &varDeclInner = buffer ""
7046 let &ret = buffer ""
7047 let retInput = match t.funcResultType
7048 case T_TUPLE(types=_::tys) then
7049 (tys |> ty =>
7050 let name = 'tmp<%System.tmpTick()%>'
7051 let &ret += ', <%name%>'
7052 ', <%expTypeArrayIf(ty)%> <%name%>')
7053 let func = 'closure<%System.tmpTickIndex(2/*auxFunction*/)%>_<%underscorePath(name)%>'
7054 let return = match t.funcResultType case T_NORETCALL(__) then "" else "return "
7055 let closure = tempDecl("modelica_metatype",&varDecls, &varFrees)
7056 let createClosure = (expList |> e => ', <%daeExp(e,context,&preExp,&varDecls, &varFrees,&auxFunction)%>') + (if attr.isFunctionPointer then ', _<%underscorePath(name)%>')
7057 let &preExp += '<%closure%> = omc_mk_box<%if attr.isFunctionPointer then daeExpMetaHelperBoxStart(incrementInt(listLength(expList),1)) else daeExpMetaHelperBoxStart(listLength(expList))%>0<%createClosure%>);<%\n%>'
7058 let &auxFunction +=
7059 <<
7060 static <%match t.funcResultType case T_NORETCALL(__) then "void" else "modelica_metatype"%> <%func%>(threadData_t *thData, modelica_metatype closure<%t.funcArg |> a as FUNCARG(__) => ', <%expTypeArrayIf(a.ty)%> <%a.name%>'%><%retInput%>)
7061 {
7062 <%varDeclInner%>
7063 <%setDifference(orig.funcArg,t.funcArg) |> a as FUNCARG(__) hasindex i1 fromindex 1 => '<%expTypeArrayIf(a.ty)%> <%a.name%> = OMC_BOX_FIELD(closure, <%i1%>);<%\n%>'%>
7064 <%
7065 if attr.isFunctionPointer then
7066 let fname = '_<%underscorePath(name)%>'
7067 let func = '(OMC_BOX_FIELD(<%fname%>, 1))'
7068 let typeCast1 = generateTypeCastFromType(orig, true)
7069 let typeCast2 = generateTypeCastFromType(orig, false)
7070 <<
7071 modelica_fnptr <%fname%> = OMC_BOX_FIELD(closure, <%incrementInt(listLength(setDifference(orig.funcArg,t.funcArg)),1)%>);
7072 if (OMC_BOX_FIELD(<%fname%>, 2)) {
7073 <%return%> (<%typeCast1%> <%func%>) (thData, OMC_BOX_FIELD(<%fname%>, 2)<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>);
7074 } else { /* No closure in the called variable */
7075 <%return%> (<%typeCast2%> <%func%>) (thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>);
7076 }
7077 >>
7078 else
7079 '<%return%>boxptr_<%underscorePath(name)%>(thData<%orig.funcArg |> a as FUNCARG(__) => ', <%a.name%>'%><%ret%>);'
7080 %>
7081 }
7082 >>
7083 '(modelica_fnptr) omc_mk_box2(0,<%if Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS) then "&"%><%func%>,<%closure%>)'
7084 // error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>')
7085 case PARTEVALFUNCTION(__) then
7086 error(sourceInfo(), 'PARTEVALFUNCTION: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>, ty=<%unparseType(ty)%>, origType=<%unparseType(origType)%>')
7087 end daeExpPartEvalFunctionBoxed;
7088
7089 109582 template daeExpCall(Exp call, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7090 "Generates code for a function call."
7091 ::=
7092 let &sub = buffer ""
7093 match call
7094 // special builtins
7095 case CALL(path=IDENT(name="smooth"),
7096 expLst={e1, e2}) then
7097 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7098 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7099 var2
7100
7101 case CALL(path=IDENT(name="der"), expLst={arg as CREF(__)}) then
7102 cref(crefPrefixDer(arg.componentRef), &sub)
7103 case CALL(path=IDENT(name="der"), expLst={exp}) then
7104 error(sourceInfo(), 'Code generation does not support der(<%ExpressionDumpTpl.dumpExp(exp,"\"")%>)')
7105 case CALL(path=IDENT(name="pre"), expLst={arg}) then
7106 daeExpCallPre(arg, context, preExp, varDecls, varFrees, &auxFunction)
7107 // Clock builtins
7108 case CALL(path=IDENT(name="interval")) then
7109 'data->simulationInfo->baseClocks[baseClockIndex].subClocks[subClockIndex].stats.previousInterval'
7110 case CALL(path=IDENT(name="previous"), expLst={arg as CREF(__)}) then
7111 '<%cref(crefPrefixPrevious(arg.componentRef), &sub)%>'
7112 case CALL(path=IDENT(name="firstTick")) then
7113 '(data->simulationInfo->baseClocks[baseClockIndex].subClocks[subClockIndex].stats.count == 1)'
7114 case CALL(path=IDENT(name="$_clkfire"), expLst={arg as ICONST(__)}) then
7115 'handleBaseClock(data, threadData, <%intSub(arg.integer,1)%>, data->localData[0]->timeValue)'
7116
7117 // if arg >= 0 then 1 else -1
7118 case CALL(path=IDENT(name="$_signNoNull"), expLst={e1}) then
7119 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7120 '(<%var1%> >= 0.0 ? 1.0:-1.0)'
7121 // numerical der()
7122 case CALL(path=IDENT(name="$_DF$DER"), expLst={arg as CREF(__)}) then
7123 let derstr = cref(crefPrefixDer(arg.componentRef), &sub)
7124 let nameold0 = crefOld(arg.componentRef, 0)
7125 let nameold1 = crefOld(arg.componentRef, 1)
7126 let dt = 'data->simulationInfo->inlineData->dt'
7127 '(<%dt%> == 0.0 ? <%derstr%> : (<%nameold0%> - <%nameold1%>)/<%dt%>)'
7128 // round
7129 case CALL(path=IDENT(name="$_round"), expLst={e1}) then
7130 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7131 '((modelica_integer)round((modelica_real)(<%var1%>)))'
7132 case CALL(path=IDENT(name="edge"), expLst={arg as CREF(__)}) then
7133 '(<%cref(arg.componentRef, &sub)%> && !<%crefPre(arg.componentRef)%>)'
7134 case CALL(path=IDENT(name="edge"), expLst={LUNARY(exp = arg as CREF(__))}) then
7135 '(!<%cref(arg.componentRef, &sub)%> && <%crefPre(arg.componentRef)%>)'
7136 case CALL(path=IDENT(name="edge"), expLst={exp}) then
7137 error(sourceInfo(), 'Code generation does not support edge(<%ExpressionDumpTpl.dumpExp(exp,"\"")%>)')
7138 case CALL(path=IDENT(name="change"), expLst={arg as CREF(__)}) then
7139 '(<%cref(arg.componentRef, &sub)%> != <%crefPre(arg.componentRef)%>)'
7140 case CALL(path=IDENT(name="change"), expLst={exp}) then
7141 error(sourceInfo(), 'Code generation does not support change(<%ExpressionDumpTpl.dumpExp(exp,"\"")%>)')
7142 case CALL(path=IDENT(name="cardinality"), expLst={exp}) then
7143 error(sourceInfo(), 'Code generation does not support cardinality(<%ExpressionDumpTpl.dumpExp(exp,"\"")%>). It should have been handled somewhere else in the compiler.')
7144
7145 case CALL(path=IDENT(name="print"), expLst={e1}) then
7146 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7147 'fputs(omc_string_data(<%var1%>),stdout)'
7148
7149 case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then
7150 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7151 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7152 'fmax(<%var1%>,<%var2%>)'
7153
7154 case CALL(path=IDENT(name="max"), expLst={e1,e2}) then
7155 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7156 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7157 'modelica_integer_max((modelica_integer)(<%var1%>),(modelica_integer)(<%var2%>))'
7158
7159 case CALL(path=IDENT(name="sum"), attr=CALL_ATTR(ty = ty), expLst={e}) then
7160 let arr = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7161 let ty_str = '<%expTypeArray(ty)%>'
7162 'sum_<%ty_str%>(<%arr%>)'
7163
7164 case CALL(path=IDENT(name="product"), attr=CALL_ATTR(ty = ty), expLst={e}) then
7165 let arr = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7166 let ty_str = '<%expTypeArray(ty)%>'
7167 'product_<%ty_str%>(<%arr%>)'
7168
7169 case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = T_REAL(__)), expLst={e1,e2}) then
7170 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7171 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7172 'fmin(<%var1%>,<%var2%>)'
7173
7174 case CALL(path=IDENT(name="min"), expLst={e1,e2}) then
7175 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7176 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7177 'modelica_integer_min((modelica_integer)(<%var1%>),(modelica_integer)(<%var2%>))'
7178
7179 case CALL(path=IDENT(name="abs"), expLst={e1}, attr=CALL_ATTR(ty = T_INTEGER(__))) then
7180 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7181 'labs(<%var1%>)'
7182
7183 case CALL(path=IDENT(name="abs"), expLst={e1}) then
7184 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7185 'fabs(<%var1%>)'
7186
7187 case CALL(path=IDENT(name="sqrt"), expLst={e1}, attr=attr as CALL_ATTR(__)) then
7188 let argStr = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7189 (if isPositiveOrZero(e1)
7190 then
7191 'sqrt(<%argStr%>)'
7192 else
7193 let tmp = tempDecl(expTypeFromExpModelica(e1), &varDecls, &varFrees)
7194 let cstr = ExpressionDumpTpl.dumpExp(e1,"\"")
7195 let &preExp +=
7196 <<
7197 <%tmp%> = <%argStr%>;
7198 <%assertCommonVar('<%tmp%> >= 0.0', '"Model error: Argument of sqrt(<%Util.escapeModelicaStringToCString(cstr)%>) was %g should be >= 0", <%tmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7199 >>
7200 'sqrt(<%tmp%>)')
7201
7202 case CALL(path=IDENT(name="nthRoot"), expLst={e1, e2}, attr=attr as CALL_ATTR(__)) then
7203 let v = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7204 let n = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7205 let vtmp = tempDecl(expTypeFromExpModelica(e1), &varDecls, &varFrees)
7206 let ntmp = tempDecl(expTypeFromExpModelica(e2), &varDecls, &varFrees)
7207 let vstr = ExpressionDumpTpl.dumpExp(e1,"\"")
7208 let nstr = ExpressionDumpTpl.dumpExp(e2,"\"")
7209 let &preExp +=
7210 <<
7211 <%vtmp%> = <%v%>;
7212 <%ntmp%> = <%n%>;
7213 <%assertCommonVar('<%ntmp%> > 0.0', '"Model error: Second argument of nthRoot(<%Util.escapeModelicaStringToCString(vstr)%>, <%Util.escapeModelicaStringToCString(nstr)%>) must be > 0, got %d", <%ntmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7214 <%assertCommonVar('modelica_integer_mod(<%ntmp%>, 2) != 0 || <%vtmp%> >= 0.0', '"Model error: First argument of nthRoot(<%Util.escapeModelicaStringToCString(vstr)%>, <%Util.escapeModelicaStringToCString(nstr)%>) must be >= 0 if the second is even, got %g", <%vtmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7215 >>
7216 'copysign(pow(fabs(<%vtmp%>), 1.0/<%ntmp%>), <%vtmp%>)'
7217
7218 case CALL(path=IDENT(name="log"), expLst={e1}, attr=attr as CALL_ATTR(__)) then
7219 let argStr = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7220 let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls, &varFrees)
7221 let cstr = ExpressionDumpTpl.dumpExp(e1,"\"")
7222 let &preExp +=
7223 <<
7224 <%tmp%> = <%argStr%>;
7225 <%assertCommonVar('<%tmp%> > 0.0', '"Model error: Argument of log(<%Util.escapeModelicaStringToCString(cstr)%>) was %g should be > 0", <%tmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7226 >>
7227 'log(<%tmp%>)'
7228
7229 case CALL(path=IDENT(name="log10"), expLst={e1}, attr=attr as CALL_ATTR(__)) then
7230 let argStr = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7231 let tmp = tempDecl(expTypeFromExpModelica(e1),&varDecls, &varFrees)
7232 let cstr = ExpressionDumpTpl.dumpExp(e1,"\"")
7233 let &preExp +=
7234 <<
7235 <%tmp%> = <%argStr%>;
7236 <%assertCommonVar('<%tmp%> > 0.0','"Model error: Argument of log10(<%Util.escapeModelicaStringToCString(cstr)%>) was %g should be > 0", <%tmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7237 >>
7238 'log10(<%tmp%>)'
7239
7240 case CALL(path=IDENT(name="acos"), expLst={e1}, attr=attr as CALL_ATTR(__)) then
7241 let argStr = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7242 let tmp = tempDecl("modelica_real",&varDecls, &varFrees)
7243 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7244 let &preExp +=
7245 <<
7246 <%tmp%> = <%argStr%>;
7247 <%assertCommonVar('<%tmp%> >= -1.0 && <%tmp%> <= 1.0', '"Model error: Argument of <%Util.escapeModelicaStringToCString(cstr)%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7248 >>
7249 'acos(<%tmp%>)'
7250
7251 case CALL(path=IDENT(name="asin"), expLst={e1}, attr=attr as CALL_ATTR(__)) then
7252 let argStr = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7253 let tmp = tempDecl("modelica_real",&varDecls, &varFrees)
7254 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7255 let &preExp +=
7256 <<
7257 <%tmp%> = <%argStr%>;
7258 <%assertCommonVar('<%tmp%> >= -1.0 && <%tmp%> <= 1.0', '"Model error: Argument of <%Util.escapeModelicaStringToCString(cstr)%> outside the domain -1.0 <= %g <= 1.0", <%tmp%>', context, &varDecls, &varFrees, Absyn.dummyInfo)%>
7259 >>
7260 'asin(<%tmp%>)'
7261
7262 /* Begin code generation of event triggering math functions */
7263
7264 case CALL(path=IDENT(name="mod"), expLst={e1,e2, index}, attr=CALL_ATTR(ty = ty)) then
7265 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7266 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7267 let constIndex = daeExp(index, context, &preExp, &varDecls, &varFrees, &auxFunction)
7268 match context
7269 case ZEROCROSSINGS_CONTEXT(__) then
7270 '<%expTypeModelica(ty)%>_mod(<%var1%>, <%var2%>)'
7271 else
7272 '_event_mod_<%expTypeShort(ty)%>(<%var1%>, <%var2%>, <%constIndex%>, data, threadData)'
7273
7274 case CALL(path=IDENT(name="div"), expLst={e1,e2, index}, attr=CALL_ATTR(ty = ty)) then
7275 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7276 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7277 let constIndex = daeExp(index, context, &preExp, &varDecls, &varFrees, &auxFunction)
7278 match context
7279 case ZEROCROSSINGS_CONTEXT(__) then
7280 match ty
7281 case T_INTEGER(__) then
7282 'modelica_div_integer(<%var1%>,<%var2%>).quot'
7283 else
7284 'trunc((<%var1%>) / (<%var2%>))'
7285 else
7286 '_event_div_<%expTypeShort(ty)%>(<%var1%>, <%var2%>, <%constIndex%>, data, threadData)'
7287
7288 case CALL(path=IDENT(name="integer"), expLst={inExp,index}) then
7289 let exp = daeExp(inExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7290 let constIndex = daeExp(index, context, &preExp, &varDecls, &varFrees, &auxFunction)
7291 match context
7292 case ZEROCROSSINGS_CONTEXT(__) then
7293 '((modelica_integer)floor(<%exp%>))'
7294 else
7295 '(_event_integer(<%exp%>, <%constIndex%>, data))'
7296
7297 case CALL(path=IDENT(name="floor"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then
7298 let exp = daeExp(inExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7299 let constIndex = daeExp(index, context, &preExp, &varDecls, &varFrees, &auxFunction)
7300 match context
7301 case ZEROCROSSINGS_CONTEXT(__) then
7302 '((<%expTypeModelica(ty)%>)floor(<%exp%>))'
7303 else
7304 '((<%expTypeModelica(ty)%>)_event_floor(<%exp%>, <%constIndex%>, data))'
7305
7306 case CALL(path=IDENT(name="ceil"), expLst={inExp,index}, attr=CALL_ATTR(ty = ty)) then
7307 let exp = daeExp(inExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7308 let constIndex = daeExp(index, context, &preExp, &varDecls, &varFrees, &auxFunction)
7309 match context
7310 case ZEROCROSSINGS_CONTEXT(__) then
7311 '((<%expTypeModelica(ty)%>)ceil(<%exp%>))'
7312 else
7313 '((<%expTypeModelica(ty)%>)_event_ceil(<%exp%>, <%constIndex%>, data))'
7314
7315 /* end codegeneration of event triggering math functions */
7316
7317 case CALL(path=IDENT(name="integer"), expLst={inExp}) then
7318 let exp = daeExp(inExp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7319 '((modelica_integer)floor(<%exp%>))'
7320
7321 case CALL(path=IDENT(name="mod"), expLst={e1,e2}, attr=CALL_ATTR(ty=ty)) then
7322 let tp_str = expTypeModelica(ty)
7323 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7324 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7325 let tvar = if metaModelicaRuntime() then '<%var2%>' else tempDecl(tp_str, &varDecls, &varFrees)
7326 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7327 let &preExp += if metaModelicaRuntime() then "" else '<%tvar%> = <%var2%>;<%\n%><%errorCheck(context)%>'
7328 let &preExp +=
7329 if metaModelicaRuntime()
7330 then ""
7331 else 'if (<%tvar%> == 0) {raiseStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(cstr)%>"); <%errorCheck(context)%>}<%\n%>'
7332 '<%tp_str%>_mod(<%var1%>, <%tvar%>)'
7333
7334 case CALL(path=IDENT(name="mod"), expLst={e1,e2}) then
7335 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7336 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7337 let tvar = tempDecl("modelica_real", &varDecls, &varFrees)
7338 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7339 let &preExp += '<%tvar%> = <%var2%>;<%\n%><%errorCheck(context)%>'
7340 let &preExp +=
7341 if metaModelicaRuntime()
7342 then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>'
7343 else 'if (<%tvar%> == 0) {raiseStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(cstr)%>"); <%errorCheck(context)%>}<%\n%>'
7344 '((<%var1%>) - floor((<%var1%>) / (<%tvar%>)) * (<%tvar%>))'
7345
7346 case CALL(path=IDENT(name="div"), expLst={e1,e2}, attr=CALL_ATTR(ty = T_INTEGER(__))) then
7347 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7348 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7349 let tvar = tempDecl("modelica_integer", &varDecls, &varFrees)
7350 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7351 let &preExp += '<%tvar%> = <%var2%>;<%\n%><%errorCheck(context)%>'
7352 let &preExp +=
7353 if metaModelicaRuntime()
7354 then 'if (<%tvar%> == 0) {<%generateThrow()%>;}<%\n%>'
7355 else 'if (<%tvar%> == 0) {raiseStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(cstr)%>"); <%errorCheck(context)%>}<%\n%>'
7356 /* ldiv not available in opencl c*/
7357 if isParallelFunctionContext(context) then '(modelica_integer)((<%var1%>) / <%tvar%>)'
7358 else 'modelica_div_integer(<%var1%>,<%tvar%>).quot'
7359
7360 case CALL(path=IDENT(name="div"), expLst={e1,e2}) then
7361 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7362 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7363 let cstr = ExpressionDumpTpl.dumpExp(call,"\"")
7364 let tvar = tempDecl("modelica_real", &varDecls, &varFrees)
7365 let &preExp += '<%tvar%> = <%var2%>;<%\n%><%errorCheck(context)%>'
7366 let &preExp +=
7367 if metaModelicaRuntime()
7368 then 'if (<%tvar%> == 0.0) {<%generateThrow()%>;}<%\n%>'
7369 else 'if (<%tvar%> == 0.0) {raiseStreamPrint(threadData, "Division by zero %s", "<%Util.escapeModelicaStringToCString(cstr)%>"); <%errorCheck(context)%>}<%\n%>'
7370 'trunc((<%var1%>) / (<%tvar%>))'
7371
7372 case CALL(path=IDENT(name="mod"), expLst={e1,e2}, attr=CALL_ATTR(ty = ty)) then
7373 let var1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7374 let var2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7375 'modelica_mod_<%expTypeShort(ty)%>(<%var1%>,<%var2%>)'
7376
7377 case CALL(path=IDENT(name="max"), attr=CALL_ATTR(ty = ty), expLst={array}) then
7378 let expVar = daeExp(array, context, &preExp, &varDecls, &varFrees, &auxFunction)
7379 let arr_tp_str = expTypeArray(ty)
7380 let tvar = tempDecl(expTypeModelica(ty), &varDecls, &varFrees)
7381 let &preExp += '<%tvar%> = max_<%arr_tp_str%>(<%expVar%>);<%\n%>'
7382 tvar
7383
7384 case CALL(path=IDENT(name="argmin"), expLst={array}) then
7385 let expVar = daeExp(array, context, &preExp, &varDecls, &varFrees, &auxFunction)
7386 let tvar = tempDecl("modelica_integer", &varDecls, &varFrees)
7387 let &preExp += '<%tvar%> = argmin_real_array(<%expVar%>);<%\n%>'
7388 tvar
7389
7390 case CALL(path=IDENT(name="argmax"), expLst={array}) then
7391 let expVar = daeExp(array, context, &preExp, &varDecls, &varFrees, &auxFunction)
7392 let tvar = tempDecl("modelica_integer", &varDecls, &varFrees)
7393 let &preExp += '<%tvar%> = argmax_real_array(<%expVar%>);<%\n%>'
7394 tvar
7395
7396 case CALL(path=IDENT(name="min"), attr=CALL_ATTR(ty = ty), expLst={array}) then
7397 let expVar = daeExp(array, context, &preExp, &varDecls, &varFrees, &auxFunction)
7398 let arr_tp_str = expTypeArray(ty)
7399 let tvar = tempDecl(expTypeModelica(ty), &varDecls, &varFrees)
7400 let &preExp += '<%tvar%> = min_<%arr_tp_str%>(<%expVar%>);<%\n%>'
7401 tvar
7402
7403 case CALL(path=IDENT(name="fill"), expLst=val::dims, attr=CALL_ATTR(ty = ty)) then
7404 let valExp = daeExpAsLValue(val, context, &preExp, &varDecls, &varFrees, &auxFunction)
7405 let dimsExp = (dims |> dim =>
7406 daeExp(dim, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
7407 let ty_str = expTypeArray(ty)
7408 let tvar = tempDecl(ty_str, &varDecls, &varFrees)
7409 let &preExp += '<%rcReleaseBefore(ty_str, tvar)%>fill_alloc_<%ty_str%>(&<%tvar%>, <%valExp%>, <%listLength(dims)%>, <%dimsExp%>);<%\n%>'
7410 tvar
7411
7412 case call as CALL(path=IDENT(name="vector"), expLst={exp}, attr=CALL_ATTR(ty=ty)) then
7413 let ndim = listLength(getDimensionSizes(Expression.typeof(exp)))
7414 let tvarc = tempDecl("modelica_integer", &varDecls, &varFrees)
7415 let tvardata = tempDecl("void *", &varDecls, &varFrees)
7416 let nElts = tempDecl("modelica_integer", &varDecls, &varFrees)
7417 let val = daeExpAsLValue(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7418 let szElt = 'sizeof(<%expTypeModelica(ty)%>)'
7419 let dims =
7420 (getDimensionSizes(Expression.typeof(exp)) |> sz hasindex ix fromindex 1 =>
7421 (match sz
7422 case 0 then 'if (size_of_dimension_base_array(<%val%>, <%ix%>)>1) <%tvarc%>++;<%\n%>'
7423 case 1 then ""
7424 else '<%tvarc%>++;<%\n%>')
7425 ; empty)
7426 let ty_str = expTypeArray(ty)
7427 let tvar = tempDecl(ty_str, &varDecls, &varFrees)
7428 let &preExp += // Why does not Susan allow me to use << here?
7429 <<
7430 <%tvarc%>=0;
7431 <%dims%>if (<%tvarc%> > 1) {
7432 <%raiseOrThrow()%>(threadData, "Called vector with >1 dimensions with size >1: <%Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp,"\""))%>");
7433 }
7434 <%nElts%> = base_array_nr_of_elements(<%val%>);
7435 <%tvardata%> = omc_alloc_interface.malloc(<%szElt%>*<%nElts%>);
7436 memcpy(<%tvardata%>, <%val%>.data, <%szElt%>*<%nElts%>);
7437 simple_alloc_1d_base_array(&<%tvar%>, <%nElts%>, <%tvardata%>);
7438 >>
7439 tvar
7440
7441 case CALL(path=IDENT(name="cat"), expLst=dim::arrays, attr=CALL_ATTR(ty = ty)) then
7442 let dim_exp = daeExp(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)
7443 let arrays_exp = (arrays |> array =>
7444 daeExpAsLValue(array, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", &")
7445 let ty_str = expTypeArray(ty)
7446 let tvar = tempDecl(ty_str, &varDecls, &varFrees)
7447 let &preExp += '<%rcReleaseBefore(ty_str, tvar)%>cat_alloc_<%ty_str%>(<%dim_exp%>, &<%tvar%>, <%listLength(arrays)%>, &<%arrays_exp%>);<%\n%>'
7448 tvar
7449
7450 case CALL(path=IDENT(name="promote"), expLst={A, n}) then
7451 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7452 let var2 = daeExp(n, context, &preExp, &varDecls, &varFrees, &auxFunction)
7453 let arr_tp_str = '<%expTypeFromExpArray(A)%>'
7454 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7455 /* Runtime gets number of dimensions to promote; Modelica has the total number of dimensions that the promoted result should have */
7456 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>promote_alloc_<%arr_tp_str%>(&<%var1%>, <%var2%> - ndims_base_array(&<%var1%>), &<%tvar%>);<%\n%>'
7457 tvar
7458
7459 case CALL(path=IDENT(name="transpose"), expLst={A}) then
7460 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7461 let arr_tp_str = '<%expTypeFromExpArray(A)%>'
7462 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7463 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>transpose_alloc_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>'
7464 tvar
7465
7466 case CALL(path=IDENT(name="symmetric"), expLst={A}) then
7467 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7468 let arr_tp_str = '<%expTypeFromExpArray(A)%>'
7469 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7470 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>symmetric_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>'
7471 tvar
7472
7473 case CALL(path=IDENT(name="skew"), expLst={A}) then
7474 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7475 let arr_tp_str = '<%expTypeFromExpArray(A)%>'
7476 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7477 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>skew_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>'
7478 tvar
7479
7480 case CALL(path=IDENT(name="cross"), expLst={v1, v2}) then
7481 let var1 = daeExpAsLValue(v1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7482 let var2 = daeExpAsLValue(v2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7483 let arr_tp_str = expTypeFromExpArray(v1)
7484 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7485 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>cross_alloc_<%arr_tp_str%>(&<%var1%>, &<%var2%>, &<%tvar%>);<%\n%>'
7486 tvar
7487
7488 case CALL(path=IDENT(name="identity"), expLst={A}) then
7489 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7490 let arr_tp_str = expTypeFromExpArray(A)
7491 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7492 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>identity_alloc_<%arr_tp_str%>(<%var1%>, &<%tvar%>);<%\n%>'
7493 tvar
7494
7495 case CALL(path=IDENT(name="diagonal"), expLst={A}) then
7496 let var1 = daeExpAsLValue(A, context, &preExp, &varDecls, &varFrees, &auxFunction)
7497 let arr_tp_str = expTypeFromExpArray(A)
7498 let tvar = tempDecl(arr_tp_str, &varDecls, &varFrees)
7499 let &preExp += '<%rcReleaseBefore(arr_tp_str, tvar)%>diagonal_alloc_<%arr_tp_str%>(&<%var1%>, &<%tvar%>);<%\n%>'
7500 tvar
7501
7502 case CALL(path=IDENT(name="String"), expLst={s, format}) then
7503 let tvar = tempDecl("modelica_string", &varDecls, &varFrees)
7504 let sExp = daeExp(s, context, &preExp, &varDecls, &varFrees, &auxFunction)
7505
7506 let formatExp = daeExp(format, context, &preExp, &varDecls, &varFrees, &auxFunction)
7507 let typeStr = expTypeFromExpModelica(s)
7508 let &preExp += '<%rcReleaseBefore("modelica_string", tvar)%><%tvar%> = <%typeStr%>_to_modelica_string_format(<%sExp%>, <%formatExp%>);<%\n%>'
7509 tvar
7510
7511 case CALL(path=IDENT(name="String"), expLst={s, minlen, leftjust}) then
7512 let tvar = tempDecl("modelica_string", &varDecls, &varFrees)
7513 let sExp = daeExp(s, context, &preExp, &varDecls, &varFrees, &auxFunction)
7514 let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &varFrees, &auxFunction)
7515 let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &varFrees, &auxFunction)
7516 let enumStr = (match typeof(s)
7517 case T_ENUMERATION(__) then
7518 let strs = names |> s => '"<%Util.escapeModelicaStringToCString(s)%>"' ; separator = ", "
7519 ', <%tempDeclArray("const char*", listLength(names), strs, &varDecls, &varFrees)%>')
7520 let typeStr = (if enumStr then "enum" else expTypeFromExpModelica(s))
7521 match typeStr
7522 case "modelica_real" then
7523 let &preExp += '<%rcReleaseBefore("modelica_string", tvar)%><%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, 6);<%\n%>'
7524 tvar
7525 case "modelica_string" then
7526 let &preExp += 'omc_string_store(&<%tvar%>, <%sExp%>);<%\n%>'
7527 tvar
7528 else
7529 let &preExp += '<%rcReleaseBefore("modelica_string", tvar)%><%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%><%enumStr%>, <%minlenExp%>, <%leftjustExp%>);<%\n%>'
7530 tvar
7531 end match
7532
7533 case CALL(path=IDENT(name="String"), expLst={s, signdig, minlen, leftjust}) then
7534 let tvar = tempDecl("modelica_string", &varDecls, &varFrees)
7535 let sExp = daeExp(s, context, &preExp, &varDecls, &varFrees, &auxFunction)
7536 let minlenExp = daeExp(minlen, context, &preExp, &varDecls, &varFrees, &auxFunction)
7537 let leftjustExp = daeExp(leftjust, context, &preExp, &varDecls, &varFrees, &auxFunction)
7538 let signdigExp = daeExp(signdig, context, &preExp, &varDecls, &varFrees, &auxFunction)
7539 let &preExp += '<%rcReleaseBefore("modelica_string", tvar)%><%tvar%> = modelica_real_to_modelica_string(<%sExp%>, <%signdigExp%>, <%minlenExp%>, <%leftjustExp%>);<%\n%>'
7540 tvar
7541
7542 case CALL(path=IDENT(name="delay"), expLst={ICONST(integer=index), e, d, delayMax}) then
7543 let tvar = tempDecl("modelica_real", &varDecls, &varFrees)
7544
7545 let var1 = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7546 let var2 = daeExp(d, context, &preExp, &varDecls, &varFrees, &auxFunction)
7547 let var3 = daeExp(delayMax, context, &preExp, &varDecls, &varFrees, &auxFunction)
7548 let &preExp += '<%tvar%> = delayImpl(data, threadData, <%index%>, <%var1%>, <%var2%>, <%var3%>);<%\n%>'
7549 tvar
7550
7551 case CALL(path=IDENT(name="spatialDistribution"), expLst={ICONST(integer=index), in0, in1, posX, posVelo}) then
7552 let tvar = tempDecl("modelica_real", &varDecls, &varFrees)
7553
7554 let var1 = daeExp(in0, context, &preExp, &varDecls, &varFrees, &auxFunction)
7555 let var2 = daeExp(in1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7556 let var3 = daeExp(posX, context, &preExp, &varDecls, &varFrees, &auxFunction)
7557 let var4 = daeExp(posVelo, context, &preExp, &varDecls, &varFrees, &auxFunction)
7558 let &preExp += '<%tvar%> = spatialDistribution(data, threadData, <%index%>, <%var1%>, <%var2%>, <%var3%>, <%var4%>);<%\n%>'
7559 tvar
7560
7561 case CALL(path=IDENT(name="Integer"), expLst={toBeCasted}) then
7562 let castedVar = daeExp(toBeCasted, context, &preExp, &varDecls, &varFrees, &auxFunction)
7563 '((modelica_integer)(<%castedVar%>))'
7564
7565 case CALL(path=IDENT(name="clock"), expLst={}) then
7566 'mmc_clock()'
7567
7568 case CALL(path=IDENT(name="noEvent"), expLst={e1}) then
7569 daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7570
7571 case CALL(path=IDENT(name="$getPart"), expLst={e1}) then
7572 daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7573
7574 case CALL(path=IDENT(name="$stateSelectionSet"), expLst=ICONST(integer=setIndex)::_) then
7575 'stateSelectionSet(data, threadData, 1, 1, <%setIndex%>, 0)'
7576
7577 case CALL(path=IDENT(name="$initialStateSelection"), expLst=ICONST(integer=setIndex)::_) then
7578 'initialStateSelection(data, threadData, 1, 1, <%setIndex%>, 0)'
7579
7580 case CALL(path=IDENT(name="sample"), expLst={ICONST(integer=index), _, _}) then
7581 'data->simulationInfo->samples[<%intSub(index, 1)%>]'
7582
7583 case CALL(path=IDENT(name="delayZeroCrossing"), expLst={ICONST(integer=index), ICONST(integer=rindex), delay}) then
7584 let delay_T = daeExp(delay, context, &preExp, &varDecls, &varFrees, &auxFunction)
7585 'delayZeroCrossing(data, threadData, <%index%>, <%rindex%>, <%delay_T%>)'
7586
7587 case CALL(path=IDENT(name="spatialDistributionZeroCrossing"), expLst={ICONST(integer=index), ICONST(integer=rindex), xPos, dir}) then
7588 let xPos_T = daeExp(xPos, context, &preExp, &varDecls, &varFrees, &auxFunction)
7589 let dir_T = daeExp(dir, context, &preExp, &varDecls, &varFrees, &auxFunction)
7590 'spatialDistributionZeroCrossing(data, threadData, <%index%>, <%rindex%>, <%xPos_T%>, <%dir_T%>)'
7591
7592 case CALL(path=IDENT(name="anyString"), expLst={e1}) then
7593 'mmc_anyString(<%daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)%>)'
7594
7595 case CALL(path=IDENT(name="fail"), attr = CALL_ATTR(builtin = true)) then
7596 '<%generateThrow()%>'
7597
7598 case CALL(path=IDENT(name="mmc_get_field"), expLst={s1, ICONST(integer=i)}) then
7599 let tvar = tempDecl("modelica_metatype", &varDecls, &varFrees)
7600 let expPart = daeExp(s1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7601 let &preExp += '<%tvar%> = OMC_BOX_FIELD(<%expPart%>, <%i%>);<%\n%>'
7602 tvar
7603
7604 case CALL(path=IDENT(name = "mmc_unbox_record"), expLst={s1}, attr=CALL_ATTR(ty=ty)) then
7605 let argStr = daeExp(s1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7606 unboxRecord(argStr, ty, &preExp, &varDecls, &varFrees)
7607
7608 case CALL(path=IDENT(name = "threadData")) then
7609 "threadData"
7610
7611 case CALL(path=IDENT(name = "intBitNot"),expLst={e}) then
7612 let e1 = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7613 '(~<%e1%>)'
7614
7615 case CALL(path=IDENT(name = name as "intBitNot"),expLst={e1,e2})
7616 case CALL(path=IDENT(name = name as "intBitAnd"),expLst={e1,e2})
7617 case CALL(path=IDENT(name = name as "intBitOr"),expLst={e1,e2})
7618 case CALL(path=IDENT(name = name as "intBitXor"),expLst={e1,e2})
7619 case CALL(path=IDENT(name = name as "intBitLShift"),expLst={e1,e2})
7620 case CALL(path=IDENT(name = name as "intBitRShift"),expLst={e1,e2}) then
7621 let i1 = daeExp(e1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7622 let i2 = daeExp(e2, context, &preExp, &varDecls, &varFrees, &auxFunction)
7623 let op = (match name
7624 case "intBitAnd" then "&"
7625 case "intBitOr" then "|"
7626 case "intBitXor" then "^"
7627 case "intBitLShift" then "<<"
7628 case "intBitRShift" then ">>")
7629 '((<%i1%>) <%op%> (<%i2%>))'
7630
7631 case exp as CALL(attr=attr as CALL_ATTR(tailCall=tail as TAIL(__))) then
7632 let &postExp = buffer ""
7633 let tail = daeExpTailCall(expLst, tail.vars, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)
7634 let res = <<
7635 /* Tail recursive call */
7636 <%tail%><%&postExp%>goto _tailrecursive;
7637 /* TODO: Make sure any eventual dead code below is never generated */
7638 >>
7639 let &preExp += res
7640 ""
7641
7642 case exp as CALL(attr=attr as CALL_ATTR(__)) then
7643 let additionalOutputs = (match attr.ty case T_TUPLE(types=t::ts) then List.fill(", NULL",listLength(ts)))
7644 let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &varFrees, &auxFunction)
7645 match context
7646 case FUNCTION_CONTEXT(is_parallel = true) then res
7647 case FUNCTION_CONTEXT(__) then
7648 // Check each call, not only the statement: the next call would read what
7649 // a failed one left behind. MetaModelica throws instead.
7650 if metaModelicaRuntime() then res
7651 else if attr.builtin then res
7652 else callSpillAndCheck(res, attr.ty, context, &preExp, &varDecls, &varFrees)
7653 else
7654 if boolAnd(profileFunctions(),boolNot(attr.builtin)) then
7655 let funName = underscorePath(exp.path)
7656 let &tvarTy = buffer ""
7657 let tvar = (match attr.ty
7658 case T_NORETCALL(__) then ""
7659 case T_TUPLE(types=t::_)
7660 case t then
7661 let &tvarTy += expTypeArrayIf(t)
7662 let tvar2 = tempDecl(expTypeArrayIf(t),&varDecls, &varFrees)
7663 let &preExp += '<%rcReleaseBefore(expTypeArrayIf(t), tvar2)%>'
7664 let &preExp += if isArrayType(t) then '<%tvar2%>.dim_size = 0;<%\n%>'
7665 tvar2
7666 )
7667 let &preExp += 'SIM_PROF_TICK_FN(<%funName%>_index);<%\n%>'
7668 let &preExp += if tvar then '<%tvar%> = <%res%>;<%\n%><%rcRetain(tvarTy, tvar)%>' else '<%res%>;<%\n%>'
7669 let &preExp += 'SIM_PROF_ACC_FN(<%funName%>_index);<%\n%>'
7670 let &preExp += errorCheck(context)
7671 tvar
7672 else if attr.builtin then res
7673 else callSpillAndCheck(res, attr.ty, context, &preExp, &varDecls, &varFrees)
7674 end daeExpCall;
7675
7676 22795 template callSpillAndCheck(Text res, Type ty, Context context, Text &preExp, Text &varDecls, Text &varFrees)
7677 "A call that raised has no result, and the rest of the statement would read
7678 one. A counted result already sits in a temporary that daeExpCallTuple
7679 checked, and a noretcall leaves nothing to read."
7680 ::=
7681 match rcCallResultType(ty)
7682 case "" then
7683 (match ty
7684 case T_NORETCALL(__) then res
7685 case T_TUPLE(types=t::_)
7686 case t then
7687 if deviceCallResult() then res
7688 else
7689 let tvar = tempDecl(expTypeArrayIf(t), &varDecls, &varFrees)
7690 let &preExp += '<%tvar%> = <%res%>;<%\n%><%errorCheck(context)%>'
7691 tvar)
7692 else res
7693 end callSpillAndCheck;
7694
7695 45152 template daeExpCallTuple(Exp call, Text additionalOutputs /* arguments 2..N */, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7696 ::=
7697 match call
7698
7699 case CALL(path=IDENT(name="spatialDistribution"), expLst={ICONST(integer=index), in0, in1, posX, dir, _, _}) then
7700 let tvar = tempDecl("modelica_real", &varDecls, &varFrees)
7701
7702 let var1 = daeExp(in0, context, &preExp, &varDecls, &varFrees, &auxFunction)
7703 let var2 = daeExp(in1, context, &preExp, &varDecls, &varFrees, &auxFunction)
7704 let var3 = daeExp(posX, context, &preExp, &varDecls, &varFrees, &auxFunction)
7705 let var4 = daeExp(dir, context, &preExp, &varDecls, &varFrees, &auxFunction)
7706 let &preExp += '<%tvar%> = spatialDistribution(data, threadData, <%index%> /* index */, <%var1%>, <%var2%>, <%var3%>, <%var4%><%additionalOutputs%>);<%\n%>'
7707 tvar
7708
7709 case exp as CALL(attr=attr as CALL_ATTR(isFunctionPointerCall=true)) then
7710 daeExpCallFunctionReference(exp, additionalOutputs, context, &preExp, &varDecls, &varFrees, &auxFunction)
7711
7712 case exp as CALL(attr=attr as CALL_ATTR(__)) then
7713 let argStr = if boolOr(attr.builtin,isParallelFunctionContext(context))
7714 then (expLst |> exp => '<%daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)%>' ;separator=", ")
7715 else ("threadData" + (expLst |> exp => (", " + daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction))))
7716 let name = '<% if attr.builtin then "" else "omc_" %><%underscorePath(path)%>'
7717 rcCallResult('<%name%>(<%argStr%><%additionalOutputs%>)', attr.ty, context, &preExp, &varDecls, &varFrees)
7718 end daeExpCallTuple;
7719
7720 45216 template rcCallResult(Text callTxt, Type ty, Context context, Text &preExp, Text &varDecls, Text &varFrees)
7721 "A counted result comes back holding a reference the caller owns; as an
7722 rvalue nothing would release it, so track it in a temporary."
7723 ::=
7724 let resTy = if deviceCallResult() then "" else rcCallResultType(ty)
7725 match resTy
7726 case "" then callTxt
7727 case tvarTy then
7728 let tvar = tempDecl(tvarTy, &varDecls, &varFrees)
7729 let &preExp += '<%rcReleaseBefore(tvarTy, tvar)%><%tvar%> = <%callTxt%>;<%\n%>'
7730 let &preExp += errorCheck(context)
7731 tvar
7732 end rcCallResult;
7733
7734 230 template daeExpCallFunctionReference(Exp call, Text additionalOutputs, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7735 "A call through a function value. A closure takes its environment first."
7736 ::=
7737 match call
7738 case CALL(attr=attr as CALL_ATTR(__)) then
7739 let &sub = buffer ""
7740 let n = match path
7741 case IDENT(__) then contextCref(makeUntypedCrefIdent(name), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
7742 else error(sourceInfo(), 'We only support function pointer calls where the pointer is a local variable (not inside any record). Got: <%underscorePath(path)%>')
7743 let func = '(OMC_BOX_FIELD(<%n%>, 1))'
7744 let closure = '(OMC_BOX_FIELD(<%n%>, 2))'
7745 let args = (expLst |> exp => ", " + daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction))
7746 if unboxedFunctionReferences() then
7747 let ret = functionReferenceReturnType(attr.ty)
7748 let tys = (expLst |> e => ', <%expTypeFromExpArrayIf(e)%>') + functionReferenceOutputTypes(attr.ty)
7749 let callTxt = '(<%closure%> ? ((<%ret%>(*)(threadData_t*, void*<%tys%>)) <%func%>)(threadData, <%closure%><%args%><%additionalOutputs%>) : ((<%ret%>(*)(threadData_t*<%tys%>)) <%func%>)(threadData<%args%><%additionalOutputs%>))'
7750 rcCallResult(callTxt, attr.ty, context, &preExp, &varDecls, &varFrees)
7751 else
7752 let typeCast1 = generateTypeCast(attr.ty, expLst, true)
7753 let typeCast2 = generateTypeCast(attr.ty, expLst, false)
7754 '<%closure%> ? (<%typeCast1%> <%func%>) (threadData, <%closure%><%args%><%additionalOutputs%>) : (<%typeCast2%> <%func%>) (threadData<%args%><%additionalOutputs%>)'
7755 end daeExpCallFunctionReference;
7756
7757 12867 template unboxedFunctionReferences()
7758 "See SimCodeCodegenUtil.unboxFunctionReferenceCall."
7759 ::= if Config.acceptMetaModelicaGrammar() then "" else "x"
7760 end unboxedFunctionReferences;
7761
7762 215 template functionReferenceReturnType(Type ty)
7763 ::=
7764 match ty
7765 case T_NORETCALL(__) then "void"
7766 case T_TUPLE(types=t::_) then expTypeArrayIf(t)
7767 else expTypeArrayIf(ty)
7768 end functionReferenceReturnType;
7769
7770 ✗ template functionReferenceOutputTypes(Type ty)
7771 "The outputs after the first are written through pointers."
7772 ::=
7773 match ty
7774 case T_TUPLE(types=_::tys) then (tys |> t => ', <%expTypeArrayIf(t)%>*')
7775 end functionReferenceOutputTypes;
7776
7777 332 template generateTypeCast(Type ty, list<DAE.Exp> es, Boolean isClosure)
7778 ::=
7779 let ret = (match ty
7780 case T_NORETCALL(__) then "void"
7781 else "modelica_metatype")
7782 let inputs = es |> e => ', <%expTypeFromExpArrayIf(e)%>'
7783 let outputs = match ty
7784 case T_TUPLE(types=_::tys) then (tys |> t => ', <%expTypeArrayIf(t)%>')
7785 '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))<%if boolAnd(boolNot(isClosure), Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)) then "*(void**)"%>'
7786 end generateTypeCast;
7787
7788 8 template generateTypeCastFromType(Type ty, Boolean isClosure)
7789 ::=
7790 let ret = (match ty
7791 case T_FUNCTION(funcResultType=T_NORETCALL(__)) then "void"
7792 else "modelica_metatype")
7793 let inputs = match ty
7794 case T_FUNCTION(__) then
7795 (funcArg |> fa as FUNCARG(__) => ', <%expTypeArrayIf(fa.ty)%>')
7796 let outputs = match ty
7797 case T_FUNCTION(funcResultType=T_TUPLE(types=_::tys)) then (tys |> t => ', <%expTypeArrayIf(t)%>')
7798 '(<%ret%>(*)(threadData_t*<%if isClosure then ", modelica_metatype"%><%inputs%><%outputs%>))<%if boolAnd(boolNot(isClosure), Flags.isSet(Flags.OMC_RELOCATABLE_FUNCTIONS)) then "*(void**)"%>'
7799 end generateTypeCastFromType;
7800
7801 499 template daeExpTailCall(list<DAE.Exp> es, list<String> vs, Context context, Text &preExp, Text &postExp, Text &varDecls, Text &varFrees, Text &auxFunction)
7802 ::=
7803 match es
7804 case e::erest then
7805 match vs
7806 case v::vrest then
7807 let exp = daeExp(e,context,&preExp,&varDecls, &varFrees, &auxFunction)
7808 match e
7809 case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then
7810 // adrpo: ignore _x = _x!
7811 if stringEq(v, CodegenUtil.crefStr(cr))
7812 then '<%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)%>'
7813 else '_<%System.unquoteIdentifier(v)%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)%>'
7814 case _ then
7815 (if anyExpHasCrefName(erest, v) then
7816 /* We might overwrite a value with something else, so make an extra copy of it */
7817 let tmp = tempDecl(expTypeFromExpModelica(e),&varDecls, &varFrees)
7818 let &postExp += '_<%System.unquoteIdentifier(v)%> = <%tmp%>;<%\n%>'
7819 '<%tmp%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)%>'
7820 else
7821 let restText = daeExpTailCall(erest, vrest, context, &preExp, &postExp, &varDecls, &varFrees, &auxFunction)
7822 let v2 = '_<%System.unquoteIdentifier(v)%>'
7823 if stringEq(v2, exp)
7824 then restText
7825 else '<%v2%> = <%exp%>;<%\n%><%restText%>')
7826 end daeExpTailCall;
7827
7828 3655 template daeExpArray(Exp exp, Context context, Text &preExp,
7829 Text &varDecls, Text &varFrees, Text &auxFunction)
7830 "Generates code for an array expression."
7831 ::=
7832 match exp
7833 case ARRAY(array = array, scalar = scalar, ty = T_ARRAY(ty = t as T_COMPLEX(__))) then
7834 let arrayTypeStr = expTypeArray(ty)
7835 let arrayVar = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7836 let rec_name = expTypeShort(t)
7837 let &preExp += '<%rcReleaseBefore(arrayTypeStr, arrayVar)%>alloc_<%rec_name%>_array(&<%arrayVar%>, 1, (_index_t)<%listLength(array)%>);<%\n%>'
7838 let params = (array |> e hasindex i1 fromindex 1 =>
7839 let prefix = if scalar then '' else error(sourceInfo(), 'what is this suppsoed to do?')
7840 let src = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7841 let elem = '<%rec_name%>_array_get(<%arrayVar%>, 1, <%i1%>)'
7842 <<
7843 <%elem%> = <%src%>;
7844 <%rcRetain(rec_name, elem)%>
7845 >>
7846 ;separator="\n")
7847 let &preExp += '<%params%><%\n%>'
7848 arrayVar
7849 case ARRAY(array={}) then
7850 let arrayVar = tempDecl("base_array_t", &varDecls, &varFrees)
7851 let &preExp += '<%rcReleaseBefore("base_array_t", arrayVar)%>simple_alloc_1d_base_array(&<%arrayVar%>, 0, NULL);<%\n%>'
7852 arrayVar
7853 case ARRAY(__) then
7854 let arrayTypeStr = expTypeArray(ty)
7855 let arrayVar = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7856 let scalarPrefix = if scalar then "scalar_" else ""
7857 let scalarRef = if scalar then "&" else ""
7858 let params = (array |> e =>
7859 let prefix = if scalar then '(<%expTypeFromExpModelica(e)%>)' else ""
7860 '<%prefix%><%daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)%>'
7861 ;separator=", ")
7862 let &preExp += '<%rcReleaseBefore(arrayTypeStr, arrayVar)%>array_alloc_<%scalarPrefix%><%arrayTypeStr%>(&<%arrayVar%>, <%listLength(array)%><%if params then ", "%><%params%>);<%\n%>'
7863 arrayVar
7864 end daeExpArray;
7865
7866
7867 37 template daeExpMatrix(Exp exp, Context context, Text &preExp,
7868 Text &varDecls, Text &varFrees, Text &auxFunction)
7869 "Generates code for a matrix expression."
7870 ::=
7871 match exp
7872 case MATRIX(matrix={{}}) // special case for empty matrix: create dimensional array Real[0,1]
7873 case MATRIX(matrix={}) // special case for empty array: create dimensional array Real[0,1]
7874 then
7875 let arrayTypeStr = expTypeArray(ty)
7876 let tmp = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7877 let &preExp += 'alloc_<%arrayTypeStr%>(&<%tmp%>, 2, (_index_t)0, (_index_t)1);<%\n%>'
7878 tmp
7879 case m as MATRIX(__) then
7880 let typeStr = expTypeShort(m.ty)
7881 let arrayTypeStr = expTypeArray(m.ty)
7882 match typeStr
7883 // faster creation of the matrix for basic types
7884 case "real"
7885 case "integer"
7886 case "boolean" then
7887 let tmp = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7888 let rows = '<%listLength(m.matrix)%>'
7889 let cols = '<%listLength(listGet(m.matrix, 1))%>'
7890 let matrix = (m.matrix |> row hasindex i0 =>
7891 let els = (row |> e hasindex j0 =>
7892 let expVar = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7893 'put_<%typeStr%>_matrix_element(<%expVar%>, <%i0%>, <%j0%>, &<%tmp%>);' ;separator="\n")
7894 '<%els%>'
7895 ;separator="\n")
7896 let &preExp += '/* -- start: matrix[<%rows%>,<%cols%>] -- */<%\n%>'
7897 let &preExp += 'alloc_<%typeStr%>_array(&<%tmp%>, 2, (_index_t)<%rows%>, (_index_t)<%cols%>);<%\n%>'
7898 let &preExp += '<%matrix%><%\n%>'
7899 let &preExp += '/* -- end: matrix[<%rows%>,<%cols%>] -- */<%\n%>'
7900 tmp
7901 // everything else
7902 case _ then
7903 let &vars2 = buffer ""
7904 let &promote = buffer ""
7905 let catAlloc = (m.matrix |> row =>
7906 let tmp = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7907 let vars = daeExpMatrixRow(row, arrayTypeStr, context,
7908 &promote, &varDecls, &varFrees, &auxFunction)
7909 let &vars2 += ', &<%tmp%>'
7910 'cat_alloc_<%arrayTypeStr%>(2, &<%tmp%>, <%listLength(row)%><%vars%>);'
7911 ;separator="\n")
7912 let &preExp += promote
7913 let &preExp += catAlloc
7914 let &preExp += "\n"
7915 let tmp = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7916 let &preExp += 'cat_alloc_<%arrayTypeStr%>(1, &<%tmp%>, <%listLength(m.matrix)%><%vars2%>);<%\n%>'
7917 tmp
7918 end daeExpMatrix;
7919
7920
7921 ✗ template daeExpMatrixRow(list<Exp> row, String arrayTypeStr,
7922 Context context, Text &preExp,
7923 Text &varDecls, Text &varFrees, Text &auxFunction)
7924 "Helper to daeExpMatrix."
7925 ::=
7926 let &varLstStr = buffer ""
7927
7928 let preExp2 = (row |> e =>
7929 let expVar = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
7930 let tmp = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7931 let &varLstStr += ', &<%tmp%>'
7932 'promote_scalar_<%arrayTypeStr%>(<%expVar%>, 2, &<%tmp%>);'
7933 ;separator="\n")
7934 let &preExp2 += "\n"
7935 let &preExp += preExp2
7936 varLstStr
7937 end daeExpMatrixRow;
7938
7939 46 template daeExpRange(Exp exp, Context context, Text &preExp,
7940 Text &varDecls, Text &varFrees, Text &auxFunction)
7941 "Generates code for a range expression."
7942 ::=
7943 match exp
7944 case RANGE(__) then
7945 let ty_str = expTypeArray(ty)
7946 let start_exp = daeExp(start, context, &preExp, &varDecls, &varFrees, &auxFunction)
7947 let stop_exp = daeExp(stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
7948 let tmp = tempDecl(ty_str, &varDecls, &varFrees)
7949 let step_exp = match step case SOME(stepExp) then daeExp(stepExp, context, &preExp, &varDecls, &varFrees, &auxFunction) else "1"
7950 let &preExp += '<%rcReleaseBefore(ty_str, tmp)%>create_<%ty_str%>_from_range(&<%tmp%>, <%start_exp%>, <%step_exp%>, <%stop_exp%>);<%\n%>'
7951 '<%tmp%>'
7952 end daeExpRange;
7953
7954 3661 template daeExpCast(Exp exp, Context context, Text &preExp,
7955 Text &varDecls, Text &varFrees, Text &auxFunction)
7956 "Generates code for a cast expression."
7957 ::=
7958 match exp
7959 case CAST(__) then
7960 let expVar = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
7961 match ty
7962 case T_INTEGER(__)
7963 case T_REAL(__)
7964 case T_ENUMERATION(__)
7965 case T_BOOL(__) then
7966 '(<%typeCastContext(context, ty)%><%expVar%>)'
7967 case T_ARRAY(__) then
7968 let arrayTypeStr = expTypeArray(ty)
7969 let tvar = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7970 let tevar = tempDecl(arrayTypeStr, &varDecls, &varFrees)
7971 let to = expTypeShort(ty)
7972 let from = expTypeFromExpShort(exp)
7973 // As resultVarAssignment: the copy needs a reference of its own.
7974 let &preExp += '<%rcReleaseBefore(arrayTypeStr, tevar)%><%tevar%> = <%expVar%>;<%rcArrayRetain(arrayTypeStr, tevar)%><%\n%>cast_<%from%>_array_to_<%to%>(&<%tevar%>, &<%tvar%>);<%\n%>'
7975 tvar
7976 case ty1 as T_COMPLEX(complexClassType=rec as RECORD(__)) then
7977 match typeof(exp)
7978 case ty2 as T_COMPLEX(__) then
7979 if intEq(listLength(ty1.varLst),listLength(ty2.varLst)) then expVar
7980 else
7981 error(sourceInfo(), 'Cast on record. Revise me. <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
7982 /*
7983 let tmp = tempDecl(expTypeModelica(ty2),&varDecls, &varFrees)
7984 let res = tempDecl(expTypeModelica(ty1),&varDecls, &varFrees)
7985 let &preExp += '<%tmp%> = <%expVar%>;<%\n%>'
7986 let &preExp += ty1.varLst |> var as DAE.TYPES_VAR() => '<%res%>._<%var.name%> = <%tmp%>._<%var.name%>; /* cast */<%\n%>'
7987 res
7988 */
7989 else
7990 '(<%expVar%>) /* could not cast, using the variable as it is */'
7991 end daeExpCast;
7992
7993 185 template daeExpTsub(Exp inExp, Context context, Text &preExp,
7994 Text &varDecls, Text &varFrees, Text &auxFunction)
7995 "Generates code for an tsub expression."
7996 ::=
7997 match inExp
7998 case TSUB(ix=1) then
7999 daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8000 case TSUB(exp=CALL(attr=CALL_ATTR(ty=T_TUPLE(types=tys)))) then
8001 let v = tempDecl(expTypeArrayIf(listGet(tys,ix)), &varDecls, &varFrees)
8002 let additionalOutputs = List.restOrEmpty(tys) |> ty hasindex i1 fromindex 2 => if intEq(i1,ix) then ', &<%v%>' else ", NULL"
8003 let &preExp += if isArrayType(listGet(tys,ix)) then '<%v%>.dim_size = 0;<%\n%>'
8004 let res = daeExpCallTuple(exp, additionalOutputs, context, &preExp, &varDecls, &varFrees, &auxFunction)
8005 let &preExp += '<%res%>;<%\n%>'
8006 v
8007 case TSUB(__) then
8008 error(sourceInfo(), '<%ExpressionDumpTpl.dumpExp(inExp,"\"")%>: TSUB only makes sense if the subscripted expression is a function call of tuple type')
8009 end daeExpTsub;
8010
8011 4765 template daeExpRsub(Exp inExp, Context context, Text &preExp,
8012 Text &varDecls, Text &varFrees, Text &auxFunction)
8013 "Generates code for an tsub expression."
8014 ::=
8015 match inExp
8016 case RSUB(ix=-1) then
8017 let res = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8018 '<%res%>._<%fieldName%>'
8019 case RSUB(__) then
8020 let res = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8021 let offset = intAdd(ix,1) // 1-based
8022 '(OMC_BOX_FIELD(<%res%>, <%offset%>))'
8023 else
8024 error(sourceInfo(), '<%ExpressionDumpTpl.dumpExp(inExp,"\"")%>: failed')
8025 end daeExpRsub;
8026
8027 672 template daeExpAsub(Exp inExp, Context context, Text &preExp,
8028 Text &varDecls, Text &varFrees, Text &auxFunction)
8029 "Generates code for an asub expression."
8030 ::=
8031 match expTypeFromExpShort(inExp)
8032 case "metatype" then
8033 // MetaModelica Array
8034 (match inExp case ASUB(exp=e, sub={idx}) then
8035 let e1 = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
8036 let idx1 = daeSubscript(idx, context, &preExp, &varDecls, &varFrees, &auxFunction)
8037 'arrayGet(<%e1%>,<%idx1%>) /* DAE.ASUB */')
8038 // Modelica Array
8039 else
8040 match inExp
8041 case ASUB(exp=ASUB(__)) then
8042 error(sourceInfo(),'Nested array subscripting *should* have been handled by the routine creating the asub, but for some reason it was not: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8043
8044 // Faster asub: Do not construct a whole new array just to access one subscript
8045 case ASUB(exp=exp as ARRAY(scalar=true), sub={idx}) then
8046 let res = tempDecl(expTypeFromExpModelica(exp),&varDecls, &varFrees)
8047 let idx1 = daeSubscript(idx, context, &preExp, &varDecls, &varFrees, &auxFunction)
8048 let outOfBounds = '<%raiseOrThrow()%>(threadData, "Index %ld out of bounds [1..<%listLength(exp.array)%>] for array <%Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(exp,"\""))%>", (long) <%idx1%>);'
8049 let expl = (exp.array |> e hasindex i1 fromindex 1 =>
8050 let &caseVarDecls = buffer ""
8051 let &caseVarFrees = buffer ""
8052 let &casePreExp = buffer ""
8053 let v = daeExp(e, context, &casePreExp, &caseVarDecls, &caseVarFrees, &auxFunction)
8054 <<
8055 <%if intEq(i1, 1) then 'default:<%\n%> <%outOfBounds%><%\n%>'%>case <%i1%>: {
8056 <%&caseVarDecls%>
8057 <%&casePreExp%>
8058 <%rcAssignRetain(expTypeFromExpModelica(exp), res, v)%><%&caseVarFrees%>
8059 break;
8060 }
8061 >> ; separator = "\n")
8062 let &preExp +=
8063 <<
8064 switch(<%idx1%>)
8065 { /* ASUB */
8066 <%expl%>
8067 }
8068 <%\n%>
8069 >>
8070 res
8071
8072 case ASUB(exp=range as RANGE(ty=T_ARRAY(ty = T_INTEGER()),step=NONE()), sub={idx}) then
8073 let res = tempDecl("modelica_integer", &varDecls, &varFrees)
8074 let idx1 = daeSubscript(idx, context, &preExp, &varDecls, &varFrees, &auxFunction)
8075 let start = daeExp(range.start, context, &preExp, &varDecls, &varFrees, &auxFunction)
8076 let stop = daeExp(range.stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
8077 let &preExp += <<
8078 <%res%> = <%idx1%> + <%start%> - 1;
8079 if (<%res%> > <%stop%>) {
8080 <%raiseOrThrow()%>(threadData, "Value %ld out of bounds for range <%Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(range,"\""))%>", (long) <%res%>);
8081 <%res%> = <%stop%>;
8082 }
8083 >>
8084 res
8085
8086 case ASUB(exp=range as RANGE(ty=T_ARRAY(ty = T_REAL()),step=NONE()), sub={idx}) then
8087 let res = tempDecl("modelica_real", &varDecls, &varFrees)
8088 let idx1 = daeSubscript(idx, context, &preExp, &varDecls, &varFrees, &auxFunction)
8089 let start = daeExp(range.start, context, &preExp, &varDecls, &varFrees, &auxFunction)
8090 let stop = daeExp(range.stop, context, &preExp, &varDecls, &varFrees, &auxFunction)
8091 let &preExp += <<
8092 <%res%> = <%idx1%> + <%start%> - 1;
8093 if (<%res%> > <%stop%> + 0.5) {
8094 <%raiseOrThrow()%>(threadData, "Value %f out of bounds for range <%Util.escapeModelicaStringToCString(ExpressionDumpTpl.dumpExp(range,"\""))%>", <%res%>);
8095 <%res%> = <%stop%>;
8096 }
8097 >>
8098 res
8099
8100 case ASUB(exp=RANGE(ty=t), sub={idx}) then
8101 error(sourceInfo(),'ASUB_EASY_CASE type:<%unparseType(t)%> range:<%ExpressionDumpTpl.dumpExp(exp,"\"")%> index:<%ExpressionDumpTpl.dumpSubscript(idx)%>')
8102
8103 case ASUB(exp=ecr as CREF(__), sub=subs) then
8104 daeExpCrefLhs(buildCrefExpFromSubs(ecr, subs), context, &preExp, &varDecls, &varFrees, &auxFunction, false)
8105
8106 case ASUB(exp=e, sub=indexes) then
8107 let exp = daeExp(e, context, &preExp, &varDecls, &varFrees, &auxFunction)
8108 let typeShort = expTypeFromExpShort(e)
8109 match Expression.typeof(inExp)
8110 case T_COMPLEX(complexClassType = ClassInf.RECORD(__)) then
8111 let expIndexes = (indexes |> index => daeSubscript(index, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
8112 '<%typeShort%>_array_get(<%exp%>, <%listLength(indexes)%>, <%expIndexes%>)'
8113 case ty as T_ARRAY() then
8114 let arrayType = expTypeArray(ty)
8115 let tmp = tempDecl(arrayType, &varDecls, &varFrees)
8116 let spec = daeExpCrefIndexSpec(padAsubSubscripts(e, indexes), context, &preExp, &varDecls, &varFrees, &auxFunction)
8117 let &preExp += '<%rcReleaseBefore(arrayType, tmp)%>index_alloc_<%arrayType%>(&<%exp%>, &<%spec%>, &<%tmp%>);<%\n%>'
8118 tmp
8119
8120 else
8121 let expIndexes = (indexes |> index => daeSubscriptASubIndex(index, context, &preExp, &varDecls, &varFrees, &auxFunction) ;separator=", ")
8122 '<%typeShort%>_get<%match listLength(indexes) case 1 then "" case i then '_<%i%>D'%>(<%exp%>, <%expIndexes%>)'
8123
8124 else
8125 error(sourceInfo(),'OTHER_ASUB <%ExpressionDumpTpl.dumpExp(inExp,"\"")%>')
8126 end daeExpAsub;
8127
8128 742 template daeSubscriptASubIndex(DAE.Subscript sub, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8129 ::=
8130 match sub
8131 case INDEX(__) then daeExpASubIndex(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8132 else daeSubscript(sub, context, &preExp, &varDecls, &varFrees, &auxFunction)
8133 end daeSubscriptASubIndex;
8134
8135 584 template daeExpASubIndex(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8136 ::=
8137 match exp
8138 case ICONST(__) then incrementInt(integer,-1)
8139 case ENUM_LITERAL(__) then incrementInt(index,-1)
8140 else '(<%daeExp(exp,context,&preExp,&varDecls, &varFrees, &auxFunction)%>)-1'
8141 end daeExpASubIndex;
8142
8143 2553 template daeExpCallPre(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8144 "Generates code for an asub of a cref, which becomes cref + offset."
8145 ::=
8146 match exp
8147 /*we use daeExpCrefLhs because daeExpCrefRhs returns with a cast.
8148 will reslut in 'pre(modelica_integer)$A$B...
8149 pre() functions should actaully be eliminated in backend and $PRE prepened as ident
8150 in all cases. (now it's done some places but not in others.)*/
8151 case cr as CREF(__) then
8152 daeExpCrefLhs(exp, context, &preExp, &varDecls, &varFrees, &auxFunction, true)
8153 else
8154 error(sourceInfo(), 'Code generation does not support pre(<%ExpressionDumpTpl.dumpExp(exp,"\"")%>)')
8155 end daeExpCallPre;
8156
8157 767 template daeExpSize(Exp exp, Context context, Text &preExp,
8158 Text &varDecls, Text &varFrees, Text &auxFunction)
8159 "Generates code for a size expression."
8160 ::=
8161 match exp
8162 case SIZE(sz=SOME(dim)) then
8163 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8164 let dimPart = daeExp(dim, context, &preExp, &varDecls, &varFrees, &auxFunction)
8165 let resVar = tempDecl("modelica_integer", &varDecls, &varFrees)
8166 let &preExp += '<%resVar%> = size_of_dimension_base_array(<%expPart%>, <%dimPart%>);<%\n%>'
8167 resVar
8168 case SIZE(sz=NONE()) then
8169 let expPart = daeExp(exp, context, &preExp, &varDecls, &varFrees, &auxFunction)
8170 let resVar = tempDecl("integer_array", &varDecls, &varFrees)
8171 let &preExp += 'sizes_of_dimensions_base_array(&<%expPart%>, &<%resVar%>);<%\n%>'
8172 resVar
8173 else error(sourceInfo(), ExpressionDumpTpl.dumpExp(exp,"\"") + " not implemented")
8174 end daeExpSize;
8175
8176
8177 206 template daeExpReduction(Exp exp, Context context, Text &preExp,
8178 Text &varDecls, Text &varFrees, Text &auxFunction)
8179 "Generates code for a reduction expression. The code is quite messy because it handles all
8180 special reduction functions (list, listReverse, array) and handles both list and array as input"
8181 ::=
8182 match exp
8183 case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=THREAD()),iterators=iterators)
8184 case r as REDUCTION(reductionInfo=ri as REDUCTIONINFO(iterType=COMBINE()),iterators=iterators as {_}) then
8185 (
8186 let &tmpVarDecls = buffer ""
8187 let &tmpVarFrees = buffer ""
8188 let &bodyExpPre = buffer ""
8189 let &rangeExpPre = buffer ""
8190 let arrayTypeResult = expTypeFromExpArray(r)
8191 let arrIndex = match ri.path case IDENT(name="array") then tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees)
8192 let foundFirst = match ri.path case IDENT(name="array") then "" else (if not ri.defaultValue then tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees))
8193 let resType = expTypeArrayIf(typeof(exp))
8194 let &sub = buffer ""
8195 let res = contextCref(makeUntypedCrefIdent(ri.resultName), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8196 let &tmpVarDecls += '<%resType%> <%res%>;<%\n%>'
8197 let resTmp = tempDecl(resType,&varDecls, &varFrees)
8198 let &preDefault = buffer ""
8199 let resTail = (match ri.path case IDENT(name="list") then tempDecl("modelica_metatype*",&tmpVarDecls, &tmpVarFrees))
8200 let defaultValue = (match ri.path
8201 case IDENT(name="array") then ""
8202 else (match ri.defaultValue
8203 case SOME(v) then daeExp(ValuesUtil.valueExpNoOriginal(v),context,&preDefault,&tmpVarDecls, &tmpVarFrees, &auxFunction)))
8204 let &sub = buffer ""
8205 let reductionBodyExpr = contextCref(makeUntypedCrefIdent(ri.foldName), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8206 let bodyExprType = expTypeArrayIf(typeof(r.expr))
8207 let reductionBodyExprWork = daeExp(r.expr, context, &bodyExpPre, &tmpVarDecls, &tmpVarFrees, &auxFunction)
8208 let &tmpVarDecls += '<%bodyExprType%> <%reductionBodyExpr%>;<%\n%>'
8209 let &bodyExpPre += '<%reductionBodyExpr%> = <%reductionBodyExprWork%>;<%\n%>'
8210 let foldExp = (match ri.path
8211 case IDENT(name="list") then
8212 <<
8213 *<%resTail%> = mmc_mk_cons(<%reductionBodyExpr%>,0);
8214 <%resTail%> = &MMC_CDR(*<%resTail%>);
8215 >>
8216 case IDENT(name="listReverse") then // This is too easy; the damn list is already in the correct order
8217 '<%res%> = mmc_mk_cons(<%reductionBodyExpr%>,<%res%>);'
8218 case IDENT(name="array") then
8219 match typeof(r.expr)
8220 case T_COMPLEX(complexClassType = record_state) then
8221 let rec_name = '<%underscorePath(ClassInfUtil.getStateName(record_state))%>'
8222 let elem = '<%rec_name%>_array_get(<%res%>, 1, <%arrIndex%>)'
8223 <<
8224 <%elem%> = <%reductionBodyExpr%>;
8225 <%rcRetain(bodyExprType, elem)%><%arrIndex%>++;
8226 >>
8227 case T_ARRAY(__) then
8228 let tmp = tempDecl("index_spec_t", &varDecls, &varFrees)
8229 let nridx_str = intAdd(1,listLength(dims))
8230 let idx_str = (dims |> dim => ", (modelica_integer)(1), (int*)0, 'W'")
8231 <<
8232 <%rcReleaseBefore("index_spec_t", tmp)%>create_index_spec(&<%tmp%>, <%nridx_str%>, (modelica_integer)(0), make_index_array(1, (modelica_integer) <%arrIndex%>++), 'S'<%idx_str%>);
8233 indexed_assign_<%expTypeArray(ty)%>(<%reductionBodyExpr%>, &<%res%>, &<%tmp%>);
8234 >>
8235 else
8236 <<
8237 <%arrayTypeResult%>_get1(<%res%>, 1, <%arrIndex%>) = <%reductionBodyExpr%>;
8238 <%rcRetain(bodyExprType, '<%arrayTypeResult%>_get1(<%res%>, 1, <%arrIndex%>)')%><%arrIndex%>++;
8239 >>
8240 else match ri.foldExp case SOME(fExp) then
8241 // The fold reads the accumulator, which owns its value: the loop's
8242 // temporaries are released when they are rebuilt.
8243 let &foldExpPre = buffer ""
8244 let fExpStr = daeExp(fExp, context, &foldExpPre, &tmpVarDecls, &tmpVarFrees, &auxFunction)
8245 if foundFirst then
8246 <<
8247 if (<%foundFirst%>)
8248 {
8249 <%foldExpPre%>
8250 <%rcAssignRetain(resType, res, fExpStr)%>
8251 }
8252 else
8253 {
8254 <%res%> = <%reductionBodyExpr%>;
8255 <%rcRetain(resType, res)%><%foundFirst%> = 1;
8256 }
8257 >>
8258 else
8259 <<
8260 <%foldExpPre%>
8261 <%rcAssignRetain(resType, res, fExpStr)%>
8262 >>)
8263 let endLoop = tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees)
8264 let loopHeadIter = (iterators |> iter as REDUCTIONITER(__) =>
8265 let identType = expTypeFromExpModelica(iter.exp)
8266 let arrayType = expTypeFromExpArray(iter.exp)
8267 let iteratorName = contextIteratorName(iter.id, context)
8268 let loopVar = match iter.exp case RANGE(__) then iteratorName else '<%iteratorName%>_loopVar'
8269 let stepVar = match iter.exp case RANGE(__) then tempDecl(identType,&tmpVarDecls, &tmpVarFrees)
8270 let stopVar = match iter.exp case RANGE(__) then tempDecl(identType,&tmpVarDecls, &tmpVarFrees)
8271 let &guardExpPre = buffer ""
8272 let &tmpVarDecls += (match identType
8273 case "modelica_metatype" then 'modelica_metatype <%loopVar%> = 0;<%\n%>'
8274 else (match iter.exp case RANGE(__) then "" else '<%arrayType%> <%loopVar%>;<%\n%>'))
8275 let firstIndex = match iter.exp case RANGE(__) then "" else (match identType case "modelica_metatype" then (if Expression.isMetaArray(iter.exp) then tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees) else "") else tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees))
8276 let rangeExpStep = (match iter.exp case RANGE(step=NONE()) then "1 /* Range step-value */" case RANGE(step=SOME(step)) then '<%daeExp(step,context,&rangeExpPre,&tmpVarDecls, &tmpVarFrees, &auxFunction)%> /* Range step-value */' else "")
8277 let rangeExpStop = (match iter.exp case RANGE(__) then '<%daeExp(stop,context,&rangeExpPre,&tmpVarDecls, &tmpVarFrees, &auxFunction)%> /* Range stop-value */' else "")
8278 let rangeExp = (match iter.exp case RANGE(__) then '<%daeExp(start,context,&rangeExpPre,&tmpVarDecls, &tmpVarFrees, &auxFunction)%> /* Range start-value */' else daeExp(iter.exp,context,&rangeExpPre,&tmpVarDecls, &tmpVarFrees, &auxFunction))
8279 let &rangeExpPre += if rangeExpStep then '<%stepVar%> = <%rangeExpStep%>;<%\n%>'
8280 let &rangeExpPre += if rangeExpStop then '<%stopVar%> = <%rangeExpStop%>;<%\n%>'
8281 let &rangeExpPre += '<%loopVar%> = <%rangeExp%>;<%\n%>'
8282 let &rangeExpPre += (if rangeExpStop then
8283 let check =
8284 <<
8285 if (<%stepVar%> == 0) {
8286 omc_assert(threadData, omc_dummyFileInfo, "Range with a step of zero.");
8287 <%errorCheck(context)%>
8288 }<%\n%>
8289 >>
8290 match iter.exp
8291 case RANGE(step=SOME(DAE.ICONST(integer=0))) then check
8292 case RANGE(step=NONE())
8293 case RANGE(step=SOME(DAE.ICONST(__))) then ""
8294 else check)
8295 let isArrayWithLength = if rangeExpStop then (match ri.path case IDENT(name="array") then "1" else "") else ""
8296 let &tmpVarDecls += if isArrayWithLength then 'modelica_integer <%iteratorName%>_length;<%\n%>'
8297 let &rangeExpPre += match iter.exp case RANGE(__) then "" else (if firstIndex then '<%firstIndex%> = 1;<%\n%>')
8298 let guardCond = (match iter.guardExp case SOME(grd) then daeExp(grd, context, &guardExpPre, &tmpVarDecls, &tmpVarFrees, &auxFunction) else "")
8299 let &tmpVarDecls += '<%identType%> <%iteratorName%>;<%\n%>'
8300 let &rangeExpPre += if isArrayWithLength then
8301 '<%iteratorName%>_length = ((<%stopVar%>-<%if firstIndex then firstIndex else iteratorName %>)/<%stepVar%>)+1;<%\n%>'
8302 let &rangeExpPre += match iter.exp case RANGE(__) then '<%iteratorName%> = (<%rangeExp%>)-<%stepVar%>;<%\n%>' /* We pre-increment the counter, so subtract the step for the first variable for ranges */
8303 let guardExp =
8304 <<
8305 <%&guardExpPre%>
8306 if (<%guardCond%>) {
8307 <%endLoop%>--;
8308 break;
8309 }
8310 >>
8311 (match identType
8312 case "modelica_metatype" then
8313 (if Expression.isMetaArray(iter.exp) then
8314 (if stringEq(guardCond,"") then
8315 <<
8316 if (<%firstIndex%> <= arrayLength(<%loopVar%>)) {
8317 <%iteratorName%> = arrayGet(<%loopVar%>, <%firstIndex%>++);
8318 <%endLoop%>--;
8319 }
8320 >>
8321 else
8322 <<
8323 while (<%firstIndex%> <= arrayLength(<%loopVar%>)) {
8324 <%iteratorName%> = arrayGet(<%loopVar%>, <%firstIndex%>++);
8325 <%guardExp%>
8326 }
8327 >>
8328 )
8329 else
8330 (if stringEq(guardCond,"") then
8331 <<
8332 if (!listEmpty(<%loopVar%>)) {
8333 <%iteratorName%> = MMC_CAR(<%loopVar%>);
8334 <%loopVar%> = MMC_CDR(<%loopVar%>);
8335 <%endLoop%>--;
8336 }
8337 >>
8338 else
8339 <<
8340 while (!listEmpty(<%loopVar%>)) {
8341 <%iteratorName%> = MMC_CAR(<%loopVar%>);
8342 <%loopVar%> = MMC_CDR(<%loopVar%>);
8343 <%guardExp%>
8344 }
8345 >>
8346 )
8347 )
8348 else
8349 ( /* Not metatype */
8350 match iter.exp
8351 case RANGE(__) then
8352 <<
8353 <%if stringEq(guardCond,"") then "if" else "while"%> (<%stepVar%> > 0 ? <%iteratorName%>+<%stepVar%> <= <%stopVar%> : <%iteratorName%>+<%stepVar%> >= <%stopVar%>) {
8354 <%iteratorName%> += <%stepVar%>;
8355 <%if stringEq(guardCond,"") then '<%endLoop%>--;' else guardExp%>
8356 }
8357 >>
8358 else /* Not a range; allocate a big array... */
8359 let addr = match iter.ty
8360 case T_ARRAY(ty=T_COMPLEX(complexClassType = record_state)) then
8361 let rec_name = '<%underscorePath(ClassInfUtil.getStateName(record_state))%>'
8362 '<%rec_name%>_array_get(<%loopVar%>, 1, <%firstIndex%>)'
8363 else
8364 '<%arrayType%>_get1(<%loopVar%>, 1, <%firstIndex%>)'
8365 (if stringEq(guardCond,"") then
8366 <<
8367 if(<%firstIndex%> <= size_of_dimension_base_array(<%loopVar%>, 1)) {
8368 <%iteratorName%> = <%addr%>;
8369 <%firstIndex%>++;
8370 <%endLoop%>--;
8371 }
8372 >>
8373 else
8374 <<
8375 while(<%firstIndex%> <= size_of_dimension_base_array(<%loopVar%>, 1)) {
8376 <%iteratorName%> = <%addr%>;
8377 <%firstIndex%>++;
8378 <%guardExp%>
8379 }
8380 >>
8381 )))
8382 )
8383 let firstValue = (match ri.path
8384 case IDENT(name="array") then
8385 let length = tempDecl("modelica_integer",&tmpVarDecls, &tmpVarFrees)
8386 let &rangeExpPre += '<%length%> = 0;<%\n%>'
8387 let _ = (iterators |> iter as REDUCTIONITER(__) =>
8388 let iteratorName = contextIteratorName(iter.id, context)
8389 let loopVar = '<%iteratorName%>_loopVar'
8390 let identType = expTypeFromExpModelica(iter.exp)
8391 let &rangeExpPre += '<%length%> = modelica_integer_max(<%length%>,<%match identType case "modelica_metatype" then (if Expression.isMetaArray(iter.exp) then 'arrayLength(<%loopVar%>)' else 'listLength(<%loopVar%>)') else match iter.exp case RANGE(__) then '<%iteratorName%>_length' else 'size_of_dimension_base_array(<%loopVar%>, 1)'%>);<%\n%>'
8392 "")
8393 <<
8394 <%arrIndex%> = 1;
8395 <% match typeof(r.expr)
8396 case T_COMPLEX(complexClassType = record_state) then
8397 let rec_name = '<%underscorePath(ClassInfUtil.getStateName(record_state))%>'
8398 // There is no alloc_generic_array, a record array is allocated with
8399 // the alloc_<record>_array macro generated for the record itself.
8400 'alloc_<%rec_name%>_array(&<%res%>, 1, (_index_t)<%length%>);'
8401 case T_ARRAY(__) then
8402 let dimSizes = dims |> dim => match dim
8403 case DIM_INTEGER(__) then ', (_index_t)<%integer%>'
8404 case DIM_BOOLEAN(__) then ", (_index_t)2"
8405 case DIM_ENUM(__) then ', (_index_t)<%size%>'
8406 case DAE.DIM_EXP(exp=e) then ', (_index_t)<%daeExp(e,context,&rangeExpPre,&tmpVarDecls, &tmpVarFrees, &auxFunction)%>'
8407 else error(sourceInfo(), 'array reduction unable to generate code for element of unknown dimension sizes; type <%unparseType(typeof(r.expr))%>: <%ExpressionDumpTpl.dumpExp(r.expr,"\"")%>')
8408 ; separator = ", "
8409 'alloc_<%arrayTypeResult%>(&<%res%>, <%intAdd(1,listLength(dims))%>, <%length%><%dimSizes%>);'
8410 else
8411 'simple_alloc_1d_<%arrayTypeResult%>(&<%res%>,<%length%>);'%>
8412 >>
8413 else
8414 (if foundFirst then
8415 <<
8416 <%foundFirst%> = 0; /* <%dotPath(ri.path)%> lacks default-value */
8417 >>
8418 else
8419 <<
8420 <%&preDefault%>
8421 <%res%> = <%defaultValue%>; /* defaultValue */
8422 <%rcRetain(resType, res)%>
8423 >>)
8424 )
8425 let loop =
8426 <<
8427 while(1) {
8428 <%endLoop%> = <%listLength(iterators)%>;
8429 <%loopHeadIter%>
8430 if (<%endLoop%> == 0) {
8431 <%&bodyExpPre%>
8432 <%foldExp%>
8433 } <% match iterators case _::_ then
8434 <<
8435 else if (<%endLoop%> == <%listLength(iterators)%>) {
8436 break;
8437 } else {
8438 <%generateThrow()%>;
8439 }
8440 >> %>
8441 }
8442 >>
8443 let &preExp += <<
8444 {
8445 <%&tmpVarDecls%>
8446 <%&rangeExpPre%>
8447 <%firstValue%>
8448 <% if resTail then '<%resTail%> = &<%res%>;' %>
8449 <%loop%>
8450 <% if foundFirst then 'if (!<%foundFirst%>) <%generateThrow()%>;' %>
8451 <% if resTail then '*<%resTail%> = mmc_mk_nil();' %>
8452 <%rcReleaseBefore(resType, resTmp)%><% resTmp %> = <% res %>;
8453 <%&tmpVarFrees%>
8454 }<%\n%>
8455 >>
8456 resTmp)
8457 else error(sourceInfo(), 'Code generation does not support multiple iterators: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8458 end daeExpReduction;
8459
8460 1023 template daeExpMatch(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8461 "Generates code for a match expression."
8462 ::=
8463 match exp
8464 case exp as MATCHEXPRESSION(__) then
8465 let res = match et
8466 case T_NORETCALL(__) then error(sourceInfo(), 'match expression not returning anything should be caught in a noretcall statement and not reach this code: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8467 case T_TUPLE(types={}) then error(sourceInfo(), 'match expression returning an empty tuple should be caught in a noretcall statement and not reach this code: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8468 else tempDeclZero(expTypeModelica(et), &varDecls, &varFrees)
8469 let startIndexOutputs = "ERROR_INDEX"
8470 daeExpMatch2(exp,listExpLength1,res,startIndexOutputs,context,&preExp,&varDecls, &varFrees,&auxFunction)
8471 end daeExpMatch;
8472
8473 1171 template daeExpMatch2(Exp exp, list<Exp> tupleAssignExps, Text res, Text startIndexOutputs, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8474 "Generates code for a match expression."
8475 ::=
8476 match exp
8477 case exp as MATCHEXPRESSION(__) then
8478 let mydummy = match exp.matchType
8479 case TRY_STACKOVERFLOW() then ""
8480 else codegenPushTryThrowIndex(System.tmpTick())
8481 let goto = 'goto_<%codegenPeekTryThrowIndex()%>'
8482 let &preExpInner = buffer ""
8483 let &preExpRes = buffer ""
8484 let &varDeclsInput = buffer ""
8485 let &varFreesInput = buffer ""
8486 let &varDeclsInner = buffer ""
8487 let &varFreesInner = buffer ""
8488 let &varFrees = buffer ""
8489 let &ignore = buffer ""
8490 let ignore2 = (elementVars(localDecls) |> var =>
8491 varInit(var, "", &varDeclsInner, &preExpInner, &varFrees, &auxFunction)
8492 )
8493 let prefix = 'tmp<%System.tmpTick()%>'
8494 let &preExpInput = buffer ""
8495 let &expInput = buffer ""
8496 // get the current index of tmpMeta and reserve N=listLength(inputs) values in it!
8497 let startIndexInputs = '<%System.tmpTickIndexReserve(0, 0)%>'
8498 let ignore3 = (List.zip(inputs,aliases) |> (e1,alias) hasindex i1 fromindex 1 =>
8499 let typ = '<%expTypeFromExpModelica(e1)%>'
8500 let decl = tempDeclMatchInput(exp.matchType, typ, startIndexInputs, i1, &varDeclsInput, &varFreesInput)
8501 let &expInput += '<%decl%> = <%daeExp(e1, context, &preExpInput, &varDeclsInput, &varFreesInput, &auxFunction)%>;<%\n%>'
8502 let &expInput += alias |> a => let &varDeclsInput += '<%typ%> _<%a%>;' '_<%a%> = <%decl%>;' ; separator="\n"
8503 ""; empty)
8504 let ix = match exp.matchType
8505 case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then
8506 let matchInputVar = getTempDeclMatchInputName(startIndexInputs, switchIndex)
8507 'stringHashDjb2Mod(<%matchInputVar%>,<%div%>)'
8508 case MATCH(switch=SOME((switchIndex,ty as T_METATYPE(__),_))) then
8509 let matchInputVar = getTempDeclMatchInputName(startIndexInputs, switchIndex)
8510 'valueConstructor(<%matchInputVar%>)'
8511 case MATCH(switch=SOME((switchIndex,ty as T_INTEGER(__),_))) then
8512 let matchInputVar = getTempDeclMatchInputName(startIndexInputs, switchIndex)
8513 '<%matchInputVar%>'
8514 case MATCH(switch=SOME((switchIndex,ty as T_ENUMERATION(__),_))) then
8515 let matchInputVar = getTempDeclMatchInputName(startIndexInputs, switchIndex)
8516 '<%matchInputVar%>'
8517 case MATCH(switch=SOME((switchIndex,ty as T_METABOXED(__),_))) then
8518 let matchInputVar = getTempDeclMatchInputName(startIndexInputs, switchIndex)
8519 'omc_unbox_integer(<%matchInputVar%>)'
8520 case MATCH(switch=SOME(_)) then
8521 error(sourceInfo(), 'Unknown switch: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8522 else tempDecl('volatile mmc_switch_type', &varDeclsInner, &varFreesInner)
8523 let done = tempDecl('int', &varDeclsInner, &varFreesInner)
8524 let &preExp +=
8525 match exp.matchType
8526 case TRY_STACKOVERFLOW() then
8527 let &varDeclsInner = buffer ""
8528 let &varFreesInner = buffer ""
8529 (match exp.cases
8530 case {try as CASE(__),else as CASE(__)} then
8531 let tryb = (try.body |> stmt => algStatement(stmt, context, &varDeclsInner, &varFreesInner, &auxFunction); separator="\n")
8532 let elseb = (else.body |> stmt => algStatement(stmt, context, &varDeclsInner, &varFreesInner, &auxFunction); separator="\n")
8533 <<
8534 <%endModelicaLine()%>
8535 { /* stack overflow check */
8536 <%varDeclsInput%>
8537 <%preExpInput%>
8538 <%expInput%>
8539 {
8540 <%varDeclsInner%>
8541 <%preExpInner%>
8542 OMC_TRY_STACK()
8543 <%tryb%>
8544 OMC_ELSE_STACK()
8545 <%elseb%>
8546 OMC_CATCH_STACK()
8547 }
8548 }
8549 >>
8550 else error(sourceInfo(), 'Got stack overflow block with more than 2 cases')
8551 )
8552 else
8553 <<
8554 <%endModelicaLine()%>
8555 { /* <% match exp.matchType case MATCHCONTINUE(__) then "matchcontinue expression" case MATCH(__) then "match expression" %> */
8556 <%varDeclsInput%>
8557 <%preExpInput%>
8558 <%expInput%>
8559 {
8560 <%varDeclsInner%>
8561 <%preExpInner%>
8562 <%match exp.matchType
8563 case MATCH(switch=SOME(_)) then '{'
8564 else
8565 <<
8566 <%ix%> = 0;
8567 <% match exp.matchType case MATCHCONTINUE(__) then
8568 /* One additional OMC_TRY_INTERNAL() for each caught exceptionOne additional OMC_TRY_INTERNAL() for each caught exception
8569 * You would expect you could do the setjmp only once, but some counters I guess are stored in registers and would need to become volatile
8570 * This is still a lot faster than doing OMC_TRY_INTERNAL() inside the for-loop
8571 */
8572 <<
8573 OMC_TRY_INTERNAL(mmc_jumper)
8574 <%prefix%>_top:
8575 threadData->mmc_jumper = &new_mmc_jumper;
8576 >>
8577 %>
8578 for (; <%ix%> < <%listLength(exp.cases)%>; <%ix%>++) {
8579 >>
8580 %>
8581 switch (MMC_SWITCH_CAST(<%ix%>)) {
8582 <%daeExpMatchCases(exp.cases, tupleAssignExps, exp.matchType, ix, res, startIndexOutputs, prefix, startIndexInputs, exp.inputs, context, &varDecls, &varFrees, &auxFunction, System.tmpTickIndexReserve(1,0) /* Returns the current MM tick */)%>
8583 }
8584 goto <%prefix%>_end;
8585 <%prefix%>_end: ;
8586 }<%let() = codegenPopTryThrowIndex() ""%>
8587 <% match exp.matchType case MATCHCONTINUE(__) then
8588
8589 <<
8590 goto <%goto%>;
8591 <%prefix%>_done:
8592 (void)<%ix%>;<%/* When we skip cases, the static analyzer thinks that is a dead assignment even if longjmp is in play. */%>
8593 OMC_RESTORE_INTERNAL(mmc_jumper);
8594 goto <%prefix%>_done2;
8595 <%goto%>:;
8596 OMC_CATCH_INTERNAL(mmc_jumper);
8597 if (++<%ix%> < <%listLength(exp.cases)%>) {
8598 goto <%prefix%>_top;
8599 }
8600 <%generateThrow()%>;
8601 <%prefix%>_done2:;
8602 >>
8603
8604 else
8605
8606 <<
8607 goto <%goto%>;
8608 <%goto%>:;
8609 <%generateThrow()%>;
8610 goto <%prefix%>_done;
8611 <%prefix%>_done:;
8612 >>
8613
8614 %>
8615 }
8616 }
8617 >>
8618 res
8619 end daeExpMatch2;
8620
8621 1169 template daeExpMatchCases(list<MatchCase> cases, list<Exp> tupleAssignExps, DAE.MatchType ty, Text ix, Text res, Text startIndexOutputs, Text prefix, Text startIndexInputs, list<Exp> inputs, Context context, Text &varDecls, Text &varFrees, Text &auxFunction, Integer startTmpTickIndex)
8622 ::=
8623 cases |> c as CASE(__) hasindex i0 =>
8624 let() = System.tmpTickSetIndex(startTmpTickIndex,1)
8625 // Susan doesn't let us do this outside the loop...
8626 let lastSwitchIndex = (match ty
8627 case MATCH(switch=SOME((n,ty as T_STRING(__),div))) then
8628 (match List.last(cases)
8629 case last as CASE(__) then
8630 (match switchIndex(listGet(last.patterns,n),div)
8631 case "default" then 'goto <%prefix%>_default'
8632 else 'goto <%prefix%>_end'))
8633 else 'goto <%prefix%>_end')
8634 let onPatternFail = (match ty
8635 case MATCH(switch=SOME((switchIndex,ty as T_STRING(__),div))) then
8636 lastSwitchIndex
8637 else 'goto <%prefix%>_end')
8638 let &varDeclsCaseInner = buffer ""
8639 let &varFreesCaseInner = buffer ""
8640 let &preExpCaseInner = buffer ""
8641 let &assignments = buffer ""
8642 let &preRes = buffer ""
8643 let &varFrees = buffer ""
8644 let patternMatching = (sortPatternsByComplexity(c.patterns) |> (lhs,i0)
8645 => patternMatch(lhs,'<%getTempDeclMatchInputName(startIndexInputs, i0)%>', onPatternFail, &varDeclsCaseInner, &varFreesCaseInner, &assignments); empty)
8646 let() = System.tmpTickSetIndex(startTmpTickIndex,1)
8647 let stmts = (c.body |> stmt => algStatement(stmt, context, &varDeclsCaseInner, &varFreesCaseInner, &auxFunction); separator="\n")
8648 let &preGuardCheck = buffer ""
8649 let guardCheck = (match c.patternGuard case SOME(exp) then
8650 <<
8651 /* Check guard condition after assignments */
8652 if (!<%daeExp(exp,context,&preGuardCheck,&varDeclsCaseInner, &varFreesCaseInner, &auxFunction)%>) <%onPatternFail%>;<%\n%>
8653 >>)
8654 let caseRes = match res case "" then "" else (match c.result
8655 case SOME(TUPLE(PR=exps)) then
8656 (exps |> e hasindex i1 fromindex 1 =>
8657 '<%getTempDeclMatchOutputName(exps, res, startIndexOutputs, i1)%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &varFreesCaseInner, &auxFunction)%>;<%\n%>')
8658 case SOME(exp as CALL(attr=CALL_ATTR(tailCall=TAIL(__)))) then
8659 daeExp(exp, context, &preRes, &varDeclsCaseInner, &varFreesCaseInner, &auxFunction)
8660 case SOME(exp as CALL(attr=CALL_ATTR(tuple_=true))) then
8661 let additionalOutputs = List.restOrEmpty(tupleAssignExps) |> cr hasindex i0 fromindex 2 /* starting with second element */ =>
8662 ', &<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, i0)%>'
8663 let retStruct = daeExpCallTuple(exp, additionalOutputs, context, &preRes, &varDeclsCaseInner, &varFreesCaseInner, &auxFunction)
8664 let callRet = match tupleAssignExps
8665 case {} then '<%retStruct%>;<%\n%>'
8666 case e::_ then '<%getTempDeclMatchOutputName(tupleAssignExps, res, startIndexOutputs, 1)%> = <%retStruct%>;<%\n%>'
8667 callRet
8668 case SOME(e) then '<%res%> = <%daeExp(e,context,&preRes,&varDeclsCaseInner, &varFreesCaseInner, &auxFunction)%>;<%\n%>')
8669 let _ = (elementVars(c.localDecls) |> var => varInit(var, "", &varDeclsCaseInner, &preExpCaseInner, &varFrees, &auxFunction))
8670 <<<%match ty case MATCH(switch=SOME((n,_,ea)))
8671 then
8672 let name = switchIndex(listGet(c.patterns,n),ea)
8673 (match name
8674 case "default" then
8675 // MSVC dislikes goto labels before declarations, so we put it before the block
8676 <<
8677 <%name%>:
8678 <%prefix%>_default: OMC_LABEL_UNUSED; {
8679 >>
8680 else
8681 '<%name%>: {')
8682 else
8683 'case <%i0%>: {'%>
8684 <%varDeclsCaseInner%>
8685 <%preExpCaseInner%>
8686 <%patternMatching%>
8687 <%assignments%>
8688 <%&preGuardCheck%>
8689 <% match c.jump
8690 case 0 then "/* Pattern matching succeeded */"
8691 else '<%ix%> += <%c.jump%>; /* Pattern matching succeeded; we may skip some cases if we fail */'
8692 %>
8693 <%guardCheck%>
8694 <%stmts%>
8695 <%modelicaLine(c.resultInfo)%>
8696 <% if c.result then '<%preRes%><%caseRes%>' else '<%generateThrow()%>;<%\n%>' %>
8697 <%endModelicaLine()%>
8698 goto <%prefix%>_done;
8699 }<%\n%>
8700 >>
8701 end daeExpMatchCases;
8702
8703 1262 template switchIndex(Pattern pattern, Integer extraArg)
8704 ::=
8705 match pattern
8706 case PAT_CALL(__) then 'case <%getValueCtor(index)%>'
8707 case PAT_CONSTANT(exp=e as SCONST(__))
8708 case PAT_CONSTANT(exp=SHARED_LITERAL(exp=e as SCONST(__))) then 'case <%stringHashDjb2Mod(e.string,extraArg)%> /* <%e.string%> */'
8709 case PAT_CONSTANT(exp=e as ICONST(__)) then 'case <%e.integer%>'
8710 case PAT_CONSTANT(exp=e as ENUM_LITERAL(__)) then 'case <%e.index%>'
8711 else 'default'
8712 end switchIndex;
8713
8714 827 template daeExpBox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8715 "Generates code for a match expression."
8716 ::=
8717 match exp
8718 case BOX(__) then
8719 let ty = if isArrayType(typeof(exp)) then "modelica_array" else expTypeFromExpShort(exp)
8720 let res = daeExp(exp,context,&preExp,&varDecls, &varFrees, &auxFunction)
8721 'omc_mk_<%ty%>(<%res%>)'
8722 end daeExpBox;
8723
8724 256 template daeExpUnbox(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8725 "Generates code for a match expression."
8726 ::=
8727 match exp
8728 case exp as UNBOX(ty = t as T_COMPLEX(complexClassType = RECORD(__))) then
8729 // A record is boxed field by field, so it has to be unboxed field by field
8730 // as well. unboxRecord wants the boxed value in a variable, so put the
8731 // expression in a temporary first.
8732 let res = daeExp(exp.exp,context,&preExp,&varDecls, &varFrees, &auxFunction)
8733 let boxed = tempDecl("modelica_metatype", &varDecls, &varFrees)
8734 let &preExp += '<%boxed%> = <%res%>;<%\n%>'
8735 unboxRecord(boxed, t, &preExp, &varDecls, &varFrees)
8736 case exp as UNBOX(__) then
8737 // An array is boxed with omc_mk_modelica_array, see daeExpBox, so it has to
8738 // be unboxed as an array and not as its element type.
8739 let ty = if isArrayType(exp.ty) then "array" else expTypeShort(exp.ty)
8740 let res = daeExp(exp.exp,context,&preExp,&varDecls, &varFrees, &auxFunction)
8741 'omc_unbox_<%ty%>(<%res%>)'
8742 end daeExpUnbox;
8743
8744 47357 template daeExpSharedLiteral(Exp exp)
8745 "Generates code for a match expression."
8746 ::=
8747 match exp case exp as SHARED_LITERAL(__) then '_OMC_LIT<%exp.index%>'
8748 end daeExpSharedLiteral;
8749
8750 135797 template daeSubscript(DAE.Subscript sub, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8751 ::=
8752 match sub
8753 case sub as INDEX() then daeSubscriptExp(exp,context,&preExp,&varDecls, &varFrees,&auxFunction)
8754 case sub as SLICE() then error(sourceInfo(), 'non INDEX(_) (i.e., SLICE) subscripts should not reach here. Check indexedAssign template. SLICE exp: <%ExpressionDumpTpl.dumpExp(exp,"\"")%>')
8755 case sub as WHOLEDIM() then error(sourceInfo(), 'non INDEX(_) (i.e., WHOLEDIM) subscripts should not reach here. Check indexedAssign template.')
8756 else error(sourceInfo(), 'non INDEX(_) (i.e., unknown) subscripts should not reach here. Check indexedAssign template.')
8757 end match
8758 end daeSubscript;
8759
8760 /* Subscripts need to return expressions that are different than for normal expressions.
8761 * The reason is that Modelica arrays use 1-based indexing, but Boolean indexes start at 0
8762 */
8763 135797 template daeSubscriptExp(Exp exp, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8764 ::=
8765 let res = daeExp(exp,context,&preExp,&varDecls, &varFrees,&auxFunction)
8766 match expTypeFromExpModelica(exp)
8767 case "modelica_boolean" then '(_index_t)(<%res%>+1)'
8768 else res
8769 end match
8770 end daeSubscriptExp;
8771
8772 1893126 template crefShortType(ComponentRef cr) "template crefType
8773 Like cref but with cast if type is integer."
8774 ::=
8775 match cr
8776 case CREF_IDENT(__) then expTypeShort(identType)
8777 case CREF_QUAL(__) then crefShortType(componentRef)
8778 else "crefType:ERROR"
8779 end match
8780 end crefShortType;
8781
8782 910220 template varArrayNameValues(SimVar var, Integer ix, Boolean isPre, Boolean isStart, Text &sub)
8783 ::=
8784 let arr = '<%if stringEq(&sub, "") then "" else "&" %>'
8785 match var
8786 case SIMVAR(varKind=CONST(), initialValue = SOME(value)) then
8787 let c_comment = CodegenUtil.crefCCommentWithVariability(var)
8788 '<%daeExpSimpleLiteral(value)%><%c_comment%>'
8789 case SIMVAR(varKind=PARAM())
8790 case SIMVAR(varKind=OPT_TGRID()) then
8791 let c_comment = CodegenUtil.crefCCommentWithVariability(var)
8792 let ty = crefShortType(name)
8793 '(<%arr%>data->simulationInfo-><%ty%>Parameter[<%simVarIndex(ty, "Params", '<%index%>')%>]<%c_comment%>)<%&sub%>'
8794 case SIMVAR(varKind=EXTOBJ()) then
8795 '(<%arr%>data->simulationInfo->extObjs[<%index%>])<%&sub%>'
8796 case SIMVAR(__) then
8797 let c_comment = CodegenUtil.crefCCommentWithVariability(var)
8798 let ty = crefShortType(name)
8799 if isStart then
8800 // The start attribute of a (non-scalarized) array variable can be
8801 // either an array (start = {1,2,3}: one start.data element per array
8802 // element, selected by the flattened index in &sub) or a single
8803 // broadcast value (each start = 1: start.data has exactly one
8804 // element). A scalar start variable has no subscript at all. Use the
8805 // flattened index only when the start attribute actually holds one
8806 // value per element, otherwise broadcast element [0] (issue #15686).
8807 // Select the element via the address of the chosen lvalue so the
8808 // whole expression stays an lvalue: $START crefs may appear in
8809 // array-building contexts (real_array_create(&tmp, &<expr>, ...)),
8810 // and a plain ?: ternary is an rvalue whose address cannot be taken.
8811 match ty
8812 case "real"
8813 case "integer"
8814 case "boolean"
8815 case "string" then
8816 let &nosub = buffer ""
8817 let attr = varAttributes(var, &nosub)
8818 if stringEq(&sub, "") then
8819 '((modelica_<%ty%> *)(<%attr%>.start.data))[0]'
8820 else
8821 '(*(base_array_nr_of_elements(<%attr%>.start) == 1 ? &((modelica_<%ty%> *)(<%attr%>.start.data))[0] : &((modelica_<%ty%> *)(<%attr%>.start.data))<%&sub%>))'
8822 else
8823 '<%varAttributes(var, &sub)%>.start'
8824 else if isPre then
8825 // the pre values have the layout of the values
8826 '(<%arr%>data->simulationInfo-><%ty%>VarsPre[<%simVarIndex(ty, "Vars", '<%index%>')%>]<%c_comment%>)<%&sub%>'
8827 else
8828 '(<%arr%>data->localData[<%ix%>]-><%ty%>Vars[<%simVarIndex(ty, "Vars", '<%index%>')%>]<%c_comment%>)<%sub%>'
8829 end match
8830 end varArrayNameValues;
8831
8832 287 template contiguousSlice(ComponentRef cr, String type, Context context)
8833 "Whether cr is one block of a variable's storage (contiguousSliceStart)."
8834 ::=
8835 if boolAnd(boolNot(listEmpty(contiguousSliceDims(crefSubs(cr), crefDims(cr)))),
8836 boolAnd(boolNot(stringEq(type, "string")), isContiguousArrayCref(crefStripSubs(cr), context)))
8837 then "true"
8838 end contiguousSlice;
8839
8840 12 template contiguousSliceData(ComponentRef cr, String type, Context context, Text &preExp, Text &varDecls, Text &varFrees, Text &auxFunction)
8841 ::=
8842 let &sub = buffer ""
8843 let base = contextCref(crefStripSubs(cr), context, &preExp, &varDecls, &varFrees, &auxFunction, &sub)
8844 let offset = indexSubRecursive(listReverse(List.restOrEmpty(crefDims(cr))), listReverse(contiguousSliceStart(crefSubs(cr), crefDims(cr))), context, &preExp, &varDecls, &varFrees, &auxFunction)
8845 '(((modelica_<%type%>*)&<%base%>) + (<%offset%>))'
8846 end contiguousSliceData;
8847
8848 898806 template simVarIndex(String ty, String kind, String index)
8849 "Where a variable starts in its values array. Scalarized code has only scalar
8850 variables, so the index maps are the identity there."
8851 ::=
8852 match getSimCode()
8853 case SIMCODE(scalarized=true) then index
8854 else 'data->simulationInfo-><%ty%><%kind%>Index[<%index%>]'
8855 end simVarIndex;
8856
8857 28 template startArrayGather(ComponentRef cr, Text type, Text arr, Text ndims, Text dims, Text &varDecls, Text &varFrees)
8858 "A whole-array start attribute whose dimension is not constant, so it was not
8859 expanded into one term per element. The start values live one per scalar
8860 VarsData entry, not contiguously like the value slots, so there is no first
8861 element to build the array from: gather them instead."
8862 ::=
8863 let idx = tempDecl("modelica_integer", &varDecls, &varFrees)
8864 <<
8865 alloc_<%type%>_array(&<%arr%>, <%ndims%>, <%dims%>);
8866 for (<%idx%> = 0; <%idx%> < base_array_nr_of_elements(<%arr%>); <%idx%>++) {
8867 <%if stringEq(type, "string")
8868 then 'omc_string_store(((modelica_string*)<%arr%>.data) + <%idx%>, <%startArrayElement(cr, type, idx)%>);'
8869 else '((modelica_<%type%>*)<%arr%>.data)[<%idx%>] = <%startArrayElement(cr, type, idx)%>;'%>
8870 }<%\n%>
8871 >>
8872 end startArrayGather;
8873
8874 24 template startArrayScatter(ComponentRef cr, Text type, Text arr, Text &varDecls, Text &varFrees)
8875 "The dual of startArrayGather. Each scalar owns its start attribute, so there
8876 is no array to copy into: write them one at a time."
8877 ::=
8878 let idx = tempDecl("modelica_integer", &varDecls, &varFrees)
8879 <<
8880 <%startArrayScatterEnsureSize(cr, type, arr)%>
8881 for (<%idx%> = 0; <%idx%> < base_array_nr_of_elements(<%arr%>); <%idx%>++) {
8882 <%if stringEq(type, "string")
8883 then 'omc_string_store(&(<%startArrayElement(cr, type, idx)%>), ((modelica_string*)<%arr%>.data)[<%idx%>]);'
8884 else '<%startArrayElement(cr, type, idx)%> = ((modelica_<%type%>*)<%arr%>.data)[<%idx%>];'%>
8885 }<%\n%>
8886 >>
8887 end startArrayScatter;
8888
8889 2 template startArrayEnsureSize(ComponentRef cr)
8890 "The start attribute of an array variable might only hold a broadcast value or
8891 the values of an inner dimension. Before start values of the whole array are
8892 written into it, it has to hold one element per array element."
8893 ::=
8894 match getDimensionSizes(crefTypeFull(crefStripSubs(popCref(cr))))
8895 case sizes as _::_ then
8896 match cref2simvar(crefStripSubs(popCref(cr)), getSimCode())
8897 case var as SIMVAR(__) then
8898 let ty = crefShortType(name)
8899 match ty
8900 case "real"
8901 case "integer"
8902 case "boolean" then
8903 let &nosub = buffer ""
8904 let size = if isSymbolicArrayVar(var) then varSizeRuntime(var) else (sizes ; separator="*")
8905 '<%ty%>_array_ensure_size(&<%varAttributes(var, &nosub)%>.start, <%size%>);'
8906 else ""
8907 else ""
8908 else ""
8909 end startArrayEnsureSize;
8910
8911 ✗ template varSizeRuntime(SimVar var)
8912 "the number of elements of an array variable at runtime (resizable arrays)"
8913 ::=
8914 let &preExp = buffer ""
8915 let &varDecls = buffer ""
8916 let &varFrees = buffer ""
8917 let &aux = buffer ""
8918 '(<%daeExp(simVarSizeExp(var), contextSimulationNonDiscrete, &preExp, &varDecls, &varFrees, &aux)%>)'
8919 end varSizeRuntime;
8920
8921 24 template startArrayScatterEnsureSize(ComponentRef cr, Text type, Text arr)
8922 "Without --simCodeScalarize the array is one VarsData entry. Its start
8923 attribute may hold a single value for all elements (each), so it gets one per
8924 element before they are written."
8925 ::=
8926 match getSimCode()
8927 case SIMCODE(scalarized=false) then
8928 if boolNot(stringEq(type, "string")) then
8929 match cref2simvar(crefStripSubs(popCref(cr)), getSimCode())
8930 case var as SIMVAR(__) then
8931 '<%type%>_array_ensure_size(&data->modelData-><%varArrayName(var)%>Data[<%index%>].attribute.start, base_array_nr_of_elements(<%arr%>));'
8932 end startArrayScatterEnsureSize;
8933
8934 52 template startArrayElement(ComponentRef cr, Text type, Text idx)
8935 "Element `idx`'s start attribute. With --simCodeScalarize the array's elements
8936 are consecutive VarsData entries, each holding its own. Without, the array is
8937 one entry whose start attribute holds one value per element, or a single value
8938 for all of them (each)."
8939 ::=
8940 match cref2simvar(crefStripSubs(popCref(cr)), getSimCode())
8941 case var as SIMVAR(__) then
8942 if intLt(index,0) then error(sourceInfo(), 'startArrayElement got negative index=<%index%> for <%CodegenUtil.crefStr(name)%>') else
8943 match getSimCode()
8944 case SIMCODE(scalarized=false) then
8945 let entry = 'data->modelData-><%varArrayName(var)%>Data[<%index%>].attribute.start'
8946 '((modelica_<%type%>*)(<%entry%>.data))[(<%idx%>) % base_array_nr_of_elements(<%entry%>)]'
8947 else
8948 let entry = 'data->modelData-><%varArrayName(var)%>Data[<%index%> + <%idx%>].attribute.start'
8949 '((modelica_<%type%>*)(<%entry%>.data))[0]'
8950 end startArrayElement;
8951
8952 25540 template varArrayName(SimVar var)
8953 ::=
8954 match var
8955 case SIMVAR(varKind=PARAM()) then '<%crefShortType(name)%>Parameter'
8956 case SIMVAR(__) then '<%crefShortType(name)%>Vars'
8957 end varArrayName;
8958
8959 5707 template crefVarInfo(ComponentRef cr)
8960 "C code to access info element of component reference."
8961 ::=
8962 match cref2simvar(cr, getSimCode())
8963 case var as SIMVAR(__) then
8964 if intLt(index,0) then
8965 error(sourceInfo(), 'crefVarInfo got negative index=<%index%> for <%CodegenUtil.crefStr(name)%>')
8966 else
8967 'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .info'
8968 end crefVarInfo;
8969
8970 668 template crefVarDimension(ComponentRef cr)
8971 "C code to access dimension attribute of component reference"
8972 ::=
8973 match cref2simvar(cr, getSimCode())
8974 case var as SIMVAR(__) then
8975 if intLt(index,0) then
8976 error(sourceInfo(), 'crefVarDimension got negative index=<%index%> for <%CodegenUtil.crefStr(name)%>')
8977 else
8978 'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .dimension'
8979 end crefVarDimension;
8980
8981 7331 template lsVarKind(SimVar var)
8982 "var_kind enum constant matching this var, for initializeStaticLSVars."
8983 ::=
8984 match var
8985 case SIMVAR(varKind=PARAM()) then 'VAR_KIND_PARAMETER'
8986 case SIMVAR(__) then 'VAR_KIND_VARIABLE'
8987 end lsVarKind;
8988
8989 1053 template initializeStaticLSVars(list<SimVar> vars, Integer index)
8990 ::=
8991 let len = listLength(vars)
8992 let indices = (vars |> var as SIMVAR(__) => '<%index%> /* <%crefCComment(var, crefStrNoUnderscore(name))%> */' ;separator=",\n")
8993 // A torn linear system's own iteration variables can be `fixed=false`
8994 // PARAMETERS (solved via an initial-equation call, e.g. a filter's
8995 // coefficient array) rather than ordinary VARIABLEs -- their scalar
8996 // index lives in realParamsIndex/nParametersReal, a completely
8997 // different space than realVarsIndex/nVariablesReal. Hardcoding
8998 // VAR_KIND_VARIABLE here (as opposed to the equivalent, correct
8999 // per-var dispatch in generateStaticInitialData for NONLINEAR_SYSTEM_DATA)
9000 // looked up a variable-space index using a parameter-space index value,
9001 // failing getNominalFromScalarIdx's out-of-bounds assertion whenever the
9002 // parameter index exceeds nVariablesReal.
9003 let kinds = (vars |> var as SIMVAR(__) => lsVarKind(var) ;separator=",\n")
9004 <<
9005 void initializeStaticLSData<%index%>(DATA* data, threadData_t* threadData, LINEAR_SYSTEM_DATA* linearSystemData, modelica_boolean initSparsePattern)
9006 {
9007 const int indices[<%len%>] = {
9008 <%indices%>
9009 };
9010 const enum var_kind kinds[<%len%>] = {
9011 <%kinds%>
9012 };
9013 for (int i = 0; i < <%len%>; ++i) {
9014 if (indices[i] < 0) {
9015 linearSystemData->nominal[i] = 1.0;
9016 linearSystemData->min[i] = -DBL_MAX;
9017 linearSystemData->max[i] = DBL_MAX;
9018 } else {
9019 linearSystemData->nominal[i] = getNominalFromScalarIdx(data->simulationInfo, data->modelData, kinds[i], indices[i]);
9020 linearSystemData->min[i] = getMinFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, kinds[i], indices[i]);
9021 linearSystemData->max[i] = getMaxFromScalarIdx(data->simulationInfo, data->modelData, VAR_TYPE_REAL, kinds[i], indices[i]);
9022 }
9023 }
9024 }
9025 >>
9026 end initializeStaticLSVars;
9027
9028 10803 template crefIndexWithComment(ComponentRef cr)
9029 ::=
9030 match cref2simvar(crefRemovePrePrefix(cr), getSimCode())
9031 case SIMVAR(index=-1) then crefIndexWithComment(crefRemovePrePrefix(name))
9032 case var as SIMVAR(__) then '<%index%> /* <%crefCComment(var, crefStrNoUnderscore(name))%> */'
9033 end crefIndexWithComment;
9034
9035 17790 template varAttributes(SimVar var, Text &sub)
9036 ::=
9037 let arr = '<%if stringEq(&sub, "") then "" else "&" %>'
9038 match var
9039 case SIMVAR(index=-1) then crefAttributes(name) // input variable? pass subs!!!
9040 case SIMVAR(__) then
9041 '(<%arr%>data->modelData-><%varArrayName(var)%>Data[<%index%>]<%crefCCommentWithVariability(var)%>)<%sub%>.attribute '
9042 end varAttributes;
9043
9044 1403 template crefAttributes(ComponentRef cr)
9045 ::=
9046 match cref2simvar(crefRemovePrePrefix(cr), getSimCode())
9047 case var as SIMVAR(index=-1, varKind=JAC_VAR()) then "dummyREAL_ATTRIBUTE"
9048 case var as SIMVAR(__) then
9049 if intLt(index,0) then error(sourceInfo(), 'varAttributes got negative index=<%index%> for <%CodegenUtil.crefStr(name)%>') else
9050 'data->modelData-><%varArrayName(var)%>Data[<%index%>] /* <%crefCComment(var, crefStrNoUnderscore(name))%> */ .attribute'
9051 end crefAttributes;
9052
9053 3622 template typeCastContext(Context context, Type ty)
9054 "Generates code for type cast to basic data types."
9055 ::=
9056 match ty
9057 case T_INTEGER(__)
9058 case T_ENUMERATION(__) then "(modelica_integer)"
9059 case T_REAL(__) then "(modelica_real)"
9060 case T_BOOL(__) then "(modelica_boolean)"
9061 end match
9062 end typeCastContext;
9063
9064
9065 310573 template typeCastContextInt(Context context, Type ty)
9066 "Generates code for type cast to basic data types."
9067 ::=
9068 match ty
9069 // case T_INTEGER(__)
9070 case T_ENUMERATION(__) then "(modelica_integer)"
9071 end match
9072 end typeCastContextInt;
9073
9074 annotation(__OpenModelica_Interface="codegen_cfunctions");
9075 end CodegenCFunctions;
9076
9077 // vim: filetype=susan sw=2 sts=2
9078