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 |