Linux GNU 11.4.0 Code Coverage Report


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

OMCompiler/Compiler/Template/GenerateAPIFunctionsTpl.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 package GenerateAPIFunctionsTpl
37
38 import interface SimCodeTV;
39 import CodegenUtil.*;
40
41 ✗ template getCevalScriptInterface(list<DAE.Type> tys)
42 ::=
43 let funcs = tys |> ty as T_FUNCTION(__) => '<%getCevalScriptInterfaceFunc(AbsynUtil.pathLastIdent(path), ty.funcArg, ty.funcResultType)%><%\n%>'
44 <<
45 import Absyn;
46 import AbsynUtil;
47 import CevalScript;
48 import Parser;
49
50 protected
51
52 import Values;
53 import ValuesMake;
54 import ValuesUtil;
55 constant Absyn.Msg dummyMsg = Absyn.MSG(SOURCEINFO("<interactive>",false,1,1,1,1,0.0));
56
57 public
58
59 <%funcs%>
60 >>
61 end getCevalScriptInterface;
62
63 ✗ template getInType(DAE.Type ty)
64 ::=
65 match ty
66 case T_STRING(__) then "String"
67 case T_INTEGER(__) then "Integer"
68 case T_BOOL(__) then "Boolean"
69 case T_REAL(__) then "Real"
70 case aty as T_ARRAY(__) then 'list<<%getInType(aty.ty)%>>'
71 case T_CODE(ty=C_TYPENAME(__)) then "String"
72 else error(sourceInfo(), 'getInType failed for <%unparseType(ty)%>')
73 end getInType;
74
75 ✗ template getInValue(Text name, DAE.Type ty)
76 ::=
77 match ty
78 case T_STRING(__) then 'Values.STRING(<%name%>)'
79 case T_INTEGER(__) then 'Values.INTEGER(<%name%>)'
80 case T_BOOL(__) then 'Values.BOOL(<%name%>)'
81 case T_REAL(__) then 'Values.REAL(<%name%>)'
82 case aty as T_ARRAY(__) then 'ValuesMake.makeArray(list(<%getInValue('<%name%>_iter', aty.ty)%> for <%name%>_iter in <%name%>))'
83 case T_CODE(ty=C_TYPENAME(__)) then 'Values.CODE(Absyn.C_TYPENAME(Parser.stringPath(<%name%>)))'
84 else error(sourceInfo(), 'getInValue failed for <%unparseType(ty)%>')
85 end getInValue;
86
87 ✗ template getOutValue(Text name, DAE.Type ty, Text &varDecl, Text &postMatch)
88 ::=
89 match ty
90 case T_STRING(__) then 'Values.STRING(<%name%>)'
91 case T_INTEGER(__) then 'Values.INTEGER(<%name%>)'
92 case T_BOOL(__) then 'Values.BOOL(<%name%>)'
93 case T_REAL(__) then 'Values.REAL(<%name%>)'
94 case aty as T_ARRAY(__) then
95 let &varDecl += 'Values.Value <%name%>_arr;<%\n%>'
96 let &postMatch += '<%name%> := <%getOutValueArray('<%name%>_arr', aty)%>;<%\n%>'
97 '<%name%>_arr'
98
99 case T_CODE(ty=C_TYPENAME(__)) then
100 let &varDecl += 'Absyn.Path <%name%>_path;<%\n%>'
101 let &postMatch += '<%name%> := AbsynUtil.pathString(<%name%>_path);<%\n%>'
102 'Values.CODE(Absyn.C_TYPENAME(path=<%name%>_path))'
103 else error(sourceInfo(), 'getOutValue failed for <%unparseType(ty)%>')
104 end getOutValue;
105
106 ✗ template getOutValueArray(Text name, DAE.Type ty)
107 ::=
108 match ty
109 case T_STRING(__) then 'match <%name%> case Values.STRING() then <%name%>.string; end match'
110 case T_INTEGER(__) then 'match <%name%> case Values.INTEGER() then <%name%>.integer; end match'
111 case T_BOOL(__) then 'match <%name%> case Values.BOOL() then <%name%>.boolean; end match'
112 case T_REAL(__) then 'match <%name%> case Values.REAL() then <%name%>.real; end match'
113 case aty as T_ARRAY(__) then
114 'list(<%getOutValueArray('<%name%>_iter', aty.ty)%> for <%name%>_iter in ValuesUtil.arrayValues(<%name%>))'
115 case T_CODE(ty=C_TYPENAME(__)) then
116 'ValuesUtil.valString(<%name%>)'
117 else error(sourceInfo(), 'getOutValueArray failed for <%unparseType(ty)%>')
118 end getOutValueArray;
119
120 ✗ template getCevalScriptInterfaceFunc(String name, list<DAE.FuncArg> args, DAE.Type res)
121 ::=
122 let &varDecl = buffer ""
123 let &postMatch = buffer ""
124 let inVals = args |> arg as FUNCARG(__) => getInValue(arg.name, arg.ty) ; separator=", "
125 let outVals = match res
126 case T_TUPLE(__) then 'Values.TUPLE({<%types |> ty hasindex i fromindex 1 => getOutValue('res<%i%>', ty, &varDecl, &postMatch) ; separator=", "%>})'
127 case T_NORETCALL(__) then "Values.NORETCALL()"
128 else '<%getOutValue("res", res, &varDecl, &postMatch)%>'
129 <<
130 function <%name%>
131 <%args |> arg as FUNCARG(__) =>
132 'input <%getInType(arg.ty)%> <%arg.name%>;' ; separator="\n" %>
133 <%
134 match res
135 case T_TUPLE(__) then (types |> ty hasindex i fromindex 1 => 'output <%getInType(ty)%> res<%i%>;' ; separator="\n")
136 case T_NORETCALL(__) then ""
137 else 'output <%getInType(res)%> res;'
138 %>
139 <%if varDecl then
140 <<
141 protected
142 <%varDecl%>
143 >>
144 %>
145 algorithm
146 (_,<%outVals%>) := CevalScript.cevalInteractiveFunctions2(FCore.emptyCache(), FGraph.empty(), "<%name%>", {<%inVals%>}, dummyMsg);
147 <%postMatch%>
148 end <%name%>;<%\n%>
149 >>
150 end getCevalScriptInterfaceFunc;
151
152 ✗ template getQtInterface(list<DAE.Type> tys, String classNameWithColons, String className)
153 ::=
154 let funcs = tys |> ty as T_FUNCTION(__) => '<%getQtInterfaceFunc(AbsynUtil.pathLastIdent(path), ty.funcArg, ty.funcResultType, classNameWithColons)%><%\n%>'
155 <<
156 /* generated by OpenModelica */
157
158 #include <stdexcept>
159 #include "OpenModelicaScriptingAPIQt.h"
160
161 <%classNameWithColons%><%className%>(threadData_t *td)
162 : threadData(td)
163 {
164 }
165 <%funcs%>
166
167 >>
168 end getQtInterface;
169
170 ✗ template getQtInterfaceHeaders(list<DAE.Type> tys, String className)
171 ::=
172 let heads = tys |> ty as T_FUNCTION(__) => '<%getQtInterfaceHeader(AbsynUtil.pathLastIdent(path), "", ty.funcArg, ty.funcResultType, className, true)%>;<%\n%>'
173 <<
174 /* generated by OpenModelica */
175 #ifndef OpenModelicaScriptingAPIQt__H
176 #define OpenModelicaScriptingAPIQt__H
177
178 #include <QOpenGLContext> // must be first include to fix undefined GLDEBUGPROC
179 #include <QtCore>
180 /* import the scripting here */
181 #define IMPORT_INTO
182 #include "OpenModelicaScriptingAPI.h"
183
184 class <%className%> : public QObject
185 {
186 Q_OBJECT
187 public:
188 threadData_t *threadData;
189 <%className%>(threadData_t *td);
190 <%heads%>
191 signals:
192 void logCommand(QString command);
193 // elapsed time in seconds
194 void logResponse(QString command, QString response, double elapsed);
195 void throwException(QString exception);
196 };
197
198 #endif /* OpenModelicaScriptingAPIQt__H */
199 >>
200 end getQtInterfaceHeaders;
201
202 ✗ template getQtType(DAE.Type ty)
203 ::=
204 match ty
205 case T_STRING(__) then "QString"
206 case T_INTEGER(__) then "modelica_integer"
207 case T_BOOL(__) then "modelica_boolean"
208 case T_REAL(__) then "modelica_real"
209 case aty as T_ARRAY(__) then 'QList<<%getQtType(aty.ty)%> >'
210 case T_CODE(ty=C_TYPENAME(__)) then "QString"
211 else error(sourceInfo(), 'getQtType failed for <%unparseType(ty)%>')
212 end getQtType;
213
214 ✗ template getQtTupleTypeOutputNameHelper(Option<list<String>> names, Integer index)
215 ::=
216 match names
217 case SOME(lst) then listGet(lst, index)
218 else 'res<%index%>'
219 end getQtTupleTypeOutputNameHelper;
220
221 ✗ template getQtTupleTypeOutputName(DAE.Type ty, Integer index)
222 ::=
223 match ty
224 case T_TUPLE(__) then getQtTupleTypeOutputNameHelper(names, index)
225 else 'res<%index%>'
226 end getQtTupleTypeOutputName;
227
228 ✗ template structToString(DAE.Type res, DAE.Type ty, Integer index, Text name)
229 ::=
230 match ty
231 case T_CODE(ty=C_TYPENAME(__)) then
232 '<%name%>.append(<%getQtTupleTypeOutputName(res, index)%>);'
233 case T_STRING(__) then
234 '<%name%>.append("\"" + <%getQtTupleTypeOutputName(res, index)%> + "\"");'
235 case T_INTEGER(__)
236 case T_REAL(__) then
237 '<%name%>.append(QString::number(<%getQtTupleTypeOutputName(res, index)%>));'
238 case T_BOOL(__) then
239 '<%name%>.append(<%getQtTupleTypeOutputName(res, index)%> ? "true" : "false");'
240 case aty as T_ARRAY(__) then
241 let varName = '<%getQtTupleTypeOutputName(res, index)%>'
242 let elt = '<%varName%>_elt'
243 let counter = '<%varName%>_i'
244 <<
245 <%name%>.append("{");
246 int <%counter%> = 0;
247 foreach(<%getQtType(aty.ty)%> <%elt%>, <%varName%>) {
248 if (<%counter%>) {
249 <%name%>.append(",");
250 }
251 <%getQtResponseLogText(elt, aty.ty, name)%>
252 <%counter%>++;
253 }
254 <%name%>.append("}");
255 >>
256 else error(sourceInfo(), 'structToString failed for <%unparseType(ty)%>')
257 end structToString;
258
259 ✗ template getQtInterfaceHeader(String name, String prefix, list<DAE.FuncArg> args, DAE.Type res, String className, Boolean addStructs)
260 ::=
261 let inTypes = args |> arg as FUNCARG(__) => '<%getQtType(arg.ty)%> <%arg.name%>' ; separator=", "
262 let outType = match res
263 case T_TUPLE(__) then
264 if addStructs then
265 <<
266 typedef struct <%name%>_res {
267 <%types |> ty hasindex i fromindex 1 => '<%getQtType(ty)%> <%getQtTupleTypeOutputName(res, i)%>;' ; separator="\n" %>
268 QString toString() {
269 QString resultBuffer = "(";
270 <%types |> ty hasindex i fromindex 1 => '<%structToString(res, ty, i, 'resultBuffer')%>' ; separator="\n" + 'resultBuffer.append(",");' + "\n" %>
271 resultBuffer.append(")");
272 return resultBuffer;
273 }
274 } <%name%>_res;
275 <%name%>_res
276 >>
277 else
278 '<%prefix%><%name%>_res'
279 case T_NORETCALL(__) then "void"
280 else '<%getQtType(res)%>'
281 <<
282 <%outType%> <%prefix%><%name%>(<%inTypes%>)
283 >>
284 end getQtInterfaceHeader;
285
286 ✗ template getQtInArg(Text name, DAE.Type ty, Text &varDecl)
287 ::=
288 match ty
289 case T_CODE(ty=C_TYPENAME(__))
290 case T_STRING(__) then
291 let &varDecl += 'QByteArray <%name%>_utf8 = <%name%>.toUtf8();<%\n%>'
292 'mmc_mk_scon(<%name%>_utf8.constData())'
293 case T_INTEGER(__)
294 case T_BOOL(__)
295 case T_REAL(__) then name
296 case aty as T_ARRAY(__) then
297 let &varDecl2 = buffer ""
298 let elt = '<%name%>_elt'
299 let body = getQtInArgBoxed(getQtInArg(elt, aty.ty, varDecl2), aty.ty)
300 let i = '<%name%>_i'
301 let &varDecl +=
302 <<
303 void *<%name%>_lst = mmc_mk_nil();
304 for (int <%i%> = <%name%>.size()-1; <%i%>>=0; <%i%>--) {
305 <%getQtType(aty.ty)%> <%elt%> = <%name%>[<%i%>];
306 <%varDecl2%>
307 <%name%>_lst = mmc_mk_cons(<%body%>, <%name%>_lst);
308 }<%\n%>
309 >>
310 '<%name%>_lst'
311 else error(sourceInfo(), 'getQtInArg failed for <%unparseType(ty)%>')
312 end getQtInArg;
313
314 ✗ template getQtInArgBoxed(Text name, DAE.Type ty)
315 ::=
316 match ty
317 case T_CODE(ty=C_TYPENAME(__))
318 case T_STRING(__)
319 case T_ARRAY(__) then name
320 case T_INTEGER(__)
321 case T_BOOL(__) then 'mmc_mk_icon(<%name%>)'
322 case T_REAL(__) then 'mmc_mk_rcon(<%name%>)'
323 else error(sourceInfo(), 'getQtInArgBoxed failed for <%unparseType(ty)%>')
324 end getQtInArgBoxed;
325
326 ✗ template getQtCommandLogText(Text name, DAE.Type ty, Text commandLog)
327 ::=
328 match ty
329 case T_CODE(ty=C_TYPENAME(__)) then '<%commandLog%>.append(<%name%>);' + "\n"
330 case T_STRING(__) then '<%commandLog%>.append("\"" + <%name%> + "\"");' + "\n"
331 case T_INTEGER(__)
332 case T_REAL(__) then '<%commandLog%>.append(QString::number(<%name%>));' + "\n"
333 case T_BOOL(__) then '<%commandLog%>.append(<%name%> ? "true" : "false");' + "\n"
334 case aty as T_ARRAY(__) then
335 let elt = '<%name%>_elt'
336 let counter = '<%name%>_i'
337 <<
338 <%commandLog%>.append("{");
339 int <%counter%> = 0;
340 foreach(<%getQtType(aty.ty)%> <%elt%>, <%name%>) {
341 if (<%counter%>) {
342 <%commandLog%>.append(",");
343 }
344 <%getQtCommandLogText(elt, aty.ty, commandLog)%>
345 <%counter%>++;
346 }
347 <%commandLog%>.append("}");
348 >>
349 else error(sourceInfo(), 'getQtCommandLogText failed for <%unparseType(ty)%>')
350 end getQtCommandLogText;
351
352 ✗ template getQtOutArg(Text name, Text shortName, DAE.Type ty, Text &varDecl, Text &postCall)
353 ::=
354 match ty
355 case T_CODE(ty=C_TYPENAME(__))
356 case T_STRING(__) then
357 let &varDecl += 'void *<%shortName%>_mm = NULL;<%\n%>'
358 let &postCall += '<%name%> = QString::fromUtf8((char*)MMC_STRINGDATA(<%shortName%>_mm));<%\n%>'
359 '<%shortName%>_mm'
360 case T_INTEGER(__)
361 case T_BOOL(__)
362 case T_REAL(__) then '<%name%>'
363 case aty as T_ARRAY(__) then
364 let &varDecl += 'void *<%shortName%>_mm = NULL;<%\n%>'
365 let &postCall += getQtOutArgArray(name, shortName, '<%shortName%>_mm', aty)
366 '<%shortName%>_mm'
367 else error(sourceInfo(), 'getQtOutArg failed for <%unparseType(ty)%>')
368 end getQtOutArg;
369
370 ✗ template getQtOutArgArray(Text name, Text shortName, Text mm, DAE.Type ty)
371 ::=
372 match ty
373 case T_CODE(ty=C_TYPENAME(__))
374 case T_STRING(__) then '<%name%> = MMC_STRINGDATA(<%mm%>);<%\n%>'
375 case T_INTEGER(__) then '<%name%> = mmc_unbox_integer(<%mm%>);<%\n%>'
376 case T_BOOL(__) then '<%name%> = mmc_unbox_boolean(<%mm%>);<%\n%>'
377 case T_REAL(__) then '<%name%> = mmc_unbox_real(<%mm%>);<%\n%>'
378 case aty as T_ARRAY(__) then
379 let elt = '<%shortName%>_elt'
380 <<
381 <%name%>.clear();
382 while (!listEmpty(<%mm%>)) {
383 <%getQtType(aty.ty)%> <%elt%>;
384 <%getQtOutArgArray(elt, elt, 'MMC_CAR(<%mm%>)', aty.ty)%>
385 <%name%>.push_back(<%elt%>);
386 <%mm%> = MMC_CDR(<%mm%>);
387 }<%\n%>
388 >>
389 else error(sourceInfo(), 'getOutValueArray failed for <%unparseType(ty)%>')
390 end getQtOutArgArray;
391
392 ✗ template getQtResponseLogText(Text name, DAE.Type ty, Text responseLog)
393 ::=
394 match ty
395 case T_CODE(ty=C_TYPENAME(__)) then '<%responseLog%>.append(<%name%>);' + "\n"
396 case T_STRING(__) then '<%responseLog%>.append("\"" + <%name%> + "\"");' + "\n"
397 case T_INTEGER(__)
398 case T_REAL(__) then '<%responseLog%>.append(QString::number(<%name%>));' + "\n"
399 case T_BOOL(__) then '<%responseLog%>.append(<%name%> ? "true" : "false");' + "\n"
400 case T_TUPLE(__) then '<%responseLog%>.append(<%name%>.toString());' + "\n"
401 case aty as T_ARRAY(__) then
402 let elt = '<%name%>_elt'
403 let counter = '<%name%>_i'
404 <<
405 <%responseLog%>.append("{");
406 int <%counter%> = 0;
407 foreach(<%getQtType(aty.ty)%> <%elt%>, <%name%>) {
408 if (<%counter%>) {
409 <%responseLog%>.append(",");
410 }
411 <%getQtResponseLogText(elt, aty.ty, responseLog)%>
412 <%counter%>++;
413 }
414 <%responseLog%>.append("}");
415 >>
416 else error(sourceInfo(), 'getQtResponseLogText failed for <%unparseType(ty)%>')
417 end getQtResponseLogText;
418
419 ✗ template getQtInterfaceFunc(String name, list<DAE.FuncArg> args, DAE.Type res, String className)
420 ::=
421 let &varDecl = buffer ""
422 let &responseLog = buffer ""
423 let &postCall = buffer ""
424 let inArgs = args |> arg as FUNCARG(__) => ', <%getQtInArg(arg.name, arg.ty, varDecl)%>'
425 let &commandLog = buffer ""
426 let &commandLog += args |> arg as FUNCARG(__) => getQtCommandLogText(arg.name, arg.ty, 'commandLog') ; separator='commandLog.append(",");' + "\n"
427 let &outArg = buffer ""
428 let outArgs = (match res
429 case T_NORETCALL(__) then
430 ""
431 case t as T_TUPLE(types=type1::types2) then
432 let &varDecl += '<%name%>_res result;<%\n%>'
433 let &responseLog += '<%getQtResponseLogText('result', res, 'responseLog')%>'
434 let &outArg += '<%getQtOutArg('result.<%getQtTupleTypeOutputName(res, 1)%>', 'out1', type1, varDecl, postCall)%> = '
435 (types2 |> t hasindex i1 fromindex 2 => ', &<%getQtOutArg('result.<%getQtTupleTypeOutputName(res, i1)%>', 'out<%i1%>', t, varDecl, postCall)%>')
436 else
437 let &varDecl += '<%getQtType(res)%> result;<%\n%>'
438 let &responseLog += '<%getQtResponseLogText('result', res, 'responseLog')%>'
439 let &outArg += '<%getQtOutArg('result', 'result', res, varDecl, postCall)%> = '
440 ""
441 )
442 <<
443 <%getQtInterfaceHeader(name, '<%className%>', args, res, className, false)%>
444 {
445 QElapsedTimer commandTime;
446 commandTime.start();
447 <%if intGt(listLength(args), 0) then
448 <<
449 QString commandLog;
450 <%commandLog%>
451 emit logCommand("<%replaceDotAndUnderscore(name)%>("+commandLog+")");
452 >> else
453 <<
454 emit logCommand("<%replaceDotAndUnderscore(name)%>()");
455 >>%>
456
457 <%varDecl%>
458
459 try {
460 MMC_TRY_TOP_INTERNAL()
461
462 <%outArg%>omc_OpenModelicaScriptingAPI_<%replaceDotAndUnderscore(name)%>(threadData<%inArgs%><%outArgs%>);
463 <%postCall%>
464
465 MMC_CATCH_TOP()
466 } catch(std::exception &exception) {
467 emit throwException(QString("<%replaceDotAndUnderscore(name)%> failed. %1").arg(exception.what()));
468 }
469
470 QString responseLog;
471 <%responseLog%>
472 double elapsed = (double)commandTime.elapsed() / 1000.0;
473 <%if intGt(listLength(args), 0) then
474 <<
475 emit logResponse("<%replaceDotAndUnderscore(name)%>("+commandLog+")", responseLog, elapsed);
476 >> else
477 <<
478 emit logResponse("<%replaceDotAndUnderscore(name)%>()", responseLog, elapsed);
479 >>%>
480
481 <%if outArg then "return result;"%>
482 }
483 >>
484 end getQtInterfaceFunc;
485
486 annotation(__OpenModelica_Interface="backend_tools");
487 end GenerateAPIFunctionsTpl;
488
489 // vim: filetype=susan sw=2 sts=2
490