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

OMCompiler/Compiler/Template/AbsynToJulia.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 AbsynToJulia
37 "
38 Translates Absyn to Julia.
39 @Authors: John Tinnerholm & Martin Sjoelund
40 "
41 /* TODOS:
42
43 TODO: Public/Private semantics : (
44 TODO: Julia does string concatination with * instead of +
45
46 */
47
48 import interface AbsynToJuliaTV;
49 import AbsynDumpTpl;
50
51 ✗ template dumpProgram(Absyn.Program program)
52 ::=
53 match program
54 case PROGRAM(classes = {}) then ""
55 case PROGRAM(__) then
56 /* Necessary forward declarations */
57 let cls_str = (classes |> cls => dumpClass(cls, defaultDumpOptions) ;separator="\n\n")
58 <<
59 <%cls_str%>
60 >>
61 end dumpProgram;
62
63 ✗ template dumpSCodeElements(list<SCode.Element> elements)
64 "
65 Dumps forward declaration of uniontypes and partial functions unless elements is empty.
66 Recursion needed to find all partial functions!. This should be call on a per module basis"
67 ::= dumpSCodeElements2(filterElements(elements, defaultOptions))
68 end dumpSCodeElements;
69
70 ✗ template dumpSCodeElements2(list<SCode.Element> elements)
71 ::=
72 let str = elements |> el hasindex i1 fromindex 1 =>
73 (
74 match el
75 case CLASS(restriction=SCode.R_UNIONTYPE(__)) then
76 '@UniontypeDecl <%name%> <%\n%>'
77 case CLASS(classDef = parts as SCode.PARTS(__), partialPrefix = SCode.NOT_PARTIAL(), restriction=SCode.R_FUNCTION(__)) then
78 dumpSCodeElements2(parts.elementLst)
79 case CLASS(partialPrefix = SCode.PARTIAL(), restriction=SCode.R_FUNCTION(__)) then
80 '<%name%> = Function<%\n%>'
81 else ''
82 )
83 if str then
84 '<%\n%><%str%>'
85 else ''
86 end dumpSCodeElements2;
87
88 ✗ template dumpClass(Absyn.Class cls, DumpOptions options)
89 /*We do not yet know our context in Absyn */
90 ::= dumpClassElement(cls, options, noContext)
91 end dumpClass;
92
93 ✗ template dumpClassElement(Absyn.Class class, DumpOptions options, Context context)
94 "
95 Note that partial functions are not handled here. They cannot really be translated to Julia in the way they are used in MetaModelica
96 they are dumped as forward decls along with Uniontypes within the packages they occur.
97 "
98 ::=
99 match class
100 case CLASS(body=parts as PARTS(__), restriction=R_UNIONTYPE(__)) then
101 let commentStr = dumpCommentStrOpt(parts.comment)
102 let class_def_str = dumpClassDef(parts, makeUniontypeContext(name), options)
103 <<
104 <%commentStr%>
105 @Uniontype <%name%> begin
106 <%class_def_str%>
107 end
108 >>
109 /* We need to forward declare partial functions in Julia */
110 case CLASS(partialPrefix=true, restriction=R_FUNCTION(__)) then ''
111 case CLASS(partialPrefix=false, body=parts as PARTS(__), restriction=R_FUNCTION(__)) then
112 let commentStr = dumpCommentStrOpt(parts.comment)
113 let returnType = (parts.classParts |> cp => dumpReturnTypeJL(getElementItemsInClassPart(cp)))
114 let return_str = '<%(parts.classParts |> cp => dumpReturnStrJL(getElementItemsInClassPart(cp), functionContext))%>'
115 let inputs_str = (parts.classParts |> cp => dumpInputsJL(getElementItemsInClassPart(cp), inputContext))
116 let typevar_inputs = System.stringReplace(inputs_str, "<:", "")
117 let header = dumpClassHeader(parts, restriction)
118 let functionBodyStr = dumpClassDef(parts, makeFunctionContext(return_str), options)
119 /*
120 Input output variables are treated as parameters
121 output and bidirectional variables occurs as local variables in Julia
122 */
123 <<
124 <%commentStr%>
125 function <%name%>(<%if header then typevar_inputs else inputs_str%>) <%if header then "" else returnType%> <%header%>
126 <%functionBodyStr%>
127 <%return_str%>
128 end
129 >>
130 case CLASS(body=parts as PARTS(__)) then
131 let enc_str = if encapsulatedPrefix then "" /*Should we use a macro here?*/ else ""
132 let partial_str = if partialPrefix then "#=TODO: Originally partial =# " else ""
133 let class_type_str = dumpClassType(restriction)
134 let cdef_str1 = match restriction
135 case R_PACKAGE(__) then
136 dumpClassDef(parts, packageContext, options)
137 case R_RECORD(__) then
138 dumpClassDef(parts, makeUniontypeContext(""), options)
139 else
140 dumpClassDef(parts, context, options)
141 let forwardDeclarations = dumpSCodeElements(AbsynToSCode.translateClassdefElements(parts.classParts))
142 let inform = if forwardDeclarations then
143 '#= Necessary to write declarations for your uniontypes until Julia adds support for mutually recursive types =#'
144 else ''
145 let cdef_str2 = match restriction
146 case R_PACKAGE(__) then
147 <<
148 <%\n%>
149 using MetaModelica
150 #= ExportAll is not good practice but it makes it so that we do not have to write export after each function :( =#
151 using ExportAll
152 <%inform%>
153 <%forwardDeclarations%>
154 <%\n%>
155 <%cdef_str1%>
156 <%\n%>
157 #= So that we can use wildcard imports and named imports when they do occur. Not good Julia practice =#
158 @exportAll()
159 >>
160 else
161 <<
162 <%cdef_str1%>
163 >>
164 let begin_str = match restriction
165 case R_RECORD(__) then 'begin'
166 else ''
167
168 let cdef_str = cdef_str2
169 let cmt_str = dumpCommentStrOpt(parts.comment)
170 /* Investigate header_str and annotation string*/
171 //let ann_str = dumpClassAnnotation(cmt)
172 let header_str = dumpClassHeader(parts, restriction)
173 let footer_str = dumpClassFooter(parts, cdef_str, name, cmt_str, "" /*ann_str*/)
174 let partial_str_and_class_type = '<%partial_str%><%class_type_str%>'
175 <<
176 <%partial_str_and_class_type%> <%name%> <%begin_str%>
177 <%header_str%>
178 <%\n%>
179 <%footer_str%>
180 >>
181 /*Regular type redefinitions*/
182 case CLASS(body=parts as DERIVED(__), restriction=R_TYPE(__)) then
183 /* Derived should have the last context as it's context right? */
184 let comment = dumpCommentOpt(parts.comment, context)
185 let spec = dumpTypeSpec(parts.typeSpec, context)
186 let args = (parts.arguments |> earg => dumpElementArg(earg, context) ;separator=', ')
187 let attr = dumpElementAttr(parts.attributes)
188 <<
189 <%name%> = <%spec%> <%attr%><%comment%>
190 >>
191 /*
192 This is a special case that seems to occur from time to time!
193 Modelica style function redfinition something that is not support in Julia.
194 I solve this using a macro @FunctionExtend..
195 function pathStringNoQual = pathString(usefq=false);
196 =>
197 @ExtendedFunction pathStringNoQual pathString(usefq=false);
198 */
199 case CLASS(body=parts as DERIVED(__), restriction=R_FUNCTION(__)) then
200 let comment = dumpCommentOpt(parts.comment, context)
201 let spec = dumpTypeSpec(parts.typeSpec, context)
202 let args = (parts.arguments |> earg => dumpElementArg(earg, context) ;separator=', ')
203 let attr = dumpElementAttr(parts.attributes)
204 let name_of_new_function = '<%name%>'
205 <<
206 <%comment%>
207 @ExtendedFunction <%name_of_new_function%> <%spec%>(<%args%>)
208 >>
209 /*PDER. Should not occur. Derived Enumeration and Overload might?*/
210 end dumpClassElement;
211
212 ✗ template dumpClassHeader(Absyn.ClassDef classDef, Absyn.Restriction restriction)
213 ::=
214 match classDef
215 case CLASS_EXTENDS(__) then AbsynDumpTpl.errorMsg("Extend not supported")
216 case PARTS(__) then '<%dumpClassTypeTypeVars(restriction, typeVars)%><%dumpClassTypeSuperType(restriction)%>'
217 else AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassHeader: <%dumpClassTypeSuperType(classDef)%>")
218 end dumpClassHeader;
219
220 ✗ template dumpClassTypeSuperType(Absyn.Restriction r)
221 ::=
222 match r
223 case R_METARECORD(__) then '<: <%dumpPathJL(name)%>'
224 case R_FUNCTION(__) then '' //Do nothing here for functions.. For now
225 end dumpClassTypeSuperType;
226
227 ✗ template dumpClassTypeTypeVars(Absyn.Restriction restriction, list<String> typeVars)
228 ::=
229 match restriction
230 case R_UNIONTYPE(__) then
231 (if typeVars then ("{" + (typeVars |> tv => tv ; separator=",") + "}"))
232 /*Not pretty. But should solve generic functions scathered here and there*/
233 case R_FUNCTION(__) then
234 (if typeVars then 'where {<%((typeVars |> tv => tv ; separator=", "))%>}')
235 else ""
236 end dumpClassTypeTypeVars;
237
238 ✗ template dumpClassFooter(Absyn.ClassDef classDef, String cdefStr, String name, String cmt, String ann)
239 ::=
240 match classDef
241 case DERIVED(__) then AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassFooter: Derived not yet supported.")
242 case ENUMERATION(__) then AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassFooterf: ENUMERATION not yet supported.")
243 case _ then
244 let annotation_str = if ann then '<%ann%> ' else ''
245 if cdefStr then
246 <<
247 <%cdefStr%>
248 <%if annotation_str then " "%><%annotation_str%>
249 end
250 >>
251 else
252 <<
253 <%annotation_str%>end
254 >>
255 end dumpClassFooter;
256
257 ✗ template dumpInputsJL(list<ElementItem> inputs, Context context)
258 ::=
259 let inputStr = (listReverse((MMToJuliaUtil.filterOnDirection(inputs, MMToJuliaUtil.makeInputDirection())))
260 |> ei
261 => '<%dumpComponentItems(getComponentItemsFromElementItem(ei), makeInputContext(dumpTypeSpecOpt(getTypeSpecFromElementItemOpt(ei), inputContext)))%>'
262 ;separator=", ")
263 '<%inputStr%>'
264 end dumpInputsJL;
265
266 ✗ template dumpReturnTypeJL(list<ElementItem> outputs)
267 ::=
268 match MMToJuliaUtil.filterOnDirection(outputs, MMToJuliaUtil.makeOutputDirection())
269 case {} then ""
270 case L as H::{} then '::<%dumpOutputsJL(L)%>'
271 case L as H::T then '::Tuple{<%dumpOutputsJL(L)%>}'
272 end dumpReturnTypeJL;
273
274 ✗ template dumpReturnStrJL(list<ElementItem> outputs, Context context)
275 ::=
276 match listReverse(MMToJuliaUtil.filterOnDirection(outputs, MMToJuliaUtil.makeOutputDirection()))
277 case {} then ""
278 case L as H::{} then
279 '<%(L |> e => dumpElementItemRaw(e, defaultDumpOptions, context); separator=", ")%>'
280 case L as H::T then
281 <<
282 (<%(L |> e => dumpElementItemRaw(e, defaultDumpOptions, context); separator=", ")%>)
283 >>
284 end dumpReturnStrJL;
285
286
287 ✗ template dumpClassDef(Absyn.ClassDef cdef, Context context, DumpOptions options)
288 ::=
289 match cdef
290 case PARTS(__) then
291 let body_str = (classParts |> class_part hasindex idx =>
292 dumpClassPart(class_part, idx, context, options) ;separator="\n")
293 <<
294 <%body_str%>
295 >>
296 case DERIVED(__) then
297 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassDef: Derived not yet supported.")
298 case CLASS_EXTENDS(__) then
299 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassDef: CLASS_EXETENDS not yet supported.")
300 case ENUMERATION(__) then
301 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassDef: CLASS_ENUMERATION not yet supported.")
302 else "TODO Unkown class definition"
303 end dumpClassDef;
304
305 ✗ template dumpClassType(Absyn.Restriction restriction)
306 ::=
307 match restriction
308 case R_PACKAGE(__) then "module"
309 case R_METARECORD(__) then "struct"
310 case R_RECORD(__) then '@Record' //Only handles Metamodelica records(!)
311 case R_UNIONTYPE(__) then "uniontype"
312 case R_TYPE(__) then '' // Should be const iff we are in a global scope (Julia 1.0 (Packages are not))
313 case R_FUNCTION(__) then "function"
314 /* TODO: The other ones are probably not relevant for now */
315 else AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassType: Unknown restriction for class." + AbsynDumpTpl.dumpRestriction(restriction))
316 end dumpClassType;
317
318 ✗ template dumpClassPart(Absyn.ClassPart class_part, Integer idx, Context context, DumpOptions options)
319 ::=
320 match class_part
321 case PUBLIC(__) then
322 let el_str = if isFunctionContext(context) then
323 dumpElementItems(filterOnDirection(contents, makeOutputDirection()), context, "", true, options)
324 else
325 dumpElementItems(contents, context,"", true, options)
326 <<
327 <%el_str%>
328 >>
329 case PROTECTED(__) then
330 let el_str = dumpElementItems(contents, context, "", true, options)
331 <<
332 <%el_str%>
333 >>
334 case CONSTRAINTS(__) then
335 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassPart: CONSTRAINTS(__) not supported.")
336 case EQUATIONS(__) then
337 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassPart: EQUATIONS(__) not supported.")
338 case INITIALEQUATIONS(__) then
339 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassPart: INITIALEQUATIONS() not supported.")
340 case ALGORITHMS(__) then
341 <<
342 <%(contents |> eq => dumpAlgorithmItem(eq, context) ;separator="\n")%>
343 >>
344 case INITIALALGORITHMS(__) then
345 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassPart: INITIALALGORITHMS() not supported.")
346 case EXTERNAL(__) then
347 let ann_str = match annotation_ case SOME(ann) then ' <%dumpAnnotation(ann, context)%>;'
348 match externalDecl
349 case EXTERNALDECL(__) then //Turned of temporary to translate builtin
350 "#= TODO: Defined in the runtime =#" //AbsynDumpTpl.errorMsg("AbsynToJulia.dumpClassPart: EXTERNALDECL(__) not supported.")
351 end dumpClassPart;
352
353 ✗ template dumpElementItems(list<Absyn.ElementItem> items, Context context, String prevSpacing, Boolean first, DumpOptions options)
354 ::=
355 match items
356 case item :: rest_items then
357 let spacing = dumpElementItemSpacing(item)
358 let pre_spacing = if not first then
359 dumpElementItemPreSpacing(spacing, prevSpacing)
360 let item_str = dumpElementItem(item, options, context)
361 let rest_str = dumpElementItems(rest_items, context, spacing, false, options)
362 let post_spacing = if rest_str then spacing
363 <<
364 <%pre_spacing%>
365 <%item_str%><%post_spacing%><%\n%>
366 <%if rest_str then rest_str%>
367 >>
368 end dumpElementItems;
369
370 ✗ template dumpElementItemPreSpacing(String curSpacing, String prevSpacing)
371 ::= if not prevSpacing then curSpacing
372 end dumpElementItemPreSpacing;
373
374 ✗ template dumpElementItemSpacing(Absyn.ElementItem item)
375 ::=
376 match item
377 case ELEMENTITEM(element = ELEMENT(specification = CLASSDEF(class_ = CLASS(body = cdef))))
378 then dumpClassDefSpacing(cdef)
379 end dumpElementItemSpacing;
380
381 ✗ template dumpClassDefSpacing(Absyn.ClassDef cdef)
382 ::=
383 match cdef
384 case PARTS(__) then '<%\n%>'
385 case CLASS_EXTENDS(__) then '<%\n%>'
386 end dumpClassDefSpacing;
387
388 ✗ template dumpElementItem(Absyn.ElementItem eitem, DumpOptions options, Context context)
389 ::=
390 match eitem
391 case ELEMENTITEM(__) then '<%dumpElement(element, options, context)%>'
392 case LEXER_COMMENT(__) then dumpCommentStr(comment)
393 end dumpElementItem;
394
395 ✗ template dumpElementItemRaw(Absyn.ElementItem eitem, DumpOptions options, Context context)
396 "Same as dumpElementItem but does not add the local prefix"
397 ::=
398 match eitem
399 case ELEMENTITEM(__) then
400 match element
401 case ELEMENT(__) then
402 match specification
403 case COMPONENTS(__) then
404 let comps_str = (components |> comp => dumpComponentItem(comp, context) ;separator=", ")
405 '<%comps_str%>'
406 else
407 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpElementItem: on none component type")
408 else
409 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpElementItem: on none component type")
410 case LEXER_COMMENT(__) then dumpCommentStr(comment)
411 end dumpElementItemRaw;
412
413 ✗ template dumpElement(Absyn.Element elem, DumpOptions options, Context context)
414 ::=
415 match elem
416 case ELEMENT(__) then
417 if boolOr(boolUnparseFileFromInfo(info, options), boolNot(isClassdef(elem))) then
418 let final_str = dumpFinal(finalPrefix)
419 let redecl_str = match redeclareKeywords case SOME(re) then dumpRedeclare(re)
420 let repl_str = match redeclareKeywords case SOME(re) then dumpReplaceable(re)
421 let elementSpec_str = dumpElementSpec(specification, options, context)
422 let constrainClass_str = match constrainClass case SOME(cc) then dumpConstrainClass(cc, context)
423 '<%elementSpec_str%><%constrainClass_str%>'
424 case DEFINEUNIT(__) then AbsynDumpTpl.errorMsg("AbsynToJulia.dumpElement: DEFINEUNIT(__) not supported")
425 case TEXT(__) then
426 if boolUnparseFileFromInfo(info, options) then
427 let name_str = match optName case SOME(name) then name
428 let info_str = dumpInfo(info)
429 '/* Absyn.TEXT(SOME("<%name_str%>"), "<%string%>", "<%info_str%>"); */'
430 end dumpElement;
431
432 ✗ template dumpInfo(builtin.SourceInfo info)
433 ::=
434 match info
435 case SOURCEINFO(__) then
436 let rm_str = if isReadOnly then "readonly" else "writable"
437 'SOURCEINFO("<%fileName%>", <%rm_str%>, <%lineNumberStart%>, <%columnNumberStart%>, <%lineNumberEnd%>, <%columnNumberEnd%>)\n'
438 end dumpInfo;
439
440 ✗ template dumpAnnotation(Absyn.Annotation ann, Context context)
441 ::=
442 match ann
443 case ANNOTATION(elementArgs={}) then "#= annotation() =#"
444 case ANNOTATION(__) then
445 <<
446 #= annotation(
447 <%(elementArgs |> earg => dumpElementArg(earg, context) ;separator=',<%\n%>')%>) =#
448 >>
449 end dumpAnnotation;
450
451 ✗ template dumpAnnotationOpt(Option<Absyn.Annotation> oann, Context context)
452 ::= match oann case SOME(ann) then dumpAnnotation(ann, context)
453 end dumpAnnotationOpt;
454
455 ✗ template dumpAnnotationOptSpace(Option<Absyn.Annotation> oann, Context context)
456 ::= match oann case SOME(ann) then " " + dumpAnnotation(ann, context)
457 end dumpAnnotationOptSpace;
458
459 ✗ template dumpComment(Absyn.Comment cmt, Context context)
460 ::=
461 match cmt
462 case COMMENT(__) then
463 dumpCommentStrOpt(comment) + dumpAnnotationOptSpace(annotation_, context)
464 end dumpComment;
465
466 ✗ template dumpCommentOpt(Option<Absyn.Comment> ocmt, Context context)
467 ::= match ocmt case SOME(cmt) then dumpComment(cmt, context)
468 end dumpCommentOpt;
469
470 ✗ template dumpCommentStrOpt(Option<String> comment)
471 ::= match comment case SOME(cmt) then dumpCommentStr(cmt)
472 end dumpCommentStrOpt;
473
474 ✗ template dumpCommentStr(String comment)
475 ::=
476 let replaceAllRegular = '<%\ %>#= <%System.stringReplace(System.escapedString(comment, false), "//","")%> =#'
477 '<%replaceAllRegular%>'
478 end dumpCommentStr;
479
480 ✗ template dumpElementArg(Absyn.ElementArg earg, Context context)
481 ::=
482 match earg
483 case MODIFICATION(__) then
484 let each_str = dumpEach(eachPrefix)
485 let final_str = dumpFinal(finalPrefix)
486 let path_str = dumpPathJL(path)
487 let mod_str = match modification case SOME(mod) then dumpModification(mod, context)
488 let cmt_str = dumpCommentStrOpt(comment)
489 '<%each_str%><%final_str%><%path_str%><%mod_str%><%cmt_str%>'
490 case REDECLARATION(__) then
491 let each_str = dumpEach(eachPrefix)
492 let final_str = dumpFinal(finalPrefix)
493 let redecl_str = dumpRedeclare(redeclareKeywords)
494 let repl_str = dumpReplaceable(redeclareKeywords)
495 let eredecl_str = '<%redecl_str%><%each_str%>'
496 let elem_str = dumpElementSpec(elementSpec, defaultDumpOptions, context)
497 let cc_str = match constrainClass case SOME(cc) then dumpConstrainClass(cc, context)
498 '<%elem_str%><%cc_str%>'
499 end dumpElementArg;
500
501 ✗ template dumpEach(Absyn.Each each)
502 ::= match each case EACH() then "each "
503 end dumpEach;
504
505 ✗ template dumpFinal(Boolean final)
506 ::= if final then "final "
507 end dumpFinal;
508
509 ✗ template dumpRedeclare(Absyn.RedeclareKeywords redecl)
510 ::=
511 match redecl
512 case REDECLARE() then "redeclare "
513 case REDECLARE_REPLACEABLE() then "redeclare "
514 end dumpRedeclare;
515
516 ✗ template dumpReplaceable(Absyn.RedeclareKeywords repl)
517 ::=
518 match repl
519 case REPLACEABLE() then "replaceable "
520 case REDECLARE_REPLACEABLE() then "replaceable "
521 end dumpReplaceable;
522
523 ✗ template dumpModification(Absyn.Modification mod, Context context)
524 ::=
525 match mod
526 case CLASSMOD(__) then
527 let arg_str = if elementArgLst then
528 '(<%(elementArgLst |> earg => dumpElementArg(earg, context) ;separator=", ")%>)'
529 let eq_str = dumpEqMod(eqMod, context)
530 '<%arg_str%><%eq_str%>'
531 end dumpModification;
532
533 ✗ template dumpEqMod(Absyn.EqMod eqmod, Context context)
534 ::= match eqmod case EQMOD(__) then '<%\ %>= <%dumpExp(exp, context)%>'
535 end dumpEqMod;
536
537 ✗ template dumpElementSpec(ElementSpec specification, DumpOptions options, Context context)
538 ::=
539 match specification
540 case CLASSDEF(__) then dumpClassElement(class_, options, context)
541 case EXTENDS(__) then
542 let bc_str = dumpPathJL(path)
543 let args_str = (elementArg |> earg => dumpElementArg(earg, context) ;separator=", ")
544 let mod_str = if args_str then '(<%args_str%>)'
545 let ann_str = dumpAnnotationOptSpace(annotationOpt, context)
546 'extends <%bc_str%><%mod_str%><%ann_str%>'
547 case COMPONENTS(__) then
548 let attr_str = dumpElementAttr(attributes)
549 /* Remove all items with input-output specification. They are handled earlier and separate! */
550 let ty_str = dumpTypeSpec(typeSpec, context)
551 let comps_str = if elementSpecIsOUTPUT_OR_BIDIR(specification) then
552 (components |> comp =>
553 let comp_str = dumpComponentItem(comp, makeFunctionReturnContext("",ty_str))
554 'local <%comp_str%>'
555 ;separator="\n")
556 else ''
557 let comps_str_no_local = if elementSpecIsOUTPUT_OR_BIDIR(specification) then
558 (components |> comp =>
559 let comp_str = dumpComponentItem(comp, noContext)
560 ' <%match context case PACKAGE(__) then "const "%><%comp_str%>::<%ty_str%>'
561 ;separator="\n")
562 else ''
563 /*If our context is a function context we need to redefine comps_str*/
564 let rStr = match context
565 case FUNCTION(__) then
566 '<%retValsStr%>'
567 else''
568 /* No local decl if we do not have a comps_str! */
569 match context
570 case FUNCTION(__) then
571 if comps_str then
572 '<%comps_str%>'
573 else ''
574 case UNIONTYPE(__) then
575 '<%comps_str_no_local%>'
576 case PACKAGE(__) then
577 '<%comps_str_no_local%>'
578 else 'ERROR'
579 case IMPORT(__) then
580 let imp_str = dumpImport(import_)
581 '<%imp_str%>'
582 end dumpElementSpec;
583
584 ✗ template dumpElementSpecForComponents(ElementSpec specification, DumpOptions options, Context context)
585 ::=
586 match specification
587 case COMPONENTS(__) then
588 let comps_str = (components |> comp => dumpComponentItem(comp, context) ;separator=", ")
589 '<%comps_str%>'
590 end dumpElementSpecForComponents;
591
592 ✗ template dumpElementAttr(Absyn.ElementAttributes attr)
593 ::=
594 match attr
595 case ATTR(__) then
596 let var_str = dumpVariability(variability)
597 '<%var_str%>'
598 end dumpElementAttr;
599
600 ✗ template dumpVariability(Absyn.Variability var)
601 ::=
602 match var
603 /*
604 Constants are currently only allowed in the global scope (Julia 1.1).
605 TODO: Global scope is only defined as a scope outside a module.
606 What do to here, Scope as a parameter?
607 */
608 case VAR() then ""
609 case CONST() then ""
610 else AbsynDumpTpl.errorMsg("AbsynToJulia.dumpVariability: Only const and var are supported")
611 end dumpVariability;
612
613 ✗ template dumpConstrainClass(Absyn.ConstrainClass cc, Context context)
614 ::=
615 match cc
616 case CONSTRAINCLASS(elementSpec = Absyn.EXTENDS(path = p, elementArg = el)) then
617 let path_str = dumpPathJL(p)
618 let el_str = if el then '(<%(el |> e => dumpElementArg(e, context) ;separator=", ")%>)'
619 let cmt_str = dumpCommentOpt(comment, context)
620 ' constrainedby <%path_str%><%el_str%><%cmt_str%>'
621 end dumpConstrainClass;
622
623 ✗ template dumpComponentItems(list<Absyn.ComponentItem> componentItems, Context context)
624 "Returns a comma separated list of component items without the condition string"
625 ::= (componentItems |> ci => dumpComponentItemWithoutCondString(ci, context) ;separator=", ")
626 end dumpComponentItems;
627
628 ✗ template dumpComponentItem(Absyn.ComponentItem comp, Context context)
629 ::=
630 match comp
631 case COMPONENTITEM(__) then
632 let comp_str = dumpComponent(component, context)
633 let cond_str = dumpComponentCondition(condition, context) //TODO. This will complicate things...
634 let cmt = dumpCommentOpt(comment, context)
635 '<%comp_str%><%cond_str%><%cmt%>'
636 end dumpComponentItem;
637
638 ✗ template dumpComponentItemWithoutCondString(Absyn.ComponentItem comp, Context context)
639 ::=
640 match comp
641 case COMPONENTITEM(__) then
642 let comp_str = dumpComponent(component, context)
643 let cmt = dumpCommentOpt(comment, context)
644 '<%comp_str%><%cmt%>'
645 end dumpComponentItemWithoutCondString;
646
647 ✗ template dumpComponent(Absyn.Component comp, Context context)
648 ::=
649 match comp
650 case COMPONENT(__) then
651 let dim_str = dumpSubscripts(arrayDim, context)
652 let mod_str = match modification case SOME(mod) then dumpModification(mod, context)
653 let component_name = '<%name%>'
654 /*REFACTOR INVERSE NAME INVERSE MEANING!*/
655 match context
656 case FUNCTION_RETURN_CONTEXT(__) then '<%component_name%>::<%ty_str%><%dim_str%><%mod_str%>'
657 case FUNCTION(__) then '<%component_name%>'
658 case INPUT_CONTEXT(__) then '<%component_name%>::<%ty_str%><%dim_str%><%mod_str%>'
659 else '<%component_name%><%dim_str%><%mod_str%>'
660 end dumpComponent;
661
662 ✗ template dumpComponentCondition(Option<Absyn.ComponentCondition> cond, Context context)
663 ::=
664 match cond
665 case SOME(cexp) then
666 let exp_str = dumpExp(cexp, context)
667 ' if <%exp_str%>'
668 end dumpComponentCondition;
669
670 ✗ template dumpImport(Absyn.Import imp)
671 "This will depend on my ExportAll.jl package. Not good practice but seem to be needed at places"
672 ::=
673 match imp
674 case NAMED_IMPORT(__) then
675 'import <%dumpPathJL(path)%>; <%name%>=<%dumpPathJL(path)%>'
676 case QUAL_IMPORT(__) then
677 let path_str = dumpPathJL(path)
678 match path_str
679 case "Array" then 'import ArrayUtil'
680 case "List" then 'import ListUtil'
681 else 'import <%path_str%>'
682 case UNQUAL_IMPORT(__) then 'using <%dumpPathJL(path)%>'
683 case GROUP_IMPORT(__) then
684 let prefix_str = dumpPathJL(prefix)
685 let groups_str = (groups |> group => dumpGroupImport(group) ;separator=", ")
686 'using <%prefix_str%>: <%groups_str%>'
687 end dumpImport;
688
689 ✗ template dumpGroupImport(Absyn.GroupImport gimp)
690 ::=
691 match gimp
692 case GROUP_IMPORT_NAME(__) then name
693 case GROUP_IMPORT_RENAME(__) then '<%rename%> = <%name%>'
694 end dumpGroupImport;
695
696 ✗ template dumpEquation(Absyn.Equation eq)
697 ::= "No equations allowed. Translate them to algorithms"
698 end dumpEquation;
699
700 ✗ template dumpAlgorithmItems(list<Absyn.AlgorithmItem> algs, Context context)
701 ::= (algs |> alg => dumpAlgorithmItem(alg, context) ;separator="\n")
702 end dumpAlgorithmItems;
703
704 ✗ template dumpAlgorithmItem(Absyn.AlgorithmItem alg, Context context)
705 ::=
706 match alg
707 case ALGORITHMITEM(__) then
708 let alg_str = dumpAlgorithm(algorithm_, context)
709 let cmt_str = dumpCommentOpt(comment, context)
710 '<%alg_str%><%cmt_str%>'
711 case ALGORITHMITEMCOMMENT(__) then dumpCommentStr(comment)
712 end dumpAlgorithmItem;
713
714 ✗ template dumpAlgorithm(Absyn.Algorithm alg, Context context)
715 ::=
716 match alg
717 case ALG_ASSIGN(__) then
718 let lhs_str = dumpLhsExp(assignComponent, makeFunctionContext("listMatchAssign"))
719 let rhs_str = dumpExp(value, context)
720 /* Somtimes assignments are used as assertions. There are probably more cases...*/
721 if AbsynUtil.complexIsCref(assignComponent) then
722 match assignComponent
723 case CONS(__) then
724 '@match <%lhs_str%> = <%rhs_str%>'
725 else
726 '<%lhs_str%> = <%rhs_str%>'
727 else
728 '@match <%lhs_str%> = <%rhs_str%>'
729 case ALG_IF(__) then
730 let if_str = dumpAlgorithmBranch(ifExp, trueBranch, "if", context)
731 let elseif_str = (elseIfAlgorithmBranch |> (c, b) =>
732 dumpAlgorithmBranch(c, b, "elseif", context) ;separator="\n")
733 let else_branch_str = dumpAlgorithmItems(elseBranch, context)
734 let else_str = if else_branch_str then
735 <<
736 else
737 <%else_branch_str%>
738 >>
739 <<
740 <%if_str%>
741 <%elseif_str%>
742 <%else_str%>
743 end
744 >>
745 case ALG_FOR(__) then
746 let iter_str = dumpForIterators(iterators, context)
747 let body_str = dumpAlgorithmItems(forBody, context)
748 <<
749 for <%iter_str%>
750 <%body_str%>
751 end
752 >>
753 case ALG_WHILE(__) then
754 let while_str = dumpAlgorithmBranch(boolExpr, whileBody, "while", context)
755 <<
756 <%while_str%>
757 end
758 >>
759 case ALG_WHEN_A(__) then AbsynDumpTpl.errorMsg("When statements are not allowed!.")
760 case ALG_NORETCALL(__) then
761 let name_str = dumpCref(functionCall, context)
762 let args_str = dumpFunctionArgs(functionArgs, context)
763 '<%name_str%>(<%args_str%>)'
764 /*Here we need to gather all return values for the function*/
765 case ALG_RETURN(__) then dumpAlgReturnString(context)
766 case ALG_BREAK(__) then "break"
767 case ALG_FAILURE(__) then
768 let arg_str = if equ then dumpAlgorithmItems(equ, context) else "..."
769 '@shouldFail <%arg_str%>'
770 case ALG_TRY(__) then
771 let arg1 = dumpAlgorithmItems(body, context)
772 let arg2 = dumpAlgorithmItems(elseBody, context)
773 <<
774 try
775 <%arg1%>
776 catch
777 <%arg2%>
778 end
779 >>
780 case ALG_CONTINUE(__) then "continue"
781 end dumpAlgorithm;
782
783 ✗ template dumpAlgReturnString(Context context)
784 "Dumps the return string for a specific function context"
785 ::= match context
786 case FUNCTION(__) then 'return <%retValsStr%>'
787 /*TODO: Should not occur? Models with sections?*/
788 else "return"
789 end dumpAlgReturnString;
790
791 ✗ template dumpAlgorithmBranch(Absyn.Exp cond, list<Absyn.AlgorithmItem> body,
792 String header, Context context)
793 ::=
794 let cond_str = dumpExp(cond, context)
795 let body_str = (body |> eq => dumpAlgorithmItem(eq, context) ;separator="\n")
796 <<
797 <%header%> <%cond_str%>
798 <%body_str%>
799 >>
800 end dumpAlgorithmBranch;
801
802 ✗ template dumpPathJL(Absyn.Path path)
803 "Wrapper function for dump path.
804 Needed since certain keywords will have a sligthly different meaning in Julia"
805 ::=
806 match path
807 case FULLYQUALIFIED(__) then
808 '.<%AbsynDumpTpl.dumpPath(path)%>'
809 case QUALIFIED(__) then
810 if (Flags.getConfigBool(Flags.MODELICA_OUTPUT)) then
811 '<%name%>__<%AbsynDumpTpl.dumpPath(path)%>'
812 else
813 '<%name%>.<%AbsynDumpTpl.dumpPath(path)%>'
814 case IDENT(__) then
815 match name
816 case "Real" then 'Float'
817 case "Integer" then 'Integer'
818 case "Boolean" then 'Bool'
819 case "list" then 'List'
820 case "array" then 'Array'
821 case "tuple" then 'Tuple'
822 case "polymorphic" then 'Any'
823 case "Mutable" then 'MutableType'
824 else '<%name%>'
825 else
826 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpPathJL: Unknown path.")
827 end dumpPathJL;
828
829 ✗ template dumpPathNoQual(Absyn.Path path)
830 ::=
831 match path
832 case FULLYQUALIFIED(__) then
833 dumpPathJL(path)
834 else
835 dumpPathJL(path)
836 end dumpPathNoQual;
837
838 ✗ template dumpTypeSpecOpt(Option<Absyn.TypeSpec> typespecOpt, Context context)
839 ::= match typespecOpt case SOME(ts) then dumpTypeSpec(ts, context) else ""
840 end dumpTypeSpecOpt;
841
842 ✗ template dumpTypeSpec(Absyn.TypeSpec typeSpec, Context context)
843 "
844 Dumps the type specification:
845
846 TODO add several <: for the different types. Not important at the present time.
847
848 TODO: Any types should not have the <: syntax
849 "
850 ::=
851 match typeSpec
852 case TPATH(__) then
853 let path_str = dumpPathJL(path)
854 let arraydim_str = dumpArrayDimOpt(arrayDim, context)
855 '<%path_str%><%arraydim_str%>'
856 case TCOMPLEX(__) then
857 let path_str = dumpPathJL(path)
858 let ty_str = (typeSpecs |> ty => dumpTypeSpec(ty, context) ;separator=", ")
859 let arraydim_str = dumpArrayDimOpt(arrayDim, context)
860 /* For input context/Function context we use special Julia syntax to allow covariance (ML style typing) */
861 let isFunc = match context
862 case INPUT_CONTEXT(__) then "iofunc"
863 else ""
864 let isPackage = match context
865 case PACKAGE(__) then "package"
866 else ""
867 let ty_str2 ='{<:<%ty_str%>}'
868 let res = '<%path_str%><%ty_str2%><%arraydim_str%>'
869 if isFunc then
870 '<%res%>'
871 else
872 if isPackage then
873 '<%path_str%>'
874 else
875 '<%path_str%>{<%ty_str%>}<%arraydim_str%>'
876 end dumpTypeSpec;
877
878 ✗ template dumpArrayDimOptTypeSpec(Option<Absyn.ArrayDim> arraydim, Context context)
879 "Not in use"
880 ::= match arraydim case SOME(ad) then dumpSubscriptsTypeSpec(ad, context)
881 end dumpArrayDimOptTypeSpec;
882
883 ✗ template dumpSubscriptsTypeSpec(list<Absyn.Subscript> subscripts, Context context)
884 "Not in use"
885 ::=
886 if subscripts then
887 let sub_str = (subscripts |> s => 'Array' ;separator=", ")
888 'Array{<%sub_str%>}'
889 end dumpSubscriptsTypeSpec;
890
891 ✗ template dumpArrayDimOpt(Option<Absyn.ArrayDim> arraydim, Context context)
892 ::= match arraydim case SOME(ad) then dumpSubscripts(ad, context)
893 end dumpArrayDimOpt;
894
895 ✗ template dumpSubscripts(list<Absyn.Subscript> subscripts, Context context)
896 ::=
897 if subscripts then
898 let sub_str = (subscripts |> s => dumpSubscript(s, context) ;separator=", ")
899 '[<%sub_str%>]'
900 end dumpSubscripts;
901
902 ✗ template dumpSubscript(Absyn.Subscript subscript, Context context)
903 ::=
904 match subscript
905 case NOSUB(__) then ':'
906 case SUBSCRIPT(__) then dumpExp(subscript, context)
907 end dumpSubscript;
908
909 ✗ template dumpExp(Absyn.Exp exp, Context context)
910 ::=
911 match exp
912 case INTEGER(__) then value
913 case REAL(__) then value
914 case CREF(__) then dumpCref(componentRef, context)
915 case STRING(__) then '"<%Util.escapeModelicaStringToJLString(value)%>"'
916 case BOOL(__) then value
917 case e as BINARY(__) then
918 let lhs_str = dumpOperand(exp1, e, true, context)
919 let rhs_str = dumpOperand(exp2, e, false, context)
920 let op_str = dumpOperator(op)
921 '<%lhs_str%> <%op_str%> <%rhs_str%>'
922 case e as UNARY(__) then
923 let exp_str = dumpOperand(exp, e, false, context)
924 let op_str = dumpOperator(op)
925 '<%op_str%><%exp_str%>'
926 case e as LBINARY(__) then
927 let lhs_str = dumpOperand(exp1, e, true, context)
928 let rhs_str = dumpOperand(exp2, e, false, context)
929 let op_str = dumpOperator(op)
930 '<%lhs_str%> <%op_str%> <%rhs_str%>'
931 case e as LUNARY(__) then
932 let exp_str = dumpOperand(exp, e, false, context)
933 let op_str = dumpOperator(op)
934 '<%op_str%> <%exp_str%>'
935 case e as RELATION(__) then
936 let lhs_str = dumpOperand(exp1, e, true, context)
937 let rhs_str = dumpOperand(exp2, e, false, context)
938 let op_str = dumpOperator(op)
939 '<%lhs_str%> <%op_str%> <%rhs_str%>'
940 case IFEXP(__) then dumpIfExp(exp, context)
941 case CALL(function_=Absyn.CREF_IDENT(name="$array")) then
942 let args_str = dumpFunctionArgs(functionArgs, context)
943 '{<%args_str%>}'
944 case CALL(__) then
945 let func_str = dumpCref(function_, context)
946 let args_str = dumpFunctionArgs(functionArgs, context)
947 '<%func_str%>(<%args_str%>)'
948 case PARTEVALFUNCTION(__) then
949 let func_str = dumpCref(function_, context)
950 let args_str = dumpFunctionArgs(functionArgs, context)
951 /* Same scenario when extending functions.
952 We pass a function and change the parameters
953 */
954 let args2_str = match functionArgs
955 case FUNCTIONARGS(__) then
956 '<%(argNames |> na => dumpNamedArgPattern3(na) ;separator=", ")%>'
957 else
958 ''
959 '(<%args2_str%>) -> <%func_str%>(<%args_str%>)'
960 case ARRAY(__) /*MM grammar changing behaviour... Remember to change this IF regular arrays would occur... Probably not used so can be ignored */ then
961 let array_str = (arrayExp |> e => dumpExp(e, context) ;separator=", ")
962 if array_str then
963 'list(<%array_str%>)'
964 else
965 'nil'
966 case MATRIX(__) then
967 let matrix_str = (matrix |> row =>
968 (row |> e => dumpExp(e, context) ;separator=", ") ;separator="; ")
969 '[<%matrix_str%>]'
970 case e as RANGE(step = SOME(step)) then
971 let start_str = dumpOperand(start, e, false, context)
972 let step_str = dumpOperand(step, e, false, context)
973 let stop_str = dumpOperand(stop, e, false, context)
974 '<%start_str%>:<%step_str%>:<%stop_str%>'
975 case e as RANGE(step = NONE()) then
976 let start_str = dumpOperand(start, e, false, context)
977 let stop_str = dumpOperand(stop, e, false, context)
978 '<%start_str%>:<%stop_str%>'
979 case TUPLE(__) then
980 /* Paranthesis does not seem to be needed for tuples in Julia
981 and gives parse errors.. In certain situations that is
982 Readded paranthesis and added linebreaks to if expressions. Not
983 safe to generate one line if exprs
984 */
985 let tuple_str = (expressions |> e => dumpExp(e,context); separator=", " ;empty)
986 if tuple_str then '(<%tuple_str%>)'
987 else '()'
988 case END(__) then 'end'
989 case CODE(__) then '$Code(<%dumpCodeNode(code, context)%>)'
990 case AS(__) then
991 let exp_str = dumpExp(exp, context)
992 /* TODO Macro might be needed for this case*/
993 '(@match <%exp_str%> = <%id%>)'
994 case CONS(__) then
995 let head_str = dumpExp(head, context)
996 let rest_str = dumpExp(rest, context)
997 '_cons(<%head_str%>, <%rest_str%>)'
998 case MATCHEXP(__) then dumpMatchExp(exp)
999 case LIST(__) then
1000 let list_str = (exps |> e => dumpExp(e, context) ;separator=", ")
1001 'list(<%list_str%>)'
1002 case DOT(__) then
1003 '<%dumpExp(exp, context)%>.<%dumpExp(index, context)%>'
1004 case _ then '/* AbsynDumpTpl.dumpExp: UNHANDLED Abyn.Exp */'
1005 end dumpExp;
1006
1007 ✗ template dumpPattern(Absyn.Exp exp, Context context, Text &as_str)
1008 ::=
1009 match exp
1010 case INTEGER(__) then value
1011 case REAL(__) then value
1012 case CREF(__) then dumpCref(componentRef, functionContext /*Only occurs in fc*/)
1013 case STRING(__) then ('"<%stringReplace(value,"\$","\\$"); absIndent=0%>"')
1014 case BOOL(__) then value
1015 case ARRAY(arrayExp=exps)
1016 case LIST(__)
1017 case CALL(function_=Absyn.CREF_IDENT(name="list"), functionArgs=FUNCTIONARGS(args=exps))
1018 case CALL(function_=Absyn.CREF_IDENT(name="$array"), functionArgs=FUNCTIONARGS(args=exps)) then
1019 /*Using nil() is only ok for matchexpressions*/
1020 '<%exps |> e => '<%dumpPattern(e, context, &as_str)%> <| '%> nil()'
1021 case CALL(function_=function_ as CREF_IDENT(name=id)) then
1022 let args_str = dumpFunctionArgsPattern(functionArgs)
1023 let func_str = (match id
1024 case "list" then "List"
1025 else dumpCref(function_, functionContext))
1026 if args_str then
1027 '<%func_str%>(<%args_str%>)'
1028 else
1029 /*We have a wildcard*/
1030 let isNone = match func_str
1031 case "NONE" then "NONE"
1032 else ""
1033 if isNone then
1034 '<%func_str%>()'
1035 else
1036 '<%func_str%>(__)'
1037 case CALL(__) then
1038 let func_str = dumpCref(function_, functionContext)
1039 let args_str = dumpFunctionArgsPattern(functionArgs)
1040 if args_str then
1041 '<%func_str%>(<%args_str%>)'
1042 else
1043 /* This means we have a wildcard */
1044 '<%func_str%>(__)'
1045 case TUPLE(__) then
1046 let tuple_str = (expressions |> e => dumpPattern(e, context, &as_str); separator=", " ;empty)
1047 '(<%tuple_str%>)'
1048 case AS(__) then
1049 let exp_str = dumpPattern(exp, context, &as_str)
1050 let id_str = '<%id%>'
1051 '<%id_str%> && <%exp_str%>'
1052 case CONS(__) then
1053 let consOp = dumpCons(dumpPattern(head, context, &as_str), dumpPattern(rest, context, &as_str))
1054 '<%consOp%>'
1055 case _ then '#= AbsynDumpTpl.dumpPattern: UNHANDLED Abyn.Exp =#'
1056 end dumpPattern;
1057
1058 ✗ template dumpCons(String headString, String tailString)
1059 ::= '<%headString%> <| <%tailString%>'
1060 end dumpCons;
1061
1062 ✗ template dumpFunctionArgsPattern(Absyn.FunctionArgs args)
1063 ::=
1064 match args
1065 case FUNCTIONARGS(__) then
1066 let args_str = (args |> arg => dumpPattern(arg, functionContext, emptyTxt) ;separator=", ")
1067 let namedargs_str = (argNames |> narg => dumpNamedArgPattern(narg) ;separator=", ")
1068 let separator = if args_str then if argNames then ', '
1069 '<%args_str%><%separator%><%namedargs_str%>'
1070 else 'ERROR FOR_ITER_FARG in pattern'
1071 end dumpFunctionArgsPattern;
1072
1073 ✗ template dumpNamedArgPattern(Absyn.NamedArg narg)
1074 ::=
1075 match narg
1076 case NAMEDARG(__) then
1077 '<%argName%> = <%dumpPattern(argValue, functionContext, emptyTxt)%>'
1078 end dumpNamedArgPattern;
1079
1080
1081 ✗ template dumpNamedArgPattern2(Absyn.NamedArg narg)
1082 "Returns the argument name"
1083 ::=
1084 match narg
1085 case NAMEDARG(__) then
1086 "<%argName%>"
1087 end dumpNamedArgPattern2;
1088
1089
1090 ✗ template dumpNamedArgPattern3(Absyn.NamedArg narg)
1091 "Returns the argument value"
1092 ::=
1093 match narg
1094 case NAMEDARG(__) then
1095 '<%dumpPattern(argValue, functionContext, emptyTxt)%>'
1096 end dumpNamedArgPattern3;
1097
1098 ✗ template dumpLhsExp(Absyn.Exp lhs, Context context)
1099 ::=
1100 match lhs
1101 case IFEXP(__) then '<%dumpExp(lhs, context)%>'
1102 else dumpExp(lhs, context)
1103 end dumpLhsExp;
1104
1105 ✗ template dumpOperand(Absyn.Exp operand, Absyn.Exp operation, Boolean lhs, Context context)
1106 ::=
1107 let op_str = dumpExp(operand, context)
1108 if shouldParenthesize(operand, operation, lhs) then
1109 '(<%op_str%>)'
1110 else
1111 op_str
1112 end dumpOperand;
1113
1114 ✗ template dumpIfExp(Absyn.Exp if_exp, Context context)
1115 ::=
1116 match if_exp
1117 case IFEXP(__) then
1118 let cond_str = dumpExp(ifExp, context)
1119 let true_branch_str = dumpExp(trueBranch, context)
1120 let else_branch_str = dumpExp(elseBranch, context)
1121 let else_if_str = dumpElseIfExp(elseIfBranch, context)
1122 'if <%cond_str%>
1123 <%true_branch_str%>
1124 <%else_if_str%>
1125 else
1126 <%else_branch_str%>
1127 end'
1128 end dumpIfExp;
1129
1130 ✗ template dumpElseIfExp(list<tuple<Absyn.Exp, Absyn.Exp>> else_if, Context context)
1131 ::=
1132 else_if |> eib as (cond, branch) =>
1133 let cond_str = dumpExp(cond, context)
1134 let branch_str = dumpExp(branch, context)
1135 'elseif (<%cond_str%>)
1136 <%branch_str%>' ;separator="\n"
1137 end dumpElseIfExp;
1138
1139 ✗ template dumpCodeNode(Absyn.CodeNode code, Context context)
1140 ::=
1141 match code
1142 case C_TYPENAME(__) then dumpPathJL(path)
1143 case C_VARIABLENAME(__) then dumpCref(componentRef, context)
1144 case C_CONSTRAINTSECTION(__) then
1145 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpCodeNode: C_CONSTRAINTSECTION not supported")
1146 case C_EQUATIONSECTION(__) then
1147 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpCodeNode: C_CONSTRAINTSECTION not supported")
1148 case C_ALGORITHMSECTION(__) then
1149 AbsynDumpTpl.errorMsg("AbsynToJulia.dumpCodeNode: C_ALGORITHMSECTION not supported")
1150 case C_ELEMENT(__) then dumpElement(element, Dump.defaultDumpOptions, context)
1151 case C_EXPRESSION(__) then dumpExp(exp, context)
1152 case C_MODIFICATION(__) then dumpModification(modification, context)
1153 end dumpCodeNode;
1154
1155 //John: look at this one more time...
1156 ✗ template dumpMatchExp(Absyn.Exp match_exp)
1157 ::=
1158 match match_exp
1159 case MATCHEXP(__) then
1160 let match_ty_str = dumpMatchType(matchTy)
1161 let input_str = dumpExp(inputExp, functionContext)
1162 let locals_str = dumpMatchLocals(localDecls)
1163 /* Input string is a tuple or a single variable*/
1164 let cases_str = (cases |> c => dumpMatchCase(c, makeMatchContext(inputExp)) ;separator="\n\n")
1165 let cmt_str = dumpCommentStrOpt(comment)
1166 <<
1167 begin
1168 <%locals_str%>
1169 <%match_ty_str%> <%input_str%> begin
1170 <%cases_str%><%cmt_str%>
1171 end
1172 end
1173 >>
1174 end dumpMatchExp;
1175
1176 ✗ template dumpMatchType(Absyn.MatchType match_type)
1177 ::=
1178 match match_type
1179 case MATCH() then "@match"
1180 case MATCHCONTINUE() then "@matchcontinue"
1181 end dumpMatchType;
1182
1183 ✗ template dumpMatchContents(ClassPart cp)
1184 ::=
1185 match cp
1186 case EQUATIONS(contents={}) then ""
1187 case EQUATIONS(__) then
1188 <<
1189 <%(Static.fromEquationsToAlgAssignments(cp) |> alg => dumpAlgorithmItem(alg, functionContext) ;separator="\n")%>
1190 >>
1191 case ALGORITHMS(contents={}) then ""
1192 case ALGORITHMS(contents=algs) then
1193 <<
1194 <%(algs |> alg => dumpAlgorithmItem(alg, functionContext) ;separator="\n")%>
1195 >>
1196 end dumpMatchContents;
1197
1198 ✗ template dumpMatchLocals(list<ElementItem> locals)
1199 ::= if locals then
1200 <<
1201 <%(locals |> decl => dumpElementItem(decl, defaultDumpOptions, functionContext) ;separator="\n")%>
1202 >>
1203 end dumpMatchLocals;
1204
1205 ✗ template dumpMatchCase(Absyn.Case c, Context context)
1206 ::=
1207 match c
1208 case CASE(__) then
1209 let &as_str = buffer ""
1210 let pattern_str = dumpPattern(pattern, context, &as_str)
1211 let guard_str = match patternGuard case SOME(g) then 'where (<%dumpExp(g, context)%>) '
1212 let eql_str = dumpMatchContents(classPart)
1213 let result_str = dumpExp(result, context)
1214 let cmt_str = dumpCommentStrOpt(comment)
1215 let input_str = match context
1216 case MATCH_CONTEXT(__) then dumpExp(inputExp, context)
1217 else ''
1218 /*
1219 There are more cases in which this as statements can be used to mess up rematch.jl
1220 only a partial fix.
1221 */
1222 if as_str then
1223 <<
1224 <%pattern_str%> <%guard_str%><%cmt_str%> => begin
1225 <%&as_str%>
1226 <%eql_str%>
1227 <%result_str%>
1228 end
1229 >>
1230 else
1231 <<
1232 <%pattern_str%> <%guard_str%><%cmt_str%> => begin
1233 <%eql_str%>
1234 <%result_str%>
1235 end
1236 >>
1237 case ELSE(__) then
1238 let eql_str = dumpMatchContents(classPart)
1239 let result_str = dumpExp(result, context)
1240 let cmt_str = dumpCommentStrOpt(comment)
1241 <<
1242 _ <%cmt_str%> => begin
1243 <%eql_str%>
1244 <%result_str%>
1245 end
1246 >>
1247 end dumpMatchCase;
1248
1249 ✗ template dumpOperator(Absyn.Operator op)
1250 ::= match op
1251 case AND(__) then '&&'
1252 case OR(__) then '||'
1253 case NOT(__) then '!'
1254 case NEQUAL(__) then '!='
1255 else AbsynDumpTpl.dumpOperator(op)
1256 end dumpOperator;
1257
1258 ✗ template dumpCref(Absyn.ComponentRef cref, Context context)
1259 ::=
1260 match cref
1261 case CREF_QUAL(__) then
1262 let ss_str = dumpSubscripts(subscripts, context)
1263 let c_str = dumpCref(componentRef, context)
1264 match name
1265 case "List" then 'ListUtil<%ss_str%>.<%c_str%>'
1266 case "Array" then 'ArrayUtil<%ss_str%>.<%c_str%>'
1267 else '<%name%>.<%c_str%>'
1268 case CREF_IDENT(__) then
1269 '<%name%><%dumpSubscripts(subscripts, context)%>'
1270 case CREF_FULLYQUALIFIED(__) then '.<%dumpCref(componentRef, context)%>'
1271 case WILD(__) then if Config.acceptMetaModelicaGrammar() then "_" else ""
1272 case ALLWILD(__) then '__'
1273 end dumpCref;
1274
1275 ✗ template dumpFunctionArgs(Absyn.FunctionArgs args, Context context)
1276 ::=
1277 match args
1278 case FUNCTIONARGS(__) then
1279 let args_str = (args |> arg => dumpExp(arg, context) ;separator=", ")
1280 let namedargs_str = (argNames |> narg => dumpNamedArg(narg, context) ;separator=", ")
1281 let separator = if args_str then if argNames then ', '
1282 '<%args_str%><%separator%><%namedargs_str%>'
1283 case FOR_ITER_FARG(__) then
1284 let exp_str = dumpExp(exp, context)
1285 let iter_str = (iterators |> i => dumpForIterator(i, context) ;separator=", ")
1286 let iter_names = (iterators |> i => dumpForIteratorName(i, context) ;separator=", ")
1287 let iter_ranges = (iterators |> i => dumpForIteratorRanges(i, context) ;separator=", ")
1288 match iterType
1289 case THREAD(__) then
1290 '@do_threaded_for <%exp_str%> (<%iter_names%>) (<%iter_ranges%>)'
1291 else
1292 '<%exp_str%> for <%iter_str%>'
1293 end dumpFunctionArgs;
1294
1295 ✗ template dumpNamedArg(Absyn.NamedArg narg, Context context)
1296 ::=
1297 match narg
1298 case NAMEDARG(__) then
1299 '<%argName%> = <%dumpExp(argValue, context)%>'
1300 end dumpNamedArg;
1301
1302 ✗ template dumpForIterators(Absyn.ForIterators iters, Context context)
1303 ::= (iters |> i => dumpForIterator(i, context) ;separator=", ")
1304 end dumpForIterators;
1305
1306 ✗ template dumpForIterator(Absyn.ForIterator iterator, Context context)
1307 ::=
1308 match iterator
1309 case ITERATOR(__) then
1310 let range_str = match range case SOME(r) then ' in <%dumpExp(r, context)%>'
1311 let guard_str = match guardExp case SOME(g) then ' if <%dumpExp(g, context)%>'
1312 '<%name%><%range_str%><%guard_str%>'
1313 end dumpForIterator;
1314
1315 ✗ template dumpForIteratorRanges(Absyn.ForIterator iterator, Context context)
1316 ::=
1317 match iterator
1318 case ITERATOR(__) then
1319 let range_str = match range case SOME(r) then '<%dumpExp(r, context)%>'
1320 let guard_str = match guardExp case SOME(g) then ' if <%dumpExp(g, context)%>'
1321 '<%range_str%><%guard_str%>'
1322 end dumpForIteratorRanges;
1323
1324 ✗ template dumpForIteratorName(Absyn.ForIterator iterator, Context context)
1325 ::=
1326 match iterator
1327 case ITERATOR(__) then
1328 '<%name%>'
1329 end dumpForIteratorName;
1330
1331 ✗ template dumpOutputsJL(list<ElementItem> elements)
1332 ::=
1333 let outputStr = (listReverse(elements) |> e => dumpTypeSpecOpt(AbsynUtil.getTypeSpecFromElementItemOpt(e), functionContext) ;separator=", ")
1334 '<%outputStr%>'
1335 end dumpOutputsJL;
1336
1337 annotation(__OpenModelica_Interface="backend_tools");
1338 end AbsynToJulia;
1339