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 / 35
Functions: -% 0 / 0 / 0
Branches: -% 0 / 0 / 0

OMCompiler/Compiler/Template/CodegenMidToC.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 CodegenMidToC
37
38 // import CodegenUtil.*;
39 import interface MidCodeTV;
40 import interface SimCodeTV;
41
42 /*
43 maybe do
44 - make a genGoto that generates empty statement if target is next block
45 */
46
47 ✗ template genProgram(MidCode.Program p)
48 ::=
49 match p
50 case MidCode.PROGRAM(__) then
51 <<
52 // number of functions: <% listLength(functions) %>
53 #include "<%name%>.h"
54 #include "util/modelica.h"
55
56 #include "<%name%>_includes.h"
57
58 <% functions |> fn => genFunction(fn) ; separator="\n\n"%>
59 >>
60 end match
61 end genProgram;
62
63 /*
64 template genGlobalDef(Literal lit)
65 ::=
66 match lit
67 case LITSTRING(var=var,value_=value_) then
68 let name = genVarName(var)
69 let dataName = <<_OMC_LIT_DATA_<%name%>>> //<<_OMC_LIT<%name%>_data>>
70 let structName = <<_OMC_LIT_STRUCT_<%name%>>>//<<_OMC_LIT_STRUCT<%name%>>>
71 let escaped = Util.escapeModelicaStringToCString(value_)
72 let escapedLength = System.unescapedStringLength(escaped) // =listLength(value_)?
73 <<
74 #define <%dataName%> "<%escaped%>"
75 static const OMC_DEFSTRINGLIT(<%structName%>,<%escapedLength%>,<%dataName%>);
76 #define <%name%> OMC_REFSTRINGLIT(<%structName%>)
77
78 >>
79 case LITRECORD(var=var,args=args) then
80 match var case MidCode.VAR(name=_,ty =ty as DAE.T_METARECORD(__)) then
81 let name = genVarName(var)
82 let dataName = <<_OMC_LIT_DATA_<%name%>>>
83 let structName = <<_OMC_LIT_STRUCT_<%name%>>>
84 <<
85 static const OMC_DEFBOXLIT(<%structName%>,<%ty.index%>,<%listLength(args)%>) {<%args |> arg => genVarName(arg) ; separator=","%>}};
86 #define <%name%> OMC_REFBOXLIT(<%structName%>)
87
88 >>
89 end match
90 else "notimplemented"
91 end match
92 end genGlobalDef;
93 */
94
95 ✗ template genFunction(MidCode.Function fn)
96 "Generates the body for a Modelica/MetaModelica function."
97 ::=
98 /*
99 The function should accept a thread_data argument.
100 The inputs are normal arguments.
101 The first output is the return value of the function.
102 The rest of the outputs are passed as pointers to the funtion.
103 If there is no output return void?
104 */
105 match fn
106 case MidCode.FUNCTION(__) then
107 let returnType = if listEmpty(outputs) then "void" else genVarType(listHead(outputs))
108
109 let arguments = {
110 ("threadData_t *threadData"),
111 (inputs |> i => <<<%genVarType(i)%> <%genVarName(i)%>>> ; separator=", "),
112 (List.restOrEmpty(outputs) |> o => <<<%genVarType(o)%> *outPtr_<%genVarName(o)%>>> ; separator=", ") // TODO: this might not be a great way to pointerify a type
113 } ; separator=",\n "
114
115 <<
116 <%returnType%> omc_<%underscorePath(name)%>(<%arguments%>)
117 {
118 <% genLocalDecls(fn, locals, localBufs, localBufPtrs)%>
119 <% genEntry(fn) %>
120 <% genBlocks(fn,body) %>
121 <% genExit(fn) %>
122 }
123
124 <%genInFunction(fn)%>
125 <%genBoxPtrFunction(fn)%>
126
127 >>
128
129 end match
130 end genFunction;
131
132 ✗ template genInFunction(MidCode.Function fn)
133 ::=
134 match fn
135 case MidCode.FUNCTION(__) then
136 let inputDefs = (inputs |> i => <<<%genVarType(i)%> <%genVarName(i)%>;>>; separator="\n")
137 let outputDefs = (outputs |> o => <<<%genVarType(o)%> <%genVarName(o)%>;>>; separator="\n")
138 let inputLines = (inputs |> i => <<if(<%varModelicaRead(i)%>) return 1;>>; separator="\n")
139 let outputLines = (outputs |> o => <<<%varModelicaWrite(o)%>;>>; separator="\n")
140 let callretval = if not listEmpty(outputs) then <<<%genVarName(listHead(outputs))%> = >>
141 let callargs = {
142 ("threadData"),
143 (inputs |> i => <<<%genVarName(i)%>>> ; separator=", "),
144 (List.restOrEmpty(outputs) |> o => <<&<%genVarName(o)%>>> ; separator=", ")
145 } ; separator=",\n "
146 <<
147 int in_<%underscorePath(name)%>(threadData_t *threadData, type_description *inArgs, type_description *outVar)
148 {
149 <%inputDefs%>
150 <%outputDefs%>
151 <%inputLines%>
152 OMC_TRY_TOP_INTERNAL()
153 <%callretval%>omc_<%underscorePath(name)%>(<%callargs%>);
154 OMC_CATCH_TOP(return 1)
155 <%outputLines%>
156 <%if listEmpty(outputs) then "write_noretcall(outVar);"%>
157 fflush(NULL);
158 return 0;
159 }
160 >>
161 end match
162 end genInFunction;
163
164 ✗ template genBoxPtrFunction(MidCode.Function fn)
165 ::=
166 match fn
167 case MidCode.FUNCTION(__) then
168 let returnType = if listEmpty(outputs) then "void" else "modelica_metatype"
169
170 let arguments = {
171 ("threadData_t *threadData"),
172 (inputs |> i => <<modelica_metatype <%genVarName(i)%>>> ; separator=", "),
173 (List.restOrEmpty(outputs) |> o => <<modelica_metatype *out_<%genVarName(o)%>>> ; separator=", ")
174 } ; separator=",\n "
175
176 let unboxDefs = ( inputs |> i =>
177 if varBoxType(i) then <<<%genVarType(i)%> unbox_<%genVarName(i)%>;>> ; separator="\n")
178
179 let callOutDefs = ( outputs |> o =>
180 if varBoxType(o) then <<<%genVarType(o)%> <%genVarName(o)%>;>> ; separator="\n")
181
182 let boxDefs = if not listEmpty(outputs) then <<modelica_metatype out_<%genVarName(listHead(outputs))%>;<%"\n"%>>>
183
184 let unboxes = ( inputs |> i =>
185 if varBoxType(i) then <<unbox_<%genVarName(i)%> = <%varUnbox2(i)%>;>> ; separator="\n")
186
187 let callretval = if not listEmpty(outputs) then <<<%if not varBoxType(listHead(outputs)) then "out_"%><%genVarName(listHead(outputs))%> = >>
188 let callvars = {
189 ("threadData"),
190 (inputs |> i => <<<%if varBoxType(i) then "unbox_"%><%genVarName(i)%>>> ; separator=", "),
191 (List.restOrEmpty(outputs) |> o => <<<%if varBoxType(o) then "&" else "out_"%><%genVarName(o)%>>> ; separator=", ")
192 } ; separator=",\n "
193
194 let boxes = {
195 (if not listEmpty(outputs) then (if varBoxType(listHead(outputs)) then <<out_<%genVarName(listHead(outputs))%> = <%varBox(listHead(outputs))%>;>>)),
196 (List.restOrEmpty(outputs) |> o =>
197 if varBoxType(o) then <<if(out_<%genVarName(o)%>) *out_<%genVarName(o)%> = <%varBox(o)%>;>> )
198 } ; separator="\n"
199
200 <<
201 #undef boxptr_<%underscorePath(name)%>
202 <%returnType%> boxptr_<%underscorePath(name)%>(<%arguments%>)
203 {
204 <%unboxDefs%>
205 <%callOutDefs%>
206 <%boxDefs%>
207 <%unboxes%>
208 <%callretval%>omc_<%underscorePath(name)%>(<%callvars%>);
209 <%boxes%>
210 <% if listEmpty(outputs) then "return;" else "return out_" + genVarName(listHead(outputs)) + ";" %>
211 }
212 >>
213 end match
214 end genBoxPtrFunction;
215
216 ✗ template genLocalDecls(MidCode.Function fn, list<MidCode.Var> locals, list<MidCode.VarBuf> localBufs, list<MidCode.VarBufPtr> localBufPtrs)
217 ::=
218 <<
219 <% locals |> local => genLocalDecl(fn,local) ; separator="\n" %>
220 <% localBufs |> local => genLocalBufDecl(fn,local) ; separator="\n" %>
221 <% localBufPtrs |> local => genLocalBufPtrDecl(fn,local) ; separator="\n" %>
222 >>
223 end genLocalDecls;
224
225 ✗ template genLocalDecl(MidCode.Function fn, MidCode.Var var)
226 ::=
227 <<
228 <% match var case MidCode.VAR(volatile=true) then "volatile " end match %><% genVarType(var) %> <% genVarName(var) %>;
229 >>
230 end genLocalDecl;
231
232 ✗ template genLocalBufDecl(MidCode.Function fn, MidCode.VarBuf var)
233 ::=
234 <<
235 jmp_buf <% genVarBufName(var) %>;
236 >>
237 end genLocalBufDecl;
238
239 ✗ template genLocalBufPtrDecl(MidCode.Function fn, MidCode.VarBufPtr var)
240 ::=
241 <<
242 jmp_buf *<% genVarBufPtrName(var) %>;
243 >>
244 end genLocalBufPtrDecl;
245
246 ✗ template genEntry(MidCode.Function fn)
247 ""
248 ::=
249 match fn
250 case FUNCTION(__) then
251 <<
252 goto <% genLabel(entryId) %>;
253 >>
254 end match
255 end genEntry;
256
257 ✗ template genExit(MidCode.Function fn)
258 ""
259 ::=
260 match fn
261 case FUNCTION(__) then
262 let returnString = if listEmpty(outputs) then "" else genVarName(listHead(outputs))
263 <<
264 <% genLabel(exitId) %>: // exit block
265 <% List.restOrEmpty(outputs) |> v =>
266 let outPtrName = "outPtr_"+ genVarName(v)
267 <<
268 if (<%outPtrName%> != NULL)
269 *<%outPtrName%> = <%genVarName(v)%>;
270 >> ; separator="\n"
271 %>
272 return <%returnString%>;
273 >>
274 end match
275 end genExit;
276
277 ✗ template genBlocks(MidCode.Function fn, list<MidCode.Block> body)
278 ""
279 ::=
280 body |> block => genBlock(fn, block) ; separator="\n"
281 end genBlocks;
282
283 ✗ template genBlock(MidCode.Function fn, MidCode.Block block)
284 ""
285 ::=
286 match block
287 case BLOCK(__) then
288 <<
289 <% genLabel(id) %>:
290 <% stmts |> stmt => genStmt(fn, stmt) ; separator="\n" %>
291 <% genTerminator(fn, terminator) %>
292 >>
293 end match
294 end genBlock;
295
296 ✗ template genLabel(Integer i)
297 ::=
298 <<
299 label_<% i %>
300 >>
301 end genLabel;
302
303 ✗ template genVarName(MidCode.Var v)
304 ::=
305 match v
306 case MidCode.VAR(__)
307 then name
308 end genVarName;
309
310 ✗ template genVarBufName(MidCode.VarBuf v)
311 ::=
312 match v
313 case MidCode.VARBUF(__)
314 then name
315 end genVarBufName;
316
317 ✗ template genVarBufPtrName(MidCode.VarBufPtr v)
318 ::=
319 match v
320 case MidCode.VARBUFPTR(__)
321 then name
322 end genVarBufPtrName;
323
324 ✗ template genStmt(MidCode.Function fn, MidCode.Stmt stmt)
325 ""
326 ::=
327 match stmt
328 case MidCode.NOP(__) then
329 <<
330 ; // NOP
331 >>
332 case MidCode.ASSIGN(
333 dest=MidCode.VAR(name=dest_name,ty=_)
334 ,src=rvalue
335 ) then
336 <<
337 <%dest_name%> = <%genRValue(rvalue)%>;
338 >>
339 end match
340 end genStmt;
341
342 ✗ template genRValue(MidCode.RValue rvalue)
343 ""
344 ::=
345 match rvalue
346 case MidCode.VARIABLE(src=src as MidCode.VAR(name=src_name, ty=_)) then
347 <<
348 <%src_name%>
349 >>
350 case MidCode.BINARYOP(
351 op=op
352 ,lsrc=lsrc as MidCode.VAR(name=lsrc_name,ty=DAE.T_STRING(__))
353 ,rsrc=rsrc as MidCode.VAR(name=rsrc_name,ty=DAE.T_STRING(__))
354 ) then
355 genStringBinaryop(op,lsrc,rsrc)
356 case MidCode.BINARYOP(
357 op=MidCode.POW()
358 ,lsrc=MidCode.VAR(name=lsrc_name, ty=_)
359 ,rsrc=MidCode.VAR(name=rsrc_name, ty=_)) then
360 // TODO: use custom pow for modelica semantics CodegenCFunctions.tpl:4889
361 <<
362 pow(<%lsrc_name%>, <%rsrc_name%>)
363 >>
364 case MidCode.BINARYOP( // c binary ops
365 op=op
366 ,lsrc=MidCode.VAR(name=lsrc_name, ty=_)
367 ,rsrc=MidCode.VAR(name=rsrc_name, ty=_)) then
368 <<
369 <%lsrc_name%> <%binaryopToString(op)%> <%rsrc_name%>
370 >>
371 case MidCode.UNARYOP(op=MidCode.BOX(), src=src) then
372 varBox(src)
373 case MidCode.UNARYOP(op=MidCode.UNBOX(), src=src) then
374 varUnbox(src)
375 case MidCode.UNARYOP(op=op, src=src) then
376 <<
377 (<%genVarType(src)%>) <%unaryopToString(op)%> <%genVarName(src)%>
378 >>
379 case MidCode.LITERALINTEGER(value=value) then
380 <<
381 <%value%>
382 >>
383 case MidCode.LITERALBOOLEAN(value=value) then
384 <<
385 <%if value then 1 else 0%>
386 >>
387 case MidCode.LITERALREAL(value=value) then
388 <<
389 <%value%>
390 >>
391 case MidCode.LITERALSTRING(value=value) then
392 <<
393 mmc_mk_scon("<%Util.escapeModelicaStringToCString(value)%>")
394 >>
395 case MidCode.LITERALMETATYPE(elements=elements,ty=ty) then
396 let metatypeSlots = listLength(elements)
397 let metatypeCtor = genTypeCtorIndex(elements, ty)
398 let elementargs = (elements |> element => <<<%genVarName(element)%>>> ; separator=", ")
399
400 match ty
401 case DAE.T_METARECORD(__) then
402 let arguments = {
403 (<<<%metatypeSlots%>+1>>),
404 (metatypeCtor),
405 (<<&<%genTypeUnderscorePath(ty)%>__desc>>),
406 elementargs
407 } ; separator=", "
408 <<omc_mk_box(<%arguments%>)>>
409 else
410 let arguments = {
411 (<<<%metatypeSlots%>>>),
412 (metatypeCtor),
413 elementargs
414 } ; separator=", "
415 <<omc_mk_box(<%arguments%>)>>
416
417 case MidCode.METAFIELD(src=src, index=index, ty=ty) then
418 <<OMC_BOX_FIELD(<%genVarName(src)%>, <%intAdd(index,1)%>)>>
419 case MidCode.UNIONTYPEVARIANT() then
420 <<(MMC_HDRCTOR(MMC_GETHDR(<%genVarName(src)%>)) - 3)>>
421 case MidCode.ISSOME(src=src) then
422 <<(0==MMC_HDRSLOTS(MMC_GETHDR(<%genVarName(src)%>)) ? 0 : 1)>>
423 case MidCode.ISCONS(src=src) then
424 <<(MMC_GETHDR(<%genVarName(src)%>) == MMC_CONSHDR)>>
425 else "notimplemented"
426 end match
427 end genRValue;
428
429 ✗ template binaryopToString(MidCode.BinaryOp op)
430 ::=
431 match op
432 case MidCode.ADD() then "+"
433 case MidCode.SUB() then "-"
434 case MidCode.MUL() then "*"
435 case MidCode.DIV() then "/"
436 // pow
437 case MidCode.LESS() then "<"
438 case MidCode.LESSEQ() then "<="
439 case MidCode.GREATER() then ">"
440 case MidCode.GREATEREQ() then ">="
441 case MidCode.EQUAL() then "=="
442 case MidCode.NEQUAL() then "!="
443 else "notimplemented"
444 end match
445 end binaryopToString;
446
447 ✗ template unaryopToString(MidCode.UnaryOp op)
448 ::=
449 match op
450 case MidCode.MOVE() then ""
451 case MidCode.UMINUS() then "-"
452 case MidCode.NOT() then "!"
453 else "notimplemented"
454 end match
455 end unaryopToString;
456
457 ✗ template genStringBinaryop(MidCode.BinaryOp op, MidCode.Var lsrc, MidCode.Var rsrc)
458 ::=
459 match op
460 case MidCode.ADD() then
461 <<
462 stringAppend(<%genVarName(lsrc)%>, <%genVarName(rsrc)%>)
463 >>
464 else
465 // TODO:
466 // error checking. sub,mul
467 // could optimise equality? CodegenCFunctions.tpl:5163
468 <<
469 0 <%binaryopToString(op)%> stringCompare(<%genVarName(lsrc)%>, <%genVarName(rsrc)%>)
470 >>
471 end match
472 end genStringBinaryop;
473
474
475 ✗ template genTerminator(MidCode.Function fn, MidCode.Terminator terminator)
476 ""
477 ::=
478 match fn case FUNCTION(locals=_,inputs=_,outputs=_,body=_,entryId=_,exitId=exitId) then
479 // big match expression I guess
480 match terminator
481 case MidCode.RETURN() then
482 <<
483 goto <% genLabel(exitId) %>; // exit label
484 >>
485 case MidCode.GOTO(next=label) then
486 <<
487 goto <% genLabel(label) %>;
488 >>
489 case MidCode.BRANCH(condition=condition,onTrue=labelTrue, onFalse=labelFalse) then
490 <<
491 if (<%genVarName(condition)%>)
492 goto <% genLabel(labelTrue) %>;
493 else
494 goto <% genLabel(labelFalse) %>;
495 >>
496 case MidCode.SWITCH(condition=condition, cases=cases) then
497 <<
498 switch (<%genVarName(condition)%>){
499 <% cases |> (from,to) =>
500 <<
501 case <%from%>: goto <%genLabel(to)%>;
502 >>
503 ; separator="\n" %>
504 }
505 >>
506 case MidCode.CALL(func=func,builtin=builtin,inputs=inputs,outputs=outputs,next=next) then
507 let returnAssignment = match outputs
508 case {} then ""
509 case MidCode.OUT_WILD() :: _ then ""
510 case MidCode.OUT_VAR(var=var) :: _ then <<<%genVarName(var)%> = >>
511
512 let arguments = {
513 (if not builtin then "threadData"),
514 (inputs |> i => genVarName(i) ; separator=", "),
515 (List.restOrEmpty(outputs) |> o => match o case MidCode.OUT_VAR(var=var) then <<&<%genVarName(var)%>>> else "NULL" ; separator=", ")
516 } ; separator=",\n "
517
518 <<
519 <%returnAssignment%><%if not builtin then ("omc_" + underscorePath(func)) else identBuiltinCall(func)%>(<%arguments%>);
520 goto <%genLabel(next)%>;
521 >>
522 /* SimulationRuntime/c/meta/meta_modelica_data.h
523 */
524 case MidCode.LONGJMP() then
525 // old codegen does fail-goto substitution here
526 // INFO: not allowed to throw to same function
527 <<
528 longjmp(*threadData->mmc_jumper,1);
529 >>
530 case MidCode.PUSHJMP(__) then
531 <<
532 // PUSHJMP
533 <% genVarBufPtrName(old_buf) %> = threadData->mmc_jumper;
534 threadData->mmc_jumper = &<% genVarBufName(new_buf) %>;
535 setjmp(&<% genVarBufName(new_buf) %>);
536 goto <%genLabel(next)%>;
537 >>
538 case MidCode.POPJMP(__) then
539 <<
540 // POPJMP
541 threadData->mmc_jumper = <% genVarBufPtrName(old_buf) %>;
542 goto <%genLabel(next)%>;
543 >>
544 else "notimplemented"
545 end match
546 end genTerminator;
547
548 ✗ template genVarType(MidCode.Var var)
549 "Generate the c type for a variable."
550 ::=
551 match var case VAR(name=_,ty=ty) then
552 match ty
553 case DAE.T_INTEGER(__)
554 case DAE.T_ENUMERATION(__) then
555 "modelica_integer"
556 case DAE.T_BOOL(__) then
557 "modelica_boolean"
558 case DAE.T_REAL(__) then
559 "modelica_real"
560 case DAE.T_STRING(__) then
561 "modelica_string"
562 case DAE.T_METABOXED(__)
563 case DAE.T_METARECORD(__)
564 case DAE.T_METATYPE(__)
565 case DAE.T_METAOPTION(__)
566 case DAE.T_METAARRAY(__)
567 case DAE.T_METATUPLE(__)
568 case DAE.T_METAUNIONTYPE(__)
569 case DAE.T_METALIST(__) then
570 "modelica_metatype"
571 case DAE.T_UNKNOWN() then
572 "unknown" //TODO: fail?
573 case DAE.T_METAPOLYMORPHIC(__) then
574 "error_ metapolymorphic"
575 case DAE.T_METAUNIONTYPE(__) then
576 "error_ metauniontype"
577 case DAE.T_ANYTYPE(__) then
578 "error_anytype"
579 case DAE.T_TUPLE(__) then
580 "error_tuple"
581 else "notimplemented"
582 end match
583 end match
584 end genVarType;
585
586 ✗ template genTypeCtorIndex(list<MidCode.Var> elements, DAE.Type ty)
587 "Generate the c-tag that indicates which record of a uniontype we have."
588 ::=
589 match ty
590
591 case DAE.T_METARECORD(__) then intAdd(index,3)
592 case DAE.T_METAARRAY(__) then 2
593 case DAE.T_METATUPLE(__) then 0
594 case DAE.T_METAOPTION(__) then 1
595 case DAE.T_METALIST(__) then (if listLength(elements) then 1 else 0)
596 else 0
597 end match
598 end genTypeCtorIndex;
599
600
601
602 ✗ template genTypeUnderscorePath(DAE.Type ty)
603 "generate underscored path from type"
604 ::=
605 //
606 match ty
607 case T_METARECORD(path=path)
608 then underscorePath(path)
609 case T_COMPLEX(complexClassType = RECORD(path = path), varLst = _)
610 then underscorePath(path)
611 else "error: genTypeUnderscorePath"
612 end match
613 end genTypeUnderscorePath;
614
615 ✗ template varBoxType(MidCode.Var var)
616 ::=
617 match var case VAR(name=_,ty=ty) then
618 match ty
619 case T_INTEGER(__)
620 case T_ENUMERATION(__)
621 case T_BOOL(__)
622 case T_REAL(__) then 'modelica_metatype'
623 end match
624 end match
625 end varBoxType;
626
627 ✗ template varBox(MidCode.Var var)
628 ::=
629 match var case VAR(name=name,ty=ty) then
630 match ty
631 case T_INTEGER(__)
632 case T_ENUMERATION(__) then 'omc_mk_icon(<%name%>)'
633 case T_BOOL(__) then 'omc_mk_icon(<%name%>)'
634 case T_REAL(__) then 'omc_mk_rcon(<%name%>)'
635 case T_STRING(__) then 'omc_mk_string(<%name%>)'
636 case T_COMPLEX(__) then 'omc_mk_box(<%name%>)' //?
637 else name
638 end match
639 end match
640 end varBox;
641
642
643 //TODO: split into two functions
644 //non-metaboxed case only necessary for boxptr/in functions
645 //other should be used for normal code
646 ✗ template varUnbox(MidCode.Var var)
647 ::=
648 match var case VAR(name=name,ty=ty) then
649 match ty
650 case T_METABOXED(ty=T_INTEGER(__))
651 case T_METABOXED(ty=T_ENUMERATION(__))then 'omc_unbox_integer(<%name%>)'
652 case T_METABOXED(ty=T_BOOL(__)) then 'omc_unbox_integer(<%name%>)'
653 case T_METABOXED(ty=T_REAL(__)) then 'omc_unbox_real(<%name%>)'
654 case T_STRING(__) then 'omc_unbox_string(<%name%>)'
655 else name
656 end match
657 end match
658 end varUnbox;
659
660 ✗ template varUnbox2(MidCode.Var var)
661 ::=
662 match var case VAR(name=name,ty=ty) then
663 match ty
664 case T_INTEGER(__)
665 case T_ENUMERATION(__) then 'omc_unbox_integer(<%name%>)'
666 case T_BOOL(__) then 'omc_unbox_integer(<%name%>)'
667 case T_REAL(__) then 'omc_unbox_real(<%name%>)'
668 case T_STRING(__) then 'omc_unbox_string(<%name%>)'
669 else name
670 end match
671 end match
672 end varUnbox2;
673
674 ✗ template varModelicaRead(MidCode.Var var)
675 ::=
676 match var case VAR(name=name,ty=ty) then
677 match ty
678 case T_INTEGER(__) then 'read_modelica_integer(&inArgs, &<%name%>)'
679 case T_BOOL(__) then 'read_modelica_integer(&inArgs, &<%name%>)'
680 case T_REAL(__) then 'read_modelica_real(&inArgs, &<%name%>)'
681 case T_STRING(__) then 'read_modelica_string(&inArgs, &<%name%>)'
682 case T_ENUMERATION(__) then 'read_modelica_integer(&inArgs, &<%name%>)'
683 case T_COMPLEX(__) then 'read_modelica_metatype(&inArgs, &<%name%>)' //?
684 case T_METAUNIONTYPE(__)
685 case T_METALIST(__)
686 case T_METAARRAY(__)
687 case T_METAOPTION(__)
688 case T_METATUPLE(__) then 'read_modelica_metatype(&inArgs, &<%name%>)'
689 end match
690 end match
691 end varModelicaRead;
692
693 ✗ template varModelicaWrite(MidCode.Var var)
694 ::=
695 match var case VAR(name=name,ty=ty) then
696 match ty
697 case T_INTEGER(__) then 'write_modelica_integer(outVar, &<%name%>)'
698 case T_BOOL(__) then 'write_modelica_integer(outVar, &<%name%>)'
699 case T_REAL(__) then 'write_modelica_real(outVar, &<%name%>)'
700 case T_STRING(__) then 'write_modelica_string(outVar, &<%name%>)'
701 case T_ENUMERATION(__) then 'write_modelica_integer(outVar, &<%name%>)'
702 case T_COMPLEX(__) then 'write_modelica_metatype(outVar, &<%name%>)' //?
703 case T_METAUNIONTYPE(__)
704 case T_METALIST(__)
705 case T_METAARRAY(__)
706 case T_METAOPTION(__)
707 case T_METATUPLE(__) then 'write_modelica_metatype(outVar, &<%name%>)'
708 end match
709 end match
710 end varModelicaWrite;
711
712 ✗ template identName(Absyn.Path path)
713 ::=
714 match path
715 case Absyn.IDENT(__) then name
716 end identName;
717
718 ✗ template identBuiltinCall(Absyn.Path path)
719 ::=
720 match path
721 case Absyn.IDENT(name="clock") then "mmc_clock"
722 case Absyn.IDENT(name="anyString") then "mmc_anyString"
723 case Absyn.IDENT(name="fail") then "MMC_THROW_INTERNAL"
724 case Absyn.IDENT(name="intMod") then "modelica_mod_integer"
725 //TODO: print -> puts(omc_string_data(...))
726 //TODO: mmc_get_field (usual macro solution)
727 //TODO: bitwise operators (could be done in DAEToMid instead)
728 //TODO: mod, div, max, min?
729 //needs some more advanced expression generation with arguments as input
730
731 case Absyn.IDENT(__) then name
732
733 end identBuiltinCall;
734
735
736
737 /*
738 ++++++++++++++++++++++++++++++++++++++++
739 Copied from
740 CodegenUtil.tpl
741
742 Don't know how to import across directories.
743 */
744
745 ✗ template replaceDotAndUnderscore(String str)
746 "Replace _ with __ and dot in identifiers with _"
747 ::=
748 match str
749 case name then
750 let str_dots = System.stringReplace(name,".", "_")
751 let str_underscores = System.stringReplace(str_dots, "_", "__")
752 System.unquoteIdentifier(str_underscores)
753 end replaceDotAndUnderscore;
754
755
756 ✗ template underscorePath(Absyn.Path path)
757 "Generate paths with components separated by underscores.
758 Replaces also the . in identifiers with _.
759 The dot might happen for world.gravityAccleration"
760 ::=
761 match path
762 case Absyn.QUALIFIED(__) then
763 '<%replaceDotAndUnderscore(name)%>_<%underscorePath(path)%>'
764 case Absyn.IDENT(__) then
765 replaceDotAndUnderscore(name)
766 case Absyn.FULLYQUALIFIED(__) then
767 underscorePath(path)
768 end underscorePath;
769
770
771 //++++++++++++++++++++++++++++++++++++++++
772
773 annotation(__OpenModelica_Interface="codegen");
774 end CodegenMidToC;
775