Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 56.7% 247 / 0 / 436
Functions: -% 0 / 1 / 1
Branches: 31.7% 57 / 0 / 180

OMCompiler/Compiler/Template/Tpl.mo
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
37 encapsulated package Tpl
38 "
39 file: Tpl.mo
40 package: Tpl
41 description: Susan
42
43 $Id$
44 "
45
46 protected
47 import Config;
48 import ClockIndexes;
49 import Debug;
50 import Error;
51 import File;
52 import Flags;
53 import List;
54 import Mutable;
55 import Print;
56 import StackOverflow;
57 import StringUtil;
58 import System;
59 import Testsuite;
60
61 // indentation will be implemented through spaces
62 // where tabs will be converted where 1 tab = 4 spaces ??
63 public
64 type Tokens = list<StringToken>;
65
66 public
67 uniontype Text
68 record MEM_TEXT
69 Tokens tokens; //reversed list of tokens
70 list<tuple<Tokens,BlockType>> blocksStack;
71 end MEM_TEXT;
72 record FILE_TEXT
73 Option<Integer> opaqueFile;
74 Mutable<Integer> nchars, aind;
75 Mutable<Boolean> isstart;
76 Mutable<list<BlockTypeFileText>> blocksStack;
77 end FILE_TEXT;
78 end Text;
79
80 public constant Text emptyTxt = MEM_TEXT({}, {});
81
82 public
83 uniontype BlockTypeFileText
84 record BT_FILE_TEXT
85 BlockType bt "The block type";
86 Integer nchars, aind;
87 Boolean isstart;
88 Mutable<Integer> tell "Usage depends on bt; stores the last file position to know if it is empty or not.";
89 Mutable<Option<StringToken>> septok;
90 end BT_FILE_TEXT;
91 end BlockTypeFileText;
92
93 public
94 uniontype StringToken
95 record ST_NEW_LINE "Always outputs the new-line char." end ST_NEW_LINE;
96
97 record ST_STRING "A string without new-lines in it."
98 String value;
99 end ST_STRING;
100
101 record ST_LINE "A (non-empty) string with new-line at the end."
102 String line;
103 end ST_LINE;
104
105 record ST_STRING_LIST "Every string in the list can have a new-line at its end (but does not have to)."
106 list<String> strList;
107 Boolean lastHasNewLine "True when the last string in the list has new-line at the end.";
108 end ST_STRING_LIST;
109
110 record ST_BLOCK
111 Tokens tokens;
112 BlockType blockType;
113 end ST_BLOCK;
114 end StringToken;
115
116 public
117 uniontype BlockType
118 record BT_TEXT end BT_TEXT;
119
120 record BT_INDENT
121 Integer width;
122 end BT_INDENT;
123
124 record BT_ABS_INDENT
125 Integer width;
126 end BT_ABS_INDENT;
127
128 record BT_REL_INDENT
129 Integer offset;
130 end BT_REL_INDENT;
131
132 record BT_ANCHOR
133 Integer offset;
134 end BT_ANCHOR;
135
136 record BT_ITER "Iteration items block, every token in the block is an item.
137 index0 is the active index during the build phase, then it is the last one + 1."
138 IterOptions options;
139 Mutable<Integer> index0;
140 end BT_ITER;
141 end BlockType;
142
143 public
144 uniontype IterOptions
145 record ITER_OPTIONS
146 Integer startIndex0;
147 Option<StringToken> empty;
148 Option<StringToken> separator;
149
150 Integer alignNum "Number of items to be aligned by. When 0, no alignment.";
151 Integer alignOfset;
152 StringToken alignSeparator;
153
154 Integer wrapWidth "Number of chars on a line, after that the wrapping can occur. When 0, no wrapping.";
155 StringToken wrapSeparator;
156 end ITER_OPTIONS;
157 end IterOptions;
158
159 replaceable type ArgType1 subtypeof Any;
160 replaceable type ArgType2 subtypeof Any;
161 replaceable type ArgType3 subtypeof Any;
162 replaceable type ArgType4 subtypeof Any;
163
164 //by default, we will parse new lines in every non-token string
165 public function writeStr
166 input Text inText;
167 input String inStr;
168
169 output Text outText;
170 algorithm
171 outText := match (inText, inStr)
172 local
173 Tokens toks;
174 list<tuple<Tokens,BlockType>> blstack;
175 String str;
176 Text txt;
177
178 //empty string means nothing
179 //to ensure invariant being able to check emptiness only through the tokens (list) emtiness
180 case (txt, "")
181 then
182 txt;
183
184 case (MEM_TEXT(
185 tokens = toks,
186 blocksStack = blstack
187 ), str)
188 guard
189 -1 == System.stringFind(str, "\n")
190 65933426 then
191 MEM_TEXT(ST_STRING(str) :: toks, blstack);
192
193 case (FILE_TEXT(), str)
194 guard
195 -1 == System.stringFind(str, "\n")
196 algorithm
197 2142312 stringFile(inText, str, line=false);
198 then inText;
199
200 // a new-line is inside
201 272505 else
202 writeChars(inText, System.splitOnNewline(inStr, includeDelimiter = true));
203 end match;
204 end writeStr;
205
206 public function writeTok
207 input Text inText;
208 input StringToken inToken;
209
210 output Text outText;
211 algorithm
212 outText := match (inText, inToken)
213 local
214 Text txt;
215 Tokens toks;
216 list<tuple<Tokens,BlockType>> blstack;
217 StringToken tok;
218
219 //to ensure invariant being able to check emptiness only through the tokens (list) emtiness
220 //should not happen, tokens must have at least one element
221 case (txt, ST_BLOCK( tokens = {} ))
222 then
223 txt;
224
225 //same as above - compiler should not generate this value in any case
226 case (txt, ST_STRING( value = "" ))
227 then
228 txt;
229
230 case (MEM_TEXT(
231 tokens = toks,
232 blocksStack = blstack
233 ), tok)
234 60553134 then
235 MEM_TEXT(tok :: toks, blstack);
236
237 case (FILE_TEXT(), tok)
238 algorithm
239 12513000 tokFileText(inText, tok);
240 then inText;
241
242 end match;
243 end writeTok;
244
245 public function writeText
246 input Text inText;
247 input Text inTextToWrite;
248
249 output Text outText;
250 algorithm
251 outText := match (inText, inTextToWrite)
252 local
253 Tokens toks, txttoks;
254 list<tuple<Tokens,BlockType>> blstack;
255 Text txt;
256
257 //to ensure invariant being able to check emptiness only through the tokens (list) emtiness
258 case (txt, MEM_TEXT( tokens = {} ) )
259 then
260 txt;
261
262 case (MEM_TEXT(
263 tokens = toks,
264 blocksStack = blstack
265 ),
266 MEM_TEXT(
267 tokens = txttoks,
268 blocksStack = {}
269 ))
270 58451632 then
271 MEM_TEXT(ST_BLOCK(txttoks, BT_TEXT()) :: toks, blstack);
272
273 case (FILE_TEXT(),
274 MEM_TEXT(
275 tokens = txttoks,
276 blocksStack = {}
277 ))
278 algorithm
279
2/2
✓ Branch 1 taken 6603391 times.
✓ Branch 2 taken 1136731 times.
7740122 for tok in listReverse(txttoks) loop
280 6603391 writeTok(inText, tok);
281 end for;
282 then inText;
283
284 //should not ever happen
285 //- when compilation is correct, this is impossible (only completed texts can be accessible to write out)
286 else
287 algorithm
288 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.writeText failed - incomplete text was passed to be written\n");
289 ✗ then
290 fail();
291 end match;
292 end writeText;
293
294 protected function writeChars
295 input Text inText;
296 input list<String> inChars;
297
298 output Text outText;
299 algorithm
300 outText := match (inText, inChars)
301 local
302 Text txt;
303 String c;
304 list<String> chars, lschars;
305 Boolean isline;
306
307 case (txt, {} )
308 then
309 txt;
310
311 //leading new-lines
312 case (txt, "\n" :: chars )
313 algorithm
314 25924 txt := newLine(txt);
315 25924 then
316 writeChars(txt, chars);
317
318 case (txt, "\r\n" :: chars )
319 algorithm
320 ✗ txt := newLine(txt);
321 ✗ then
322 writeChars(txt, chars);
323
324 //non-new-line at the start of the string, so a string or line only follows
325 case (txt, c :: chars )
326 algorithm
327 1733125 (lschars, chars, isline) := takeLineOrString(chars);
328 1733125 txt := writeLineOrStr(txt, stringAppendList(c :: lschars), isline);
329 //Error txt = writeLineOrStr(txt, stringCharListString( str :: lschars), isline);
330 1733125 then
331 writeChars(txt, chars);
332
333 //should not ever happen
334 case (_ , _)
335 algorithm
336 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.writeChars failed.\n");
337 ✗ then
338 fail();
339 end match;
340 end writeChars;
341
342
343 protected function writeLineOrStr
344 input Text inText;
345 input String inStr;
346 input Boolean inIsLine;
347
348 output Text outText;
349 algorithm
350 outText := match (inText, inStr, inIsLine)
351 local
352 Tokens toks;
353 list<tuple<Tokens,BlockType>> blstack;
354 String str;
355 Text txt;
356
357 //empty string means nothing
358 //to ensure invariant being able to check emptiness only through the tokens (list) emtiness
359 //should not happen
360 case (txt, "", _)
361 then
362 txt;
363
364 case (MEM_TEXT(
365 tokens = toks,
366 blocksStack = blstack
367 ), str, false)
368 21630 then
369 MEM_TEXT(ST_STRING(str) :: toks, blstack);
370
371 case (MEM_TEXT(
372 tokens = toks,
373 blocksStack = blstack
374 ), str, true)
375 1582286 then
376 MEM_TEXT(ST_LINE(str) :: toks, blstack);
377
378 case (FILE_TEXT(), str, _)
379 algorithm
380 931167 stringFile(inText, str, line=inIsLine);
381 then inText;
382
383 end match;
384 end writeLineOrStr;
385
386
387 protected function takeLineOrString
388 input list<String> inChars;
389
390 output list<String> outTillNewLineChars;
391 output list<String> outRestChars;
392 output Boolean outIsLine;
393 algorithm
394 (outTillNewLineChars, outRestChars, outIsLine) := match inChars
395 local
396 String char;
397 list<String> tnlchars, restchars, chars;
398 Boolean isline;
399
400 case {}
401 then
402 ({}, {}, false);
403
404 case "\n" :: chars
405 then
406 ({"\n"}, chars, true);
407
408 case "\r\n" :: chars
409 then
410 ({"\n"}, chars, true);
411
412 case char :: chars
413 algorithm
414 ✗ (tnlchars, restchars, isline) := takeLineOrString(chars);
415 ✗ then
416 (char :: tnlchars, restchars, isline);
417
418 end match;
419 end takeLineOrString;
420
421
422 public function softNewLine
423 input Text inText;
424 output Text outText;
425 algorithm
426 outText := match inText
427 local
428 Text txt;
429 Tokens toks;
430
431 //empty - nothing
432 case txt as MEM_TEXT(tokens = {} )
433 then
434 txt;
435
436 case txt as MEM_TEXT(tokens = toks)
437 algorithm
438 //at start of line - nothing
439
2/2
✓ Branch 1 taken 975635 times.
✓ Branch 2 taken 1337958 times.
2313593 if not isAtStartOfLine(txt) then
440 //otherwise put normal new-line
441 975635 txt.tokens := ST_NEW_LINE() :: toks;
442 end if;
443 then txt;
444
445 case FILE_TEXT()
446 algorithm
447 //at start of line - nothing
448
2/2
✓ Branch 1 taken 584254 times.
✓ Branch 2 taken 1395390 times.
1979644 if not isAtStartOfLine(inText) then
449 //otherwise put normal new-line
450 584254 newlineFile(inText);
451 end if;
452 then inText;
453
454 //should not ever happen
455 else
456 algorithm
457 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.softNL failed. \n");
458 ✗ then
459 fail();
460
461 end match;
462 end softNewLine;
463
464 protected function isAtStartOfLine
465 input Text text;
466 output Boolean b;
467 algorithm
468 b := match text
469 local
470 StringToken tok;
471
472 case MEM_TEXT(tokens=tok::_)
473 2313593 then isAtStartOfLineTok(tok);
474
475 case FILE_TEXT()
476 1979644 then Mutable.access(text.isstart);
477
478 end match;
479 end isAtStartOfLine;
480
481 protected function isAtStartOfLineTok
482 input StringToken inTok;
483 output Boolean b;
484 algorithm
485 b := match inTok
486 local
487 StringToken tok;
488
489 //a new-line at the end
490 case ST_NEW_LINE()
491 then true;
492
493 //a new-line at the end
494 case ST_LINE()
495 then true;
496
497 //a new-line at the end
498 case ST_STRING_LIST(lastHasNewLine = true)
499 then true;
500
501 //recursively in the last block
502 case ST_BLOCK(
503 tokens = (tok :: _) )
504 1296303 then isAtStartOfLineTok(tok);
505
506
507 // otherwise fail - not at the start
508 else false;
509
510 end match;
511 end isAtStartOfLineTok;
512
513
514 public function newLine
515 input Text inText;
516 output Text outText;
517 algorithm
518 outText := match inText
519 local
520 Tokens toks;
521 list<tuple<Tokens,BlockType>> blstack;
522
523 case MEM_TEXT(tokens = toks,blocksStack = blstack)
524 14038 then MEM_TEXT(ST_NEW_LINE() :: toks, blstack);
525
526 case FILE_TEXT()
527 algorithm
528 11886 newlineFile(inText);
529 then inText;
530 end match;
531 end newLine;
532
533
534 public function pushBlock
535 input output Text txt;
536 input BlockType inBlockType;
537 algorithm
538 txt := match txt
539 local
540 Tokens toks;
541 list<tuple<Tokens,BlockType>> blstack;
542 Integer nchars, aind, w;
543 Boolean isstart;
544
545 case MEM_TEXT(
546 tokens = toks,
547 blocksStack = blstack
548 )
549 3529100 then
550 MEM_TEXT(
551 {},
552 (toks, inBlockType) :: blstack
553 );
554
555 case FILE_TEXT()
556 algorithm
557 320381 nchars := Mutable.access(txt.nchars);
558 320381 aind := Mutable.access(txt.aind);
559 320381 isstart := Mutable.access(txt.isstart);
560
2/2
✓ Branch 3 taken 9373 times.
✓ Branch 4 taken 311008 times.
650135 Mutable.update(txt.blocksStack, BT_FILE_TEXT(inBlockType, nchars, aind, isstart, Mutable.create(textFileTell(txt)), Mutable.create(NONE()))::Mutable.access(txt.blocksStack));
561 () := match inBlockType
562 case BT_INDENT(width = w)
563 algorithm
564 270749 Mutable.update(txt.nchars, nchars+w);
565 270749 Mutable.update(txt.aind, aind+w);
566 then ();
567 case BT_ABS_INDENT(width = w)
568 algorithm
569 ✗ if isstart then
570 ✗ Mutable.update(txt.nchars, 0);
571 end if;
572 ✗ Mutable.update(txt.aind, w);
573 then ();
574 case BT_REL_INDENT(offset = w)
575 algorithm
576 ✗ Mutable.update(txt.aind, aind + w);
577 then ();
578 case BT_ANCHOR(offset = w)
579 algorithm
580 ✗ Mutable.update(txt.aind, nchars + w);
581 then ();
582 else ();
583 end match;
584 then txt;
585
586 //should not ever happen
587 else
588 algorithm
589 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.pushBlock failed \n");
590 ✗ then
591 fail();
592
593 end match;
594 end pushBlock;
595
596
597 public function popBlock
598 input output Text txt;
599 algorithm
600 txt := match txt
601 local
602 Tokens toks, stacktoks;
603 list<tuple<Tokens,BlockType>> blstack;
604 BlockType blType;
605 list<BlockTypeFileText> rest;
606 BlockTypeFileText blk;
607 Boolean oldisstart;
608
609 //when nothing was put, just pop tokens from the stack and no block output
610 case MEM_TEXT(
611 tokens = {},
612 blocksStack = ( (stacktoks,_) :: blstack )
613 )
614 5793 then
615 MEM_TEXT( stacktoks, blstack);
616
617 case MEM_TEXT(
618 tokens = toks,
619 blocksStack = ( (stacktoks, blType) :: blstack)
620 )
621 3517514 then
622 MEM_TEXT(
623 ST_BLOCK(toks, blType) :: stacktoks,
624 blstack);
625
626 case FILE_TEXT()
627 algorithm
628
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 270749 times.
270749 blk::rest := Mutable.access(txt.blocksStack);
629 270749 Mutable.update(txt.blocksStack, rest);
630 () := match blk.bt
631 case BT_INDENT()
632 algorithm
633
2/2
✓ Branch 1 taken 266489 times.
✓ Branch 2 taken 4260 times.
270749 if Mutable.access(txt.isstart) then
634 266489 Mutable.update(txt.nchars, blk.nchars);
635 end if;
636 270749 Mutable.update(txt.aind, blk.aind);
637 then ();
638 case _ guard match blk.bt
639 // All these have the same cases
640 case BT_ABS_INDENT() then true;
641 case BT_REL_INDENT() then true;
642 case BT_ANCHOR() then true;
643 end match
644 algorithm
645 ✗ oldisstart := Mutable.access(txt.isstart);
646 ✗ if oldisstart then
647 ✗ if textFileTell(txt)==Mutable.access(blk.tell) then
648 // No update, restore nchars
649 ✗ Mutable.update(txt.nchars, blk.nchars);
650 else
651 // Update; restore depends on if we are at start of line
652 ✗ if Mutable.access(txt.isstart) then
653 ✗ Mutable.update(txt.nchars, blk.aind);
654 end if;
655 end if;
656 else
657 // Was not at start of line before
658 ✗ if Mutable.access(txt.isstart) then
659 ✗ Mutable.update(txt.nchars, blk.aind);
660 end if;
661 end if;
662 ✗ Mutable.update(txt.aind, blk.aind);
663 then ();
664 else ();
665 end match;
666 then txt;
667
668 //should not ever happen
669 //- when compilation is correct, this is impossible (pushs and pops should be balanced)
670 case _
671 algorithm
672 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.popBlock failed - probably pushBlock and popBlock are not well balanced !\n");
673 ✗ then
674 fail();
675 end match;
676 end popBlock;
677
678
679 public function pushIter
680 input output Text txt;
681 input IterOptions inIterOptions;
682 algorithm
683 txt := match (txt, inIterOptions)
684 local
685 Tokens toks;
686 list<tuple<Tokens,BlockType>> blstack;
687 IterOptions iopts;
688 Integer i0;
689
690 case (MEM_TEXT(
691 tokens = toks,
692 blocksStack = blstack
693 ),
694 iopts as ITER_OPTIONS(
695 startIndex0 = i0))
696 6127494 then //let the existing tokens on stack in the text block and start iterating
697 MEM_TEXT(
698 {},
699 ({}, BT_ITER(iopts, Mutable.create(i0))) :: (toks, BT_TEXT()) :: blstack);
700
701 case (FILE_TEXT(),
702 iopts as ITER_OPTIONS(
703 startIndex0 = i0))
704 algorithm
705 () := match iopts
706 case ITER_OPTIONS(alignNum=0, wrapWidth=0) then ();
707 else
708 algorithm
709 ✗ Error.addInternalError("Tpl.mo FILE_TEXT does not support aligning or wrapping elements", sourceInfo());
710 ✗ then fail();
711 end match;
712 49632 pushBlock(txt, BT_ITER(inIterOptions, Mutable.create(i0)));
713 then txt;
714
715 //should not ever happen
716 case (_ , _)
717 algorithm
718 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.pushIter failed \n");
719 ✗ then
720 fail();
721 end match;
722 end pushIter;
723
724
725 public function popIter
726 input output Text txt;
727 algorithm
728 txt := match txt
729 local
730 Tokens stacktoks, itertoks;
731 list<tuple<Tokens,BlockType>> blstack;
732 BlockType blType;
733
734 //nothing was iterated, pop only the stacked tokens
735 case MEM_TEXT(
736 tokens = {},
737 blocksStack = ( ({},_) :: (stacktoks,_) :: blstack )
738 )
739 232272 then
740 MEM_TEXT(stacktoks, blstack);
741
742 case MEM_TEXT(
743 tokens = {},
744 blocksStack = ( (itertoks,blType) :: (stacktoks,_) :: blstack )
745 )
746 5662950 then
747 MEM_TEXT(
748 ST_BLOCK(itertoks, blType) :: stacktoks,
749 blstack);
750
751 case FILE_TEXT()
752 algorithm
753 49632 Mutable.update(txt.blocksStack, listRest(Mutable.access(txt.blocksStack)));
754 then txt;
755
756 //should not ever happen
757 //- when compilation is correct, this is impossible (pushs and pops should be balanced)
758 case _
759 algorithm
760 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.popIter failed - probably pushIter and popIter are not well balanced or something was written between the last nextIter and popIter ?\n");
761 ✗ then
762 fail();
763 end match;
764 end popIter;
765
766
767 public function nextIter
768 input output Text txt;
769 algorithm
770 txt := match txt
771 local
772 Tokens toks, itertoks;
773 StringToken tok, emptok;
774 list<tuple<Tokens,BlockType>> blstack;
775 IterOptions iopts;
776 Mutable<Integer> i0, tell;
777 BlockType bt;
778 Integer tellpos, curIndex;
779 Text txt2;
780 Boolean haveToken;
781 Mutable<Option<StringToken>> septok;
782
783 //empty iteration segment and 'empty' option is NONE(), so do nothing
784 case txt as MEM_TEXT(
785 tokens = {},
786 blocksStack = (_, BT_ITER(options = ITER_OPTIONS(empty = NONE()) )) :: _
787 )
788 then
789 txt;
790
791 //empty iteration segment, but 'empty' option is specified, so put the value
792 case MEM_TEXT(
793 tokens = {},
794 blocksStack = (itertoks, bt as BT_ITER(
795 options = ITER_OPTIONS(
796 empty = SOME(emptok)),
797 index0 = i0)) :: blstack
798 )
799 algorithm
800 94331 Mutable.update(i0, Mutable.access(i0) + 1);
801 188662 then
802 MEM_TEXT(
803 {},
804 (emptok :: itertoks, bt) :: blstack
805 );
806
807
808 //one token, put it as it is
809 case MEM_TEXT(
810 tokens = {tok},
811 blocksStack = (itertoks, bt as BT_ITER(index0 = i0)) :: blstack
812 )
813 algorithm
814 2897403 Mutable.update(i0, Mutable.access(i0) + 1);
815 5794806 then
816 MEM_TEXT(
817 {},
818 (tok :: itertoks, bt) :: blstack
819 );
820
821 //more tokens, put them as a text block
822 case MEM_TEXT(
823 tokens = toks /* as (_::_) */,
824 blocksStack = (itertoks, bt as BT_ITER(index0 = i0)) :: blstack
825 )
826 algorithm
827 2538483 Mutable.update(i0, Mutable.access(i0) + 1);
828 7615449 then
829 MEM_TEXT(
830 {},
831 (ST_BLOCK(toks,BT_TEXT()) :: itertoks, bt) :: blstack
832 );
833
834 case FILE_TEXT()
835 algorithm
836 () := match listGet(Mutable.access(txt.blocksStack),1)
837 case BT_FILE_TEXT(bt=BT_ITER(options = iopts, index0=i0), tell=tell, septok=septok)
838 algorithm
839 // Either the iterator always increments, or the file position changed
840 423533 tellpos := textFileTell(txt);
841
1/2
✓ Branch 1 taken 423533 times.
✗ Branch 2 not taken.
423533 if Mutable.access(tell)<>tellpos then
842 // Update file position and increment i0. Else, we are at the same position and state as before.
843 423533 Mutable.update(tell, tellpos);
844 txt2 := txt;
845 haveToken := true;
846 else
847 // File position did not change, but we might have the empty specifier
848 txt2 := match iopts.empty
849 case NONE()
850 algorithm
851 haveToken := false;
852 then txt;
853 case SOME(emptok)
854 algorithm
855 ✗ Mutable.update(i0, Mutable.access(i0) + 1);
856 haveToken := true;
857 ✗ then writeTok(txt, emptok);
858 end match;
859 end if;
860 if haveToken then
861 // Handle separator
862 423533 curIndex := Mutable.access(i0);
863 423533 Mutable.update(septok, iopts.separator);
864 423533 Mutable.update(i0, curIndex + 1);
865 end if;
866 then ();
867 end match;
868 then txt2;
869
870 //should not ever happen
871 else
872 algorithm
873 ✗ Error.addInternalError("-!!!Tpl.nextIter failed - nextIter was called in a non-iteration context?", sourceInfo());
874 ✗ then
875 fail();
876 end match;
877 end nextIter;
878
879
880 public function getIteri_i0
881 input Text inText;
882 output Integer outI0;
883 algorithm
884 outI0 := match inText
885 local
886 Mutable<Integer> i0;
887
888 case MEM_TEXT(
889 blocksStack = (_, BT_ITER(index0 = i0)) :: _
890 )
891 222900 then
892 Mutable.access(i0);
893
894 case FILE_TEXT()
895 25998 then match listGet(Mutable.access(inText.blocksStack),1) case BT_FILE_TEXT(bt=BT_ITER(index0=i0)) then Mutable.access(i0); end match;
896
897 //should not ever happen
898 case _
899 algorithm
900 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.getIter_i0 failed - getIter_i0 was called in a non-iteration context ? \n");
901 ✗ then
902 fail();
903 end match;
904 end getIteri_i0;
905
906 public function textString "function: textString:
907 This function renders a (memory-)text to string."
908 input Text inText;
909 output String outString;
910 algorithm
911 outString := match inText
912 local
913 Text txt;
914 String str;
915 Integer handle;
916 case txt
917 algorithm
918 15285096 handle := Print.saveAndClearBuf();
919 15285096 textStringBuf(txt);
920 15285096 str := Print.getString();
921 15285096 Print.restoreBuf(handle);
922 then
923 str;
924
925 //should not ever happen
926 case _
927 algorithm
928 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.textString failed.\n");
929 ✗ then
930 fail();
931 end match;
932 end textString;
933
934 public function textStringBuf "function: textStringBuf:
935 This function renders a (memory-)text to (Print.)string buffer."
936 input Text inText;
937 algorithm
938 () := match inText
939 local
940 Tokens toks;
941
942 case MEM_TEXT(
943 tokens = toks,
944 blocksStack = {}
945 )
946 algorithm
947 15293628 tokensString(listReverse(toks), 0, true, 0);
948 then
949 ();
950
951 case MEM_TEXT(
952 blocksStack = _::_
953 )
954 algorithm
955 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.textString failed - a non-comlete text was given.\n");
956 ✗ then
957 fail();
958
959 //should not ever happen
960 case _
961 algorithm
962 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.textString failed.\n");
963 ✗ then
964 fail();
965 end match;
966 end textStringBuf;
967
968 protected function tokensString
969 input Tokens inTokens;
970 input output Integer actualPositionOnLine;
971 input output Boolean atStartOfLine;
972 input output Integer afterNewLineIndent;
973 algorithm
974
2/2
✓ Branch 0 taken 92243545 times.
✓ Branch 1 taken 40820515 times.
133064060 for tok in inTokens loop
975 92243545 (actualPositionOnLine, atStartOfLine, afterNewLineIndent) := tokString(tok, actualPositionOnLine, atStartOfLine, afterNewLineIndent);
976 end for;
977 end tokensString;
978
979 protected function tokensFile
980 input File.File file;
981 input Tokens inTokens;
982 input output Integer actualPositionOnLine;
983 input output Boolean atStartOfLine;
984 input output Integer afterNewLineIndent;
985 algorithm
986
2/2
✓ Branch 0 taken 29199564 times.
✓ Branch 1 taken 9655510 times.
38855074 for tok in inTokens loop
987 29199564 (actualPositionOnLine, atStartOfLine, afterNewLineIndent) := tokFile(file, tok, actualPositionOnLine, atStartOfLine, afterNewLineIndent);
988 end for;
989 end tokensFile;
990
991 protected function tokString
992 input StringToken inStringToken;
993 input Integer inActualPositionOnLine;
994 input Boolean inAtStartOfLine;
995 input Integer inAfterNewLineIndent;
996
997 output Integer outActualPositionOnLine;
998 output Boolean outAtStartOfLine;
999 output Integer outAfterNewLineIndent;
1000 algorithm
1001 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1002 := match (inStringToken, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1003 local
1004 Tokens toks;
1005 BlockType bt;
1006 String str;
1007 list<String> strLst;
1008 Integer nchars, aind, blen;
1009 Boolean isstart;
1010
1011 case (ST_NEW_LINE(), _, _, aind)
1012 algorithm
1013 1559167 Print.printBufNewLine();
1014 1559167 then
1015 (aind, true, aind);
1016
1017 case (ST_STRING(value = str), nchars, true, aind)
1018 algorithm
1019 11647533 blen := Print.getBufLength();
1020 11647533 Print.printBufSpace(nchars);
1021 11647533 Print.printBuf(str);
1022 11647533 blen := Print.getBufLength() - blen;
1023 //str = spaceStr(nchars) + str; //indent is actually stored in nchars when on start of the line
1024 11647533 then
1025 (blen, false, aind);
1026
1027 case (ST_STRING(value = str), nchars, false, aind)
1028 algorithm
1029 54945680 blen := Print.getBufLength();
1030 54945680 Print.printBuf(str);
1031 54945680 blen := Print.getBufLength() - blen;
1032 54945680 then
1033 (nchars + blen, false, aind);
1034
1035 case (ST_LINE(line = str), nchars, true, aind)
1036 algorithm
1037 569593 Print.printBufSpace(nchars);
1038 569593 Print.printBuf(str);
1039 //str = spaceStr(nchars) + str; //indent is actually stored in nchars when on start of the line
1040 569593 then
1041 (aind, true, aind);
1042
1043 case (ST_LINE(line = str), _, false, aind)
1044 algorithm
1045 410072 Print.printBuf(str);
1046 410072 then
1047 (aind, true, aind);
1048
1049 case (ST_STRING_LIST( strList = strLst ), nchars, isstart, aind)
1050 algorithm
1051 464869 (nchars, isstart, aind)
1052 := stringListString(strLst, nchars, isstart, aind);
1053 then
1054 (nchars, isstart, aind);
1055
1056 case (ST_BLOCK(
1057 tokens = toks,
1058 blockType = bt), nchars, isstart, aind)
1059 algorithm
1060 27894032 (nchars, isstart, aind)
1061 := blockString(bt, listReverse(toks), nchars, isstart, aind);
1062 then
1063 (nchars, isstart, aind);
1064
1065 //should not ever happen
1066 else
1067 algorithm
1068 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.tokString failed.\n");
1069 ✗ then
1070 fail();
1071 end match;
1072 end tokString;
1073
1074 protected function tokFileText
1075 input Text inText;
1076 input StringToken inStringToken;
1077 input Boolean doHandleTok=true;
1078 protected
1079 File.File file = File.File(getTextOpaqueFile(inText));
1080 Integer nchars, aind;
1081 Boolean isstart;
1082 algorithm
1083
2/2
✓ Branch 0 taken 12513000 times.
✓ Branch 1 taken 405987 times.
12918987 if doHandleTok then
1084 12513000 handleTok(inText);
1085 end if;
1086 () := match inText
1087 case FILE_TEXT()
1088 algorithm
1089 12918987 nchars := Mutable.access(inText.nchars);
1090 12918987 aind := Mutable.access(inText.aind);
1091 12918987 isstart := Mutable.access(inText.isstart);
1092 12918987 (nchars, isstart, aind) := tokFile(file, inStringToken, nchars, isstart, aind);
1093 12918987 Mutable.update(inText.nchars, nchars);
1094 12918987 Mutable.update(inText.aind, aind);
1095
2/2
✓ Branch 0 taken 9939619 times.
✓ Branch 1 taken 2979368 times.
22858606 Mutable.update(inText.isstart, isstart);
1096 then ();
1097 end match;
1098 end tokFileText;
1099
1100 protected function tokFile
1101 input File.File file;
1102 input StringToken inStringToken;
1103 input output Integer nchars;
1104 input output Boolean isstart;
1105 input output Integer aind;
1106 algorithm
1107 (nchars, isstart, aind) := match (inStringToken, nchars, isstart, aind)
1108 local
1109 Tokens toks;
1110 BlockType bt;
1111 String str;
1112 list<String> strLst;
1113
1114 case (ST_NEW_LINE(), _, _, aind)
1115 algorithm
1116 3111214 File.write(file, "\n");
1117 3111214 then (aind, true, aind);
1118
1119 case (ST_STRING(value = str), nchars, true, aind)
1120 algorithm
1121 4165253 File.writeSpace(file, nchars);
1122 4165253 File.write(file, str);
1123 4165253 then
1124 (nchars+stringLength(str), false, aind);
1125
1126 case (ST_STRING(value = str), nchars, false, aind)
1127 algorithm
1128 23180904 File.write(file, str);
1129 23180904 then
1130 (nchars + stringLength(str), false, aind);
1131
1132 case (ST_LINE(line = str), nchars, true, aind)
1133 algorithm
1134 1482441 File.writeSpace(file, nchars);
1135 1482441 File.write(file, str);
1136 1482441 then
1137 (aind, true, aind);
1138
1139 case (ST_LINE(line = str), _, false, aind)
1140 algorithm
1141 861272 File.write(file, str);
1142 861272 then
1143 (aind, true, aind);
1144
1145 case (ST_STRING_LIST( strList = strLst ), nchars, isstart, aind)
1146 algorithm
1147 1270675 (nchars, isstart, aind)
1148 := stringListFile(file, strLst, nchars, isstart, aind);
1149 then
1150 (nchars, isstart, aind);
1151
1152 case (ST_BLOCK(
1153 tokens = toks,
1154 blockType = bt), nchars, isstart, aind)
1155 algorithm
1156 9897372 (nchars, isstart, aind)
1157 := blockFile(file, bt, listReverse(toks), nchars, isstart, aind);
1158 then
1159 (nchars, isstart, aind);
1160 end match;
1161 end tokFile;
1162
1163 protected function stringListString
1164 input list<String> inStringList;
1165 input Integer inActualPositionOnLine;
1166 input Boolean inAtStartOfLine;
1167 input Integer inAfterNewLineIndent;
1168
1169 output Integer outActualPositionOnLine;
1170 output Boolean outAtStartOfLine;
1171 output Integer outAfterNewLineIndent;
1172 algorithm
1173 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1174 := match (inStringList, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1175 local
1176 String str;
1177 list<String> strLst;
1178 Integer nchars, aind, blen;
1179 Boolean isstart, hasNL;
1180
1181 case ({}, _, isstart, aind)
1182 then
1183 (aind, isstart, aind);
1184
1185 //empty string ... for sure -> it can be a special case when allowed; when let for the case at start of a line, it would output an indent
1186 case ("" :: strLst, nchars, isstart, aind)
1187 algorithm
1188 ✗ (nchars, isstart, aind)
1189 := stringListString(strLst, nchars, isstart, aind);
1190 then
1191 (nchars, isstart, aind);
1192
1193
1194 //at start, new line or no new line
1195 case (str :: strLst, nchars, true, aind)
1196 algorithm
1197 719539 blen := Print.getBufLength();
1198 719539 Print.printBufSpace(nchars); //indent is actually stored in nchars when on start of the line
1199 719539 Print.printBuf(str);
1200 719539 blen := Print.getBufLength() - blen;
1201 719539 hasNL := Print.hasBufNewLineAtEnd();
1202
2/2
✓ Branch 0 taken 240714 times.
✓ Branch 1 taken 478825 times.
719539 nchars := if hasNL then aind else blen;
1203 719539 (nchars, isstart, aind) := stringListString(strLst, nchars, hasNL, aind);
1204 then
1205 (nchars, isstart, aind);
1206
1207 //not at start, new line or no new line
1208 case (str :: strLst, nchars, false, aind)
1209 algorithm
1210 367852 blen := Print.getBufLength();
1211 367852 Print.printBuf(str);
1212 367852 blen := Print.getBufLength() - blen;
1213 367852 hasNL := Print.hasBufNewLineAtEnd();
1214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367852 times.
367852 nchars := if hasNL then aind else nchars+blen;
1215 367852 (nchars, isstart, aind) := stringListString(strLst, nchars, hasNL, aind);
1216 then
1217 (nchars, isstart, aind);
1218
1219 //should not ever happen
1220 else
1221 algorithm
1222 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.stringListString failed.\n");
1223 ✗ then
1224 fail();
1225 end match;
1226 end stringListString;
1227
1228 protected function stringListFile
1229 input File.File file;
1230 input list<String> inStringList;
1231 input output Integer nchars;
1232 input output Boolean isstart;
1233 input output Integer aind;
1234 algorithm
1235 (nchars, isstart, aind)
1236 := match (inStringList, nchars, isstart, aind)
1237 local
1238 String str;
1239 list<String> strLst;
1240 Boolean hasNL;
1241
1242 case ({}, _, isstart, aind)
1243 then
1244 (aind, isstart, aind);
1245
1246 //empty string ... for sure -> it can be a special case when allowed; when let for the case at start of a line, it would output an indent
1247 case ("" :: strLst, nchars, isstart, aind)
1248 algorithm
1249 ✗ (nchars, isstart, aind)
1250 := stringListFile(file, strLst, nchars, isstart, aind);
1251 then
1252 (nchars, isstart, aind);
1253
1254
1255 //at start, new line or no new line
1256 case (str :: strLst, nchars, true, aind)
1257 algorithm
1258 2291114 File.writeSpace(file, nchars);
1259 2291114 File.write(file, str);
1260 2291114 hasNL := StringUtil.endsWithNewline(str);
1261
2/2
✓ Branch 0 taken 622472 times.
✓ Branch 1 taken 1668642 times.
2291114 nchars := if hasNL then aind else (nchars+stringLength(str));
1262 2291114 (nchars, isstart, aind) := stringListFile(file, strLst, nchars, hasNL, aind);
1263 then
1264 (nchars, isstart, aind);
1265
1266 //not at start, new line or no new line
1267 case (str :: strLst, nchars, false, aind)
1268 algorithm
1269 906151 File.write(file, str);
1270 906151 hasNL := StringUtil.endsWithNewline(str);
1271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 906151 times.
906151 nchars := if hasNL then aind else (nchars+stringLength(str));
1272 906151 (nchars, isstart, aind) := stringListFile(file, strLst, nchars, hasNL, aind);
1273 then
1274 (nchars, isstart, aind);
1275
1276 //should not ever happen
1277 else
1278 algorithm
1279 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.stringListFile failed.\n");
1280 ✗ then
1281 fail();
1282 end match;
1283 end stringListFile;
1284
1285 protected function blockString
1286 input BlockType inBlockType;
1287 input Tokens inTokens;
1288 input Integer inActualPositionOnLine;
1289 input Boolean inAtStartOfLine;
1290 input Integer inAfterNewLineIndent;
1291
1292 output Integer outActualPositionOnLine;
1293 output Boolean outAtStartOfLine;
1294 output Integer outAfterNewLineIndent;
1295 algorithm
1296 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1297 := match (inBlockType, inTokens, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1298 local
1299 Tokens toks;
1300 StringToken septok, tok, asep, wsep;
1301 Integer nchars, tsnchars, aind, w, aoffset, anum, wwidth, blen;
1302 Boolean isstart;
1303
1304 case (BT_TEXT(), toks, nchars, isstart, aind)
1305 algorithm
1306 24154886 (nchars, isstart, aind)
1307 := tokensString(toks, nchars, isstart, aind);
1308 then
1309 (nchars, isstart, aind);
1310
1311 case (BT_INDENT(width = w), toks, nchars, true, aind)
1312 algorithm
1313 415262 (tsnchars, isstart)
1314 := tokensString(toks, w + nchars, true, w + aind);
1315
2/2
✓ Branch 0 taken 64511 times.
✓ Branch 1 taken 350751 times.
415262 nchars := if isstart then nchars else tsnchars; //pop indent when at the start of a line
1316 415262 then
1317 (nchars, isstart, aind);
1318
1319 case (BT_INDENT(width = w), toks, nchars, false, aind)
1320 algorithm
1321 922317 Print.printBufSpace(w);
1322 922317 (tsnchars, isstart)
1323 := tokensString(toks, w + nchars, false, w + aind);
1324
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 922251 times.
922317 nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1325 922317 then
1326 (nchars, isstart, aind);
1327
1328 case (BT_ABS_INDENT(width = w), toks, nchars, true, aind)
1329 algorithm
1330 1834 blen := Print.getBufLength();
1331 1834 (tsnchars, isstart)
1332 := tokensString(toks, 0, true, w); //discard an indent when at the start of a line
1333 1834 blen := Print.getBufLength() - blen;
1334
3/4
✓ Branch 0 taken 1834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1833 times.
1834 nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1335 1834 then
1336 (nchars, isstart, aind);
1337
1338 case (BT_ABS_INDENT(width = w), toks, nchars, false, aind)
1339 algorithm
1340 17794 (tsnchars, isstart)
1341 := tokensString(toks, nchars, false, w);
1342
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 17712 times.
17794 nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1343 17794 then
1344 (nchars, isstart, aind);
1345
1346 case (BT_REL_INDENT(offset = w), toks, nchars, true, aind)
1347 algorithm
1348 ✗ blen := Print.getBufLength();
1349 ✗ (tsnchars, isstart)
1350 := tokensString(toks, nchars, true, aind + w);
1351 ✗ blen := Print.getBufLength() - blen;
1352 ✗ nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1353 ✗ then
1354 (nchars, isstart, aind);
1355
1356 case (BT_REL_INDENT(offset = w), toks, nchars, false, aind)
1357 algorithm
1358 ✗ (tsnchars, isstart)
1359 := tokensString(toks, nchars, false, aind + w);
1360 ✗ nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1361 ✗ then
1362 (nchars, isstart, aind);
1363
1364 case (BT_ANCHOR(offset = w), toks, nchars, true, aind)
1365 algorithm
1366 ✗ blen := Print.getBufLength();
1367 ✗ (tsnchars, isstart)
1368 := tokensString(toks, nchars, true, nchars + w);
1369 ✗ blen := Print.getBufLength() - blen;
1370 ✗ nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1371 ✗ then
1372 (nchars, isstart, aind);
1373
1374 case (BT_ANCHOR(offset = w), toks, nchars, false, aind)
1375 algorithm
1376 ✗ (tsnchars, isstart)
1377 := tokensString(toks, nchars, false, nchars + w);
1378 ✗ nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1379 ✗ then
1380 (nchars, isstart, aind);
1381
1382
1383 //iter block, no tokens ... should be impossible, but ...
1384 case (BT_ITER(), {}, nchars, isstart, aind)
1385 ✗ then
1386 (nchars, isstart, aind);
1387
1388 //concat ... i.e. text
1389 case (BT_ITER(options = ITER_OPTIONS(
1390 separator = NONE(),
1391 alignNum = 0,
1392 wrapWidth = 0)), toks, nchars, isstart, aind)
1393 algorithm
1394 14794 (nchars, isstart, aind)
1395 := tokensString(toks, nchars, isstart, aind);
1396 then
1397 (nchars, isstart, aind);
1398
1399
1400 //separator only ...
1401 case (BT_ITER(options = ITER_OPTIONS(
1402 separator = SOME(septok),
1403 alignNum = 0,
1404 wrapWidth = 0)), tok :: toks, nchars, isstart, aind)
1405 algorithm
1406 // put the first token, all the others with separator
1407 2367145 (nchars, isstart, aind) := tokString(tok, nchars, isstart, aind);
1408 2367145 (nchars, isstart)
1409 := iterSeparatorString(toks, septok, nchars, isstart, aind);
1410 2367145 then
1411 (nchars, isstart, aind);
1412
1413 //separator and alignment and/or wrapping
1414 case (BT_ITER(options = ITER_OPTIONS(
1415 separator = SOME(septok),
1416 alignNum = anum,
1417 alignOfset = aoffset,
1418 alignSeparator = asep,
1419 wrapWidth = wwidth,
1420 wrapSeparator = wsep)), tok :: toks, nchars, isstart, aind)
1421 algorithm
1422 // put the first token, all the others with separator
1423 ✗ (nchars, isstart, aind) := tokString(tok, nchars, isstart, aind);
1424 ✗ (nchars, isstart)
1425 := iterSeparatorAlignWrapString(toks, septok, 1 + aoffset, anum, asep, wwidth, wsep, nchars, isstart, aind);
1426 ✗ then
1427 (nchars, isstart, aind);
1428
1429 //no separator and alignment and/or wrapping
1430 case (BT_ITER(options = ITER_OPTIONS(
1431 separator = NONE(),
1432 alignNum = anum,
1433 alignOfset = aoffset,
1434 alignSeparator = asep,
1435 wrapWidth = wwidth,
1436 wrapSeparator = wsep)), toks, nchars, isstart, aind)
1437 algorithm
1438 ✗ (nchars, isstart)
1439 := iterAlignWrapString(toks, aoffset, anum, asep, wwidth, wsep, nchars, isstart, aind);
1440 ✗ then
1441 (nchars, isstart, aind);
1442
1443
1444 //should not ever happen
1445 else
1446 algorithm
1447 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.tokString failed.\n");
1448 ✗ then
1449 fail();
1450 end match;
1451 end blockString;
1452
1453
1454 protected function iterSeparatorString
1455 input Tokens inTokens;
1456 input StringToken inSeparator;
1457 input Integer inActualPositionOnLine;
1458 input Boolean inAtStartOfLine;
1459 input Integer inAfterNewLineIndent;
1460
1461 output Integer outActualPositionOnLine = inActualPositionOnLine;
1462 output Boolean outAtStartOfLine = inAtStartOfLine;
1463 protected
1464 Integer aind = inAfterNewLineIndent;
1465 algorithm
1466
2/2
✓ Branch 0 taken 1440128 times.
✓ Branch 1 taken 2367145 times.
3807273 for tok in inTokens loop
1467 1440128 (outActualPositionOnLine, outAtStartOfLine, aind) := tokString(inSeparator, outActualPositionOnLine, outAtStartOfLine, aind);
1468 1440128 (outActualPositionOnLine, outAtStartOfLine, aind) := tokString(tok, outActualPositionOnLine, outAtStartOfLine, aind);
1469 end for;
1470 end iterSeparatorString;
1471
1472
1473 protected function iterSeparatorAlignWrapString
1474 input Tokens inTokens;
1475 input StringToken inSeparator;
1476 input Integer inActualIndex;
1477 input Integer inAlignNum;
1478 input StringToken inAlignSeparator;
1479 input Integer inWrapWidth;
1480 input StringToken inWrapSeparator;
1481 input Integer inActualPositionOnLine;
1482 input Boolean inAtStartOfLine;
1483 input Integer inAfterNewLineIndent;
1484
1485 output Integer outActualPositionOnLine;
1486 output Boolean outAtStartOfLine;
1487 protected
1488 Tokens toks = inTokens;
1489 StringToken tok;
1490 StringToken septok = inSeparator;
1491 Integer idx = inActualIndex;
1492 Integer anum = inAlignNum;
1493 StringToken asep = inAlignSeparator;
1494 Integer wwidth = inWrapWidth;
1495 StringToken wsep = inWrapSeparator;
1496 Integer pos = inActualPositionOnLine;
1497 Boolean isstart = inAtStartOfLine;
1498 Integer aind = inAfterNewLineIndent;
1499 algorithm
1500 ✗ while (boolNot(listEmpty(toks))) loop
1501 ✗ tok::toks := toks;
1502 ✗ if((idx > 0) and (intMod(idx,anum) == 0)) then
1503 ✗ (pos, isstart, aind) := tokString(asep, pos, isstart, aind);
1504 else
1505 ✗ (pos, isstart, aind) := tokString(septok, pos, isstart, aind);
1506 end if;
1507 ✗ (pos, isstart, aind) := tryWrapString(wwidth, wsep, pos, isstart, aind);
1508 ✗ (pos, isstart, aind) := tokString(tok, pos, isstart, aind);
1509 ✗ idx := idx + 1;
1510 end while;
1511 ✗ (outActualPositionOnLine, outAtStartOfLine) := (pos, isstart);
1512 end iterSeparatorAlignWrapString;
1513
1514
1515 protected function iterAlignWrapString
1516 input Tokens inTokens;
1517 input Integer inActualIndex;
1518 input Integer inAlignNum;
1519 input StringToken inAlignSeparator;
1520 input Integer inWrapWidth;
1521 input StringToken inWrapSeparator;
1522 input Integer inActualPositionOnLine;
1523 input Boolean inAtStartOfLine;
1524 input Integer inAfterNewLineIndent;
1525
1526 output Integer outActualPositionOnLine;
1527 output Boolean outAtStartOfLine;
1528 protected
1529 Tokens toks = inTokens;
1530 StringToken tok;
1531 Integer idx = inActualIndex;
1532 Integer pos = inActualPositionOnLine;
1533 Boolean isstart = inAtStartOfLine;
1534 Integer aind = inAfterNewLineIndent;
1535 algorithm
1536 ✗ while not listEmpty(toks) loop
1537 ✗ tok::toks := toks;
1538 ✗ if (idx > 0) and (intMod(idx,inAlignNum) == 0) then
1539 //align and try wrap
1540 ✗ (pos, isstart, aind) := tokString(inAlignSeparator, pos, isstart, aind);
1541 ✗ (pos, isstart, aind) := tryWrapString(inWrapWidth, inWrapSeparator, pos, isstart, aind);
1542 elseif (inWrapWidth > 0) and (pos >= inWrapWidth) then //check wwidth for the invariant that should be always true here
1543 //wrap
1544 ✗ (pos, isstart, aind) := tokString(inWrapSeparator, pos, isstart, aind);
1545 end if;
1546 ✗ (pos, isstart, aind) := tokString(tok, pos, isstart, aind);
1547 ✗ idx := idx + 1;
1548 end while;
1549 ✗ (outActualPositionOnLine, outAtStartOfLine) := (pos, isstart);
1550 end iterAlignWrapString;
1551
1552
1553 protected function tryWrapString
1554 input Integer inWrapWidth;
1555 input StringToken inWrapSeparator;
1556 input Integer inActualPositionOnLine;
1557 input Boolean inAtStartOfLine;
1558 input Integer inAfterNewLineIndent;
1559
1560 output Integer outActualPositionOnLine;
1561 output Boolean outAtStartOfLine;
1562 output Integer outAfterNewLineIndent;
1563 algorithm
1564 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1565 := match (inWrapWidth, inWrapSeparator, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1566 local
1567 Integer pos, aind, wwidth;
1568 Boolean isstart;
1569 StringToken wsep;
1570
1571 //wrap
1572 case (wwidth, wsep, pos, isstart, aind)
1573 guard
1574 (wwidth > 0) and (pos >= wwidth) //check wwidth for the invariant that should be always true here
1575 ✗ then
1576 tokString(wsep, pos, isstart, aind);
1577
1578 ✗ else (inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent);
1579 end match;
1580 end tryWrapString;
1581
1582
1583 protected function blockFile
1584 input File.File file;
1585 input BlockType inBlockType;
1586 input Tokens inTokens;
1587 input Integer inActualPositionOnLine;
1588 input Boolean inAtStartOfLine;
1589 input Integer inAfterNewLineIndent;
1590
1591 output Integer outActualPositionOnLine;
1592 output Boolean outAtStartOfLine;
1593 output Integer outAfterNewLineIndent;
1594 algorithm
1595 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1596 := match (inBlockType, inTokens, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1597 local
1598 Tokens toks;
1599 StringToken septok, tok, asep, wsep;
1600 Integer nchars, tsnchars, aind, w, aoffset, anum, wwidth, blen;
1601 Boolean isstart;
1602
1603 case (BT_TEXT(), toks, nchars, isstart, aind)
1604 algorithm
1605 9263867 (nchars, isstart, aind)
1606 := tokensFile(file, toks, nchars, isstart, aind);
1607 then
1608 (nchars, isstart, aind);
1609
1610 case (BT_INDENT(width = w), toks, nchars, true, aind)
1611 algorithm
1612 289262 (tsnchars, isstart)
1613 := tokensFile(file, toks, w + nchars, true, w + aind);
1614
2/2
✓ Branch 0 taken 3391 times.
✓ Branch 1 taken 285871 times.
289262 nchars := if isstart then nchars else tsnchars; //pop indent when at the start of a line
1615 289262 then
1616 (nchars, isstart, aind);
1617
1618 case (BT_INDENT(width = w), toks, nchars, false, aind)
1619 algorithm
1620 97483 File.writeSpace(file, w);
1621 97483 (tsnchars, isstart)
1622 := tokensFile(file, toks, w + nchars, false, w + aind);
1623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97483 times.
97483 nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1624 97483 then
1625 (nchars, isstart, aind);
1626
1627 case (BT_ABS_INDENT(width = w), toks, nchars, true, aind)
1628 algorithm
1629 ✗ blen := File.tell(file);
1630 ✗ (tsnchars, isstart)
1631 := tokensFile(file, toks, 0, true, w); //discard an indent when at the start of a line
1632 ✗ blen := File.tell(file) - blen;
1633 ✗ nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1634 ✗ then
1635 (nchars, isstart, aind);
1636
1637 case (BT_ABS_INDENT(width = w), toks, nchars, false, aind)
1638 algorithm
1639 ✗ (tsnchars, isstart)
1640 := tokensFile(file, toks, nchars, false, w);
1641 ✗ nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1642 ✗ then
1643 (nchars, isstart, aind);
1644
1645 case (BT_REL_INDENT(offset = w), toks, nchars, true, aind)
1646 algorithm
1647 ✗ blen := File.tell(file);
1648 ✗ (tsnchars, isstart)
1649 := tokensFile(file, toks, nchars, true, aind + w);
1650 ✗ blen := File.tell(file) - blen;
1651 ✗ nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1652 ✗ then
1653 (nchars, isstart, aind);
1654
1655 case (BT_REL_INDENT(offset = w), toks, nchars, false, aind)
1656 algorithm
1657 ✗ (tsnchars, isstart)
1658 := tokensFile(file, toks, nchars, false, aind + w);
1659 ✗ nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1660 ✗ then
1661 (nchars, isstart, aind);
1662
1663 case (BT_ANCHOR(offset = w), toks, nchars, true, aind)
1664 algorithm
1665 ✗ blen := File.tell(file);
1666 ✗ (tsnchars, isstart)
1667 := tokensFile(file, toks, nchars, true, nchars + w);
1668 ✗ blen := File.tell(file) - blen;
1669 ✗ nchars := if blen == 0 then nchars else (if isstart then aind else tsnchars); //when no chars -> pop indent; when something written -> aind for the start of a line otherwise actual position
1670 ✗ then
1671 (nchars, isstart, aind);
1672
1673 case (BT_ANCHOR(offset = w), toks, nchars, false, aind)
1674 algorithm
1675 ✗ (tsnchars, isstart)
1676 := tokensFile(file, toks, nchars, false, nchars + w);
1677 ✗ nchars := if isstart then aind else tsnchars; //pop indent when at the start of a line - there were a new line, so use the aind
1678 ✗ then
1679 (nchars, isstart, aind);
1680
1681
1682 //iter block, no tokens ... should be impossible, but ...
1683 case (BT_ITER(), {}, nchars, isstart, aind)
1684 ✗ then
1685 (nchars, isstart, aind);
1686
1687 //concat ... i.e. text
1688 case (BT_ITER(options = ITER_OPTIONS(
1689 separator = NONE(),
1690 alignNum = 0,
1691 wrapWidth = 0)), toks, nchars, isstart, aind)
1692 algorithm
1693 4898 (nchars, isstart, aind)
1694 := tokensFile(file,toks, nchars, isstart, aind);
1695 then
1696 (nchars, isstart, aind);
1697
1698
1699 //separator only ...
1700 case (BT_ITER(options = ITER_OPTIONS(
1701 separator = SOME(septok),
1702 alignNum = 0,
1703 wrapWidth = 0)), tok :: toks, nchars, isstart, aind)
1704 algorithm
1705 // put the first token, all the others with separator
1706 241862 (nchars, isstart, aind) := tokFile(file, tok, nchars, isstart, aind);
1707 241862 (nchars, isstart)
1708 := iterSeparatorFile(file, toks, septok, nchars, isstart, aind);
1709 241862 then
1710 (nchars, isstart, aind);
1711
1712 //separator and alignment and/or wrapping
1713 case (BT_ITER(options = ITER_OPTIONS(
1714 separator = SOME(septok),
1715 alignNum = anum,
1716 alignOfset = aoffset,
1717 alignSeparator = asep,
1718 wrapWidth = wwidth,
1719 wrapSeparator = wsep)), tok :: toks, nchars, isstart, aind)
1720 algorithm
1721 // put the first token, all the others with separator
1722 ✗ (nchars, isstart, aind) := tokFile(file, tok, nchars, isstart, aind);
1723 ✗ (nchars, isstart)
1724 := iterSeparatorAlignWrapFile(file, toks, septok, 1 + aoffset, anum, asep, wwidth, wsep, nchars, isstart, aind);
1725 ✗ then
1726 (nchars, isstart, aind);
1727
1728 //no separator and alignment and/or wrapping
1729 case (BT_ITER(options = ITER_OPTIONS(
1730 separator = NONE(),
1731 alignNum = anum,
1732 alignOfset = aoffset,
1733 alignSeparator = asep,
1734 wrapWidth = wwidth,
1735 wrapSeparator = wsep)), toks, nchars, isstart, aind)
1736 algorithm
1737 ✗ (nchars, isstart)
1738 := iterAlignWrapFile(file, toks, aoffset, anum, asep, wwidth, wsep, nchars, isstart, aind);
1739 ✗ then
1740 (nchars, isstart, aind);
1741
1742
1743 //should not ever happen
1744 else
1745 algorithm
1746 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.tokString failed.\n");
1747 ✗ then
1748 fail();
1749 end match;
1750 end blockFile;
1751
1752 protected function iterSeparatorFile
1753 input File.File file;
1754 input Tokens inTokens;
1755 input StringToken inSeparator;
1756 input Integer inActualPositionOnLine;
1757 input Boolean inAtStartOfLine;
1758 input Integer inAfterNewLineIndent;
1759
1760 output Integer outActualPositionOnLine;
1761 output Boolean outAtStartOfLine;
1762 algorithm
1763 (outActualPositionOnLine, outAtStartOfLine) := match (inTokens, inSeparator, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1764 local
1765 Tokens toks;
1766 StringToken tok, septok;
1767 Integer pos, aind;
1768 Boolean isstart;
1769
1770 case ({}, _, pos, isstart, _)
1771 then
1772 (pos, isstart);
1773
1774 case (tok :: toks, septok, pos, isstart, aind)
1775 algorithm
1776 804359 (pos, isstart, aind) := tokFile(file, septok, pos, isstart, aind);
1777 804359 (pos, isstart, aind) := tokFile(file, tok, pos, isstart, aind);
1778 804359 (pos, isstart)
1779 := iterSeparatorFile(file, toks, septok, pos, isstart, aind);
1780 then
1781 (pos, isstart);
1782 end match;
1783 end iterSeparatorFile;
1784
1785
1786 protected function iterSeparatorAlignWrapFile
1787 input File.File file;
1788 input Tokens inTokens;
1789 input StringToken inSeparator;
1790 input Integer inActualIndex;
1791 input Integer inAlignNum;
1792 input StringToken inAlignSeparator;
1793 input Integer inWrapWidth;
1794 input StringToken inWrapSeparator;
1795 input Integer inActualPositionOnLine;
1796 input Boolean inAtStartOfLine;
1797 input Integer inAfterNewLineIndent;
1798
1799 output Integer outActualPositionOnLine;
1800 output Boolean outAtStartOfLine;
1801 protected
1802 Tokens toks = inTokens;
1803 StringToken tok;
1804 StringToken septok = inSeparator;
1805 Integer idx = inActualIndex;
1806 Integer anum = inAlignNum;
1807 StringToken asep = inAlignSeparator;
1808 Integer wwidth = inWrapWidth;
1809 StringToken wsep = inWrapSeparator;
1810 Integer pos = inActualPositionOnLine;
1811 Boolean isstart = inAtStartOfLine;
1812 Integer aind = inAfterNewLineIndent;
1813 algorithm
1814 ✗ while (boolNot(listEmpty(toks))) loop
1815 ✗ tok::toks := toks;
1816 ✗ if((idx > 0) and (intMod(idx,anum) == 0)) then
1817 ✗ (pos, isstart, aind) := tokFile(file, asep, pos, isstart, aind);
1818 else
1819 ✗ (pos, isstart, aind) := tokFile(file, septok, pos, isstart, aind);
1820 end if;
1821 ✗ (pos, isstart, aind) := tryWrapFile(file, wwidth, wsep, pos, isstart, aind);
1822 ✗ (pos, isstart, aind) := tokFile(file, tok, pos, isstart, aind);
1823 ✗ idx := idx + 1;
1824 end while;
1825 ✗ (outActualPositionOnLine, outAtStartOfLine) := (pos, isstart);
1826 end iterSeparatorAlignWrapFile;
1827
1828
1829 protected function iterAlignWrapFile
1830 input File.File file;
1831 input Tokens inTokens;
1832 input Integer inActualIndex;
1833 input Integer inAlignNum;
1834 input StringToken inAlignSeparator;
1835 input Integer inWrapWidth;
1836 input StringToken inWrapSeparator;
1837 input Integer inActualPositionOnLine;
1838 input Boolean inAtStartOfLine;
1839 input Integer inAfterNewLineIndent;
1840
1841 output Integer outActualPositionOnLine;
1842 output Boolean outAtStartOfLine;
1843 algorithm
1844 (outActualPositionOnLine, outAtStartOfLine)
1845 := match (inTokens, inActualIndex, inAlignNum, inAlignSeparator, inWrapWidth, inWrapSeparator, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1846 local
1847 Tokens toks;
1848 StringToken tok, asep, wsep;
1849 Integer pos, aind, idx, anum, wwidth;
1850 Boolean isstart;
1851
1852 case ({}, _,_,_,_,_, pos, isstart, _)
1853 then
1854 (pos, isstart);
1855
1856 //align and try wrap
1857 case (tok :: toks, idx, anum, asep, wwidth, wsep, pos, isstart, aind)
1858 guard
1859 (idx > 0) and (intMod(idx,anum) == 0)
1860 algorithm
1861 ✗ (pos, isstart, aind) := tokFile(file, asep, pos, isstart, aind);
1862 ✗ (pos, isstart, aind) := tryWrapFile(file, wwidth, wsep, pos, isstart, aind);
1863 ✗ (pos, isstart, aind) := tokFile(file, tok, pos, isstart, aind);
1864 ✗ (pos, isstart)
1865 := iterAlignWrapFile(file, toks, idx + 1, anum, asep, wwidth, wsep,
1866 pos, isstart, aind);
1867 then
1868 (pos, isstart);
1869 //wrap
1870 case (tok :: toks, idx, anum, asep, wwidth, wsep, pos, isstart, aind)
1871 guard
1872 //false = (idx > 0) and (intMod(idx,anum) == 0);
1873 (wwidth > 0) and (pos >= wwidth) //check wwidth for the invariant that should be always true here
1874 algorithm
1875 ✗ (pos, isstart, aind) := tokFile(file, wsep, pos, isstart, aind);
1876 ✗ (pos, isstart, aind) := tokFile(file, tok, pos, isstart, aind);
1877 ✗ (pos, isstart)
1878 := iterAlignWrapFile(file, toks, idx + 1, anum, asep, wwidth, wsep,
1879 pos, isstart, aind);
1880 then
1881 (pos, isstart);
1882
1883 //item only
1884 case (tok :: toks, idx, anum, asep, wwidth, wsep, pos, isstart, aind)
1885 algorithm
1886 //false = (idx > 0) and (intMod(idx,anum) == 0);
1887 //false = (wwidth > 0) and (pos >= wwidth); //check wwidth for the invariant that should be always true here
1888 ✗ (pos, isstart, aind) := tokFile(file, tok, pos, isstart, aind);
1889 ✗ (pos, isstart)
1890 := iterAlignWrapFile(file, toks, idx + 1, anum, asep, wwidth, wsep,
1891 pos, isstart, aind);
1892 then
1893 (pos, isstart);
1894
1895 //should not ever happen
1896 else
1897 algorithm
1898 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.iterAlignWrapString failed.\n");
1899 ✗ then
1900 fail();
1901 end match;
1902 end iterAlignWrapFile;
1903
1904
1905 protected function tryWrapFile
1906 input File.File file;
1907 input Integer inWrapWidth;
1908 input StringToken inWrapSeparator;
1909 input Integer inActualPositionOnLine;
1910 input Boolean inAtStartOfLine;
1911 input Integer inAfterNewLineIndent;
1912
1913 output Integer outActualPositionOnLine;
1914 output Boolean outAtStartOfLine;
1915 output Integer outAfterNewLineIndent;
1916 algorithm
1917 (outActualPositionOnLine, outAtStartOfLine, outAfterNewLineIndent)
1918 := match (inWrapWidth, inWrapSeparator, inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent)
1919 local
1920 Integer pos, aind, wwidth;
1921 Boolean isstart;
1922 StringToken wsep;
1923
1924 //wrap
1925 case (wwidth, wsep, pos, isstart, aind)
1926 guard
1927 (wwidth > 0) and (pos >= wwidth) //check wwidth for the invariant that should be always true here
1928 ✗ then
1929 tokFile(file, wsep, pos, isstart, aind);
1930
1931 ✗ else (inActualPositionOnLine, inAtStartOfLine, inAfterNewLineIndent);
1932 end match;
1933 end tryWrapFile;
1934
1935
1936 public function strTokText
1937 input StringToken inStringToken;
1938 output Text outText;
1939 algorithm
1940 105186 outText := MEM_TEXT({inStringToken},{});
1941 end strTokText;
1942
1943
1944 public function isEmpty
1945 input Text txt;
1946 output Boolean b;
1947 algorithm
1948 b := match txt
1949 case MEM_TEXT(tokens = {}) then true;
1950 else false;
1951 end match;
1952 end isEmpty;
1953
1954 public function textStrTok
1955 input Text inText;
1956 output StringToken outStringToken;
1957 algorithm
1958 outStringToken := match inText
1959 local
1960 Tokens txttoks;
1961
1962 case MEM_TEXT( tokens = {} )
1963 then
1964 ST_STRING("");
1965
1966 case MEM_TEXT(
1967 tokens = txttoks,
1968 blocksStack = {}
1969 )
1970 ✗ then
1971 ST_BLOCK(txttoks, BT_TEXT());
1972
1973 //should not ever happen
1974 //- when compilation is correct, this is impossible (only completed texts can be accessible to write out)
1975 else
1976 algorithm
1977 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.textStrTok failed - incomplete text was passed to be converted.\n");
1978 ✗ then
1979 fail();
1980 end match;
1981 end textStrTok;
1982
1983
1984 public function stringText
1985 input String inString;
1986 output Text outText;
1987 algorithm
1988 24328 outText := MEM_TEXT({ST_STRING(inString)},{});
1989 end stringText;
1990
1991
1992 public function strTokString
1993 input StringToken inStringToken;
1994 output String outString;
1995 algorithm
1996 ✗ outString := textString( MEM_TEXT({inStringToken},{}) );
1997 end strTokString;
1998
1999 public function failIfTrue
2000 input Boolean istrue;
2001 algorithm
2002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1374197 times.
1374197 if istrue then
2003 ✗ fail();
2004 end if;
2005 end failIfTrue;
2006
2007 protected function tplCallHandleErrors
2008 input Tpl_Fun inFun;
2009 input output Text txt = emptyTxt;
2010
2011 partial function Tpl_Fun
2012 input Text in_txt;
2013 output Text out_txt;
2014 end Tpl_Fun;
2015 protected
2016 Integer nErr;
2017 algorithm
2018 1377691 nErr := Error.getNumErrorMessages();
2019 try
2020 try
2021
1/2
✓ Branch 0 taken 1377691 times.
✗ Branch 1 not taken.
1377691 txt := inFun(txt);
2022 else
2023 ✗ addTemplateErrorFunc(inFun);
2024 ✗ fail();
2025 end try;
2026 else
2027 ✗ if StackOverflow.hasStacktraceMessages() then
2028 ✗ Error.addInternalError(StackOverflow.errorPrefix() + " when evaluating function:\n"+ stringDelimitList(StackOverflow.readableStacktraceMessages(), "\n"), sourceInfo());
2029 end if;
2030 ✗ addTemplateErrorFunc(inFun);
2031 ✗ fail();
2032 end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
2033 end tplCallHandleErrors;
2034
2035 public function tplCallWithFailErrorNoArg
2036 input Tpl_Fun inFun;
2037 input output Text txt = emptyTxt;
2038
2039 partial function Tpl_Fun
2040 input Text in_txt;
2041 output Text out_txt;
2042 end Tpl_Fun;
2043 algorithm
2044 28050 txt := tplCallHandleErrors(inFun, txt);
2045 end tplCallWithFailErrorNoArg;
2046
2047 public function tplCallWithFailError
2048 input Tpl_Fun inFun;
2049 input ArgType1 inArg;
2050 input output Text txt = emptyTxt;
2051
2052 partial function Tpl_Fun
2053 input Text in_txt;
2054 input ArgType1 inArgA;
2055 output Text out_txt;
2056 end Tpl_Fun;
2057 algorithm
2058 35143 txt := tplCallHandleErrors(function inFun(inArgA=inArg), txt);
2059 end tplCallWithFailError;
2060
2061 public function tplCallWithFailError2
2062 input Tpl_Fun inFun;
2063 input ArgType1 inArgA;
2064 input ArgType2 inArgB;
2065 input output Text txt = emptyTxt;
2066
2067 partial function Tpl_Fun
2068 input Text in_txt;
2069 input ArgType1 inArgA;
2070 input ArgType2 inArgB;
2071 output Text out_txt;
2072 end Tpl_Fun;
2073 protected
2074 algorithm
2075 1313307 txt := tplCallHandleErrors(function inFun(inArgA=inArgA, inArgB=inArgB), txt);
2076 end tplCallWithFailError2;
2077
2078 function tplCallWithFailError3
2079 input Tpl_Fun inFun;
2080 input ArgType1 inArgA;
2081 input ArgType2 inArgB;
2082 input ArgType3 inArgC;
2083 input output Text txt = emptyTxt;
2084
2085 partial function Tpl_Fun
2086 input Text in_txt;
2087 input ArgType1 inArgA;
2088 input ArgType2 inArgB;
2089 input ArgType3 inArgC;
2090 output Text out_txt;
2091 end Tpl_Fun;
2092 algorithm
2093 1191 txt := tplCallHandleErrors(function inFun(inArgA=inArgA, inArgB=inArgB, inArgC=inArgC), txt);
2094 end tplCallWithFailError3;
2095
2096 public function tplString
2097 input Tpl_Fun inFun;
2098 input ArgType1 inArg;
2099 output String outString;
2100
2101 partial function Tpl_Fun
2102 input Text in_txt;
2103 input ArgType1 inArgA;
2104 output Text out_txt;
2105 end Tpl_Fun;
2106 protected
2107 Text txt;
2108 Integer nErr;
2109 algorithm
2110 34926 nErr := Error.getNumErrorMessages();
2111 34926 txt := tplCallWithFailError(inFun, inArg);
2112 34926 failIfTrue(Error.getNumErrorMessages() > nErr);
2113 34926 outString := textString(txt);
2114 end tplString;
2115
2116 public function tplString2
2117 input Tpl_Fun inFun;
2118 input ArgType1 inArgA;
2119 input ArgType2 inArgB;
2120 output String outString;
2121
2122 partial function Tpl_Fun
2123 input Text in_txt;
2124 input ArgType1 inArgA;
2125 input ArgType2 inArgB;
2126 output Text out_txt;
2127 end Tpl_Fun;
2128 protected
2129 Text txt;
2130 Integer nErr;
2131 algorithm
2132 1313189 nErr := Error.getNumErrorMessages();
2133 1313189 txt := tplCallWithFailError2(inFun, inArgA, inArgB);
2134 1313189 failIfTrue(Error.getNumErrorMessages() > nErr);
2135 1313189 outString := textString(txt);
2136 end tplString2;
2137
2138 public function tplString3
2139 input Tpl_Fun inFun;
2140 input ArgType1 inArgA;
2141 input ArgType2 inArgB;
2142 input ArgType3 inArgC;
2143 output String outString;
2144
2145 partial function Tpl_Fun
2146 input Text in_txt;
2147 input ArgType1 inArgA;
2148 input ArgType2 inArgB;
2149 input ArgType3 inArgC;
2150 output Text out_txt;
2151 end Tpl_Fun;
2152 protected
2153 Text txt;
2154 Integer nErr;
2155 algorithm
2156 69 nErr := Error.getNumErrorMessages();
2157 69 txt := tplCallWithFailError3(inFun, inArgA, inArgB, inArgC);
2158 69 failIfTrue(Error.getNumErrorMessages() > nErr);
2159 69 outString := textString(txt);
2160 end tplString3;
2161
2162 public function tplPrint
2163 input Tpl_Fun inFun;
2164 input ArgType1 inArg;
2165
2166 partial function Tpl_Fun
2167 input Text in_txt;
2168 input ArgType1 inArgA;
2169 output Text out_txt;
2170 end Tpl_Fun;
2171 protected
2172 Text txt;
2173 Integer nErr;
2174 algorithm
2175 ✗ nErr := Error.getNumErrorMessages();
2176 ✗ txt := tplCallWithFailError(inFun, inArg);
2177 ✗ failIfTrue(Error.getNumErrorMessages() > nErr);
2178 ✗ textStringBuf(txt);
2179 end tplPrint;
2180
2181 public function tplPrint2
2182 input Tpl_Fun inFun;
2183 input ArgType1 inArgA;
2184 input ArgType2 inArgB;
2185
2186 partial function Tpl_Fun
2187 input Text in_txt;
2188 input ArgType1 inArgA;
2189 input ArgType2 inArgB;
2190 output Text out_txt;
2191 end Tpl_Fun;
2192 protected
2193 Text txt;
2194 Integer nErr;
2195 algorithm
2196 58 nErr := Error.getNumErrorMessages();
2197 58 txt := tplCallWithFailError2(inFun, inArgA, inArgB);
2198 58 failIfTrue(Error.getNumErrorMessages() > nErr);
2199 58 textStringBuf(txt);
2200 end tplPrint2;
2201
2202 public function tplPrint3
2203 input Tpl_Fun inFun;
2204 input ArgType1 inArgA;
2205 input ArgType2 inArgB;
2206 input ArgType3 inArgC;
2207
2208 partial function Tpl_Fun
2209 input Text in_txt;
2210 input ArgType1 inArgA;
2211 input ArgType2 inArgB;
2212 input ArgType3 inArgC;
2213 output Text out_txt;
2214 end Tpl_Fun;
2215 protected
2216 Text txt;
2217 Integer nErr;
2218 algorithm
2219 ✗ nErr := Error.getNumErrorMessages();
2220 ✗ txt := tplCallWithFailError3(inFun, inArgA, inArgB, inArgC);
2221 ✗ failIfTrue(Error.getNumErrorMessages() > nErr);
2222 ✗ textStringBuf(txt);
2223 end tplPrint3;
2224
2225 public function tplNoret3
2226 input Tpl_Fun inFun;
2227 input ArgType1 inArg;
2228 input ArgType2 inArg2;
2229 input ArgType3 inArg3;
2230
2231 partial function Tpl_Fun
2232 input Text in_txt;
2233 input ArgType1 inArgA;
2234 input ArgType2 inArgB;
2235 input ArgType3 inArgC;
2236 output Text out_txt;
2237 end Tpl_Fun;
2238 protected
2239 Integer nErr;
2240 algorithm
2241 ✗ nErr := Error.getNumErrorMessages();
2242 ✗ tplCallWithFailError3(inFun, inArg, inArg2, inArg3);
2243 ✗ failIfTrue(Error.getNumErrorMessages() > nErr);
2244 end tplNoret3;
2245
2246 public function tplNoret2
2247 input Tpl_Fun inFun;
2248 input ArgType1 inArg;
2249 input ArgType2 inArg2;
2250
2251 partial function Tpl_Fun
2252 input Text in_txt;
2253 input ArgType1 inArgA;
2254 input ArgType2 inArgB;
2255 output Text out_txt;
2256 end Tpl_Fun;
2257 protected
2258 Integer nErr;
2259 algorithm
2260 60 nErr := Error.getNumErrorMessages();
2261 60 tplCallWithFailError2(inFun, inArg, inArg2);
2262 60 failIfTrue(Error.getNumErrorMessages() > nErr);
2263 end tplNoret2;
2264
2265 public function tplNoret
2266 input Tpl_Fun inFun;
2267 input ArgType1 inArg;
2268
2269 partial function Tpl_Fun
2270 input Text in_txt;
2271 input ArgType1 inArgA;
2272 output Text out_txt;
2273 end Tpl_Fun;
2274 protected
2275 Integer nErr;
2276 algorithm
2277 135 nErr := Error.getNumErrorMessages();
2278 135 tplCallWithFailError(inFun, inArg);
2279 135 failIfTrue(Error.getNumErrorMessages() > nErr);
2280 end tplNoret;
2281
2282
2283 public function textFile "function: textFile:
2284 This function renders a (memory-)text to a file."
2285 input Text inText;
2286 input String inFileName;
2287
2288 algorithm
2289 () := matchcontinue (inText, inFileName)
2290 local
2291 Text txt;
2292 String file;
2293 Real rtTickTxt, rtTickW;
2294 case (txt, file)
2295 algorithm
2296 5606 rtTickTxt := System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL);
2297 5606 Print.clearBuf();
2298 5606 textStringBuf(txt);
2299 5606 rtTickW := System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL);
2300 5606 Print.writeBuf(file);
2301
2/2
✓ Branch 1 taken 5574 times.
✓ Branch 2 taken 32 times.
5606 if Testsuite.isRunning() then
2302 5574 System.appendFile(Testsuite.getTempFilesFile(), file + "\n");
2303 end if;
2304 5606 Print.clearBuf();
2305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5606 times.
5606 if Flags.isSet(Flags.TPL_PERF_TIMES) then
2306 ✗ Debug.trace("textFile " + file
2307 + "\n text:" + realString(realSub(rtTickW,rtTickTxt))
2308 + "\n write:" + realString(realSub(System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL), rtTickW))
2309 );
2310 end if;
2311 then
2312 ();
2313
2314 //TODO: let this function fail and the error message can be reported via # ( textFile(txt,"file.cpp") ; failMsg="error" )
2315 else
2316 algorithm
2317 ✗ if Flags.isSet(Flags.FAILTRACE) then
2318 ✗ Debug.trace("-!!!Tpl.textFile failed - a system error ?\n");
2319 end if;
2320 then
2321 ();
2322
2323 end matchcontinue;
2324 end textFile;
2325
2326 public function textFileConvertLines "This function renders a (memory-)text to a file. If we generate modelicaLine directives, translate them to C preprocessor."
2327 input Text inText;
2328 input String inFileName;
2329
2330 algorithm
2331 () := matchcontinue (inText, inFileName)
2332 local
2333 Text txt;
2334 String file;
2335 Real rtTickTxt, rtTickW;
2336 case (txt, file)
2337 algorithm
2338 2868 rtTickTxt := System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL);
2339 2868 Print.clearBuf();
2340 2868 textStringBuf(txt);
2341 2868 rtTickW := System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL);
2342 2868 System.writeFile(file, "") /* To make realpath work */;
2343
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 2820 times.
2868 if /*Config.acceptMetaModelicaGrammar() or*/ Flags.isSet(Flags.GEN_DEBUG_SYMBOLS) then
2344 48 Print.writeBufConvertLines(System.realpath(file));
2345 else
2346 2820 Print.writeBuf(file);
2347 end if;
2348
2/2
✓ Branch 1 taken 2830 times.
✓ Branch 2 taken 38 times.
2868 if Testsuite.isRunning() then
2349 2830 System.appendFile(Testsuite.getTempFilesFile(), file + "\n");
2350 end if;
2351 2868 Print.clearBuf();
2352
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2868 times.
2868 if Flags.isSet(Flags.TPL_PERF_TIMES) then
2353 ✗ Debug.traceln("textFile " + file
2354 + "\n text:" + realString(realSub(rtTickW,rtTickTxt))
2355 + "\n write:" + realString(realSub(System.realtimeTock(ClockIndexes.RT_CLOCK_BUILD_MODEL), rtTickW))
2356 );
2357 end if;
2358 then
2359 ();
2360
2361 //TODO: let this function fail and the error message can be reported via # ( textFile(txt,"file.cpp") ; failMsg="error" )
2362 else
2363 algorithm
2364 ✗ true := Flags.isSet(Flags.FAILTRACE); Debug.trace("-!!!Tpl.textFile failed - a system error ?\n");
2365 then
2366 ();
2367
2368 end matchcontinue;
2369 end textFileConvertLines;
2370
2371 public function sourceInfo
2372 "Magic sourceInfo() function implementation"
2373 input String inFileName;
2374 input Integer inLineNum;
2375 input Integer inColumnNum;
2376
2377 output SourceInfo outSourceInfo;
2378 algorithm
2379 ✗ outSourceInfo := SOURCEINFO(inFileName, false, inLineNum, inColumnNum, inLineNum, inColumnNum, 0.0);
2380 end sourceInfo;
2381
2382
2383 //we do not import Error.addSourceMessage() directly
2384 //because of list creation in Susan is not possible (yet by design)
2385 public function addSourceTemplateError
2386 "Wraps call to Error.addSourceMessage() funtion with Error.TEMPLATE_ERROR and one MessageToken."
2387 input String inErrMsg;
2388 input SourceInfo inInfo;
2389 algorithm
2390 ✗ Error.addSourceMessage(Error.TEMPLATE_ERROR, {inErrMsg}, inInfo);
2391 end addSourceTemplateError;
2392
2393 //for completeness
2394 protected function addTemplateErrorFunc<T>
2395 "Wraps call to Error.addMessage() funtion with Error.TEMPLATE_ERROR and one MessageToken."
2396 input T func;
2397 algorithm
2398 ✗ Error.addMessage(Error.TEMPLATE_ERROR_FUNC, {System.dladdr(func)});
2399 end addTemplateErrorFunc;
2400
2401 public function addTemplateError
2402 "Wraps call to Error.addMessage() funtion with Error.TEMPLATE_ERROR and one MessageToken."
2403 input String msg;
2404 algorithm
2405 ✗ Error.addMessage(Error.TEMPLATE_ERROR, {msg});
2406 end addTemplateError;
2407
2408 public function redirectToFile
2409 "Magic sourceInfo() function implementation"
2410 input output Text text;
2411 input String fileName;
2412 protected
2413 File.File file = File.File();
2414 algorithm
2415
2/2
✓ Branch 1 taken 31785 times.
✓ Branch 2 taken 2 times.
31787 if Testsuite.isRunning() then
2416 31785 System.appendFile(Testsuite.getTempFilesFile(), fileName + "\n");
2417 end if;
2418 31787 File.open(file, fileName, File.Mode.Write);
2419 31787 text := writeText(FILE_TEXT(File.getReference(file), Mutable.create(0), Mutable.create(0), Mutable.create(true), Mutable.create({})), text);
2420 end redirectToFile;
2421
2422 public function closeFile
2423 "Magic sourceInfo() function implementation"
2424 input output Text text;
2425 protected
2426 File.File file = File.File(getTextOpaqueFile(text));
2427 algorithm
2428 31787 File.releaseReference(file);
2429 text := emptyTxt;
2430 end closeFile;
2431
2432 public function booleanString // TODO: Remove me
2433 input Boolean b;
2434 output String s;
2435 algorithm
2436 151297 s := String(b);
2437 end booleanString;
2438
2439 protected function getTextOpaqueFile
2440 input Text text;
2441 output Option<Integer> opaqueFile;
2442 algorithm
2443 opaqueFile := match text
2444 17364307 case FILE_TEXT() then text.opaqueFile;
2445 else
2446 algorithm
2447 ✗ Error.addInternalError("tokFile got non-file text input", sourceInfo());
2448 ✗ then fail();
2449 end match;
2450 end getTextOpaqueFile;
2451
2452 protected function stringFile "Like ST_STRING or ST_LINE"
2453 input Text inText;
2454 input String str;
2455 input Boolean line;
2456 input Boolean recurseSeparator=true;
2457 protected
2458 File.File file = File.File(getTextOpaqueFile(inText));
2459 Integer nchars;
2460 algorithm
2461 () := match inText
2462 case FILE_TEXT()
2463 algorithm
2464 3073479 handleTok(inText);
2465 3073479 nchars := Mutable.access(inText.nchars);
2466
2/2
✓ Branch 0 taken 2143984 times.
✓ Branch 1 taken 929495 times.
3073479 if not line then
2467
2/2
✓ Branch 1 taken 243641 times.
✓ Branch 2 taken 1900343 times.
2143984 if Mutable.access(inText.isstart) then
2468 243641 File.writeSpace(file, nchars);
2469 243641 File.write(file, str);
2470 243641 Mutable.update(inText.nchars, nchars+stringLength(str));
2471 243641 Mutable.update(inText.isstart, false);
2472 else
2473 1900343 File.write(file, str);
2474 1900343 Mutable.update(inText.nchars, nchars+stringLength(str));
2475 end if;
2476 else
2477
1/2
✓ Branch 1 taken 929495 times.
✗ Branch 2 not taken.
929495 if Mutable.access(inText.isstart) then
2478 929495 File.writeSpace(file, nchars);
2479 else
2480 ✗ Mutable.update(inText.isstart, true);
2481 end if;
2482 929495 File.write(file, str);
2483 929495 Mutable.update(inText.nchars, Mutable.access(inText.aind));
2484 end if;
2485 then ();
2486 end match;
2487 end stringFile;
2488
2489 protected function newlineFile "Like ST_NEWLINE"
2490 input Text inText;
2491 protected
2492 File.File file = File.File(getTextOpaqueFile(inText));
2493 Integer nchars;
2494 algorithm
2495 () := match inText
2496 case FILE_TEXT()
2497 algorithm
2498 596140 File.write(file, "\n");
2499 596140 Mutable.update(inText.nchars, Mutable.access(inText.aind));
2500 596140 Mutable.update(inText.isstart, true);
2501 then ();
2502 end match;
2503 end newlineFile;
2504
2505 protected function textFileTell
2506 input Text inText;
2507 output Integer tell;
2508 protected
2509 File.File file = File.File(getTextOpaqueFile(inText));
2510 algorithm
2511 743914 tell := File.tell(file);
2512 end textFileTell;
2513
2514 protected function handleTok "Handle a new token, for example separators"
2515 input Text txt;
2516 protected
2517 StringToken septok;
2518 Mutable<Option<StringToken>> aseptok;
2519 algorithm
2520 () := match txt
2521 case FILE_TEXT()
2522 algorithm
2523 () := match Mutable.access(txt.blocksStack)
2524 case BT_FILE_TEXT(bt=BT_ITER(), septok=aseptok)::_
2525 algorithm
2526 () := match Mutable.access(aseptok)
2527 case SOME(septok)
2528 algorithm
2529 405987 Mutable.update(aseptok,NONE());
2530 405987 tokFileText(txt, septok, doHandleTok=false);
2531 then ();
2532 else ();
2533 end match;
2534 then ();
2535 else ();
2536 end match;
2537 then ();
2538 end match;
2539 end handleTok;
2540
2541 public function debugSusan
2542 output Boolean b;
2543 algorithm
2544 ✗ b := Flags.isSet(Flags.SUSAN_MATCHCONTINUE_DEBUG);
2545 end debugSusan;
2546
2547 public function fakeStackOverflow
2548 algorithm
2549 ✗ Error.addInternalError("Stack overflow:\n" + StackOverflow.generateReadableMessage(), sourceInfo());
2550 ✗ StackOverflow.triggerStackOverflow();
2551 end fakeStackOverflow;
2552
2553 annotation(__OpenModelica_Interface="tpl");
2554 end Tpl;
2555