/[svn]/linuxsampler/trunk/src/scriptvm/tests/NKSPTest.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/scriptvm/tests/NKSPTest.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3580 by schoenebeck, Wed Aug 28 15:23:23 2019 UTC revision 3581 by schoenebeck, Fri Aug 30 11:40:25 2019 UTC
# Line 31  using namespace std; Line 31  using namespace std;
31  struct RunScriptOpt {  struct RunScriptOpt {
32      String code;      String code;
33      bool expectParseError;      bool expectParseError;
34        bool expectParseWarning;
35      bool expectRuntimeError;      bool expectRuntimeError;
36      bool expectNoExitResult;      bool expectNoExitResult;
37        bool expectExitResultIsInt;
38        bool expectExitResultIsReal;
39      bool prohibitExitFunctionArguments;      bool prohibitExitFunctionArguments;
40      optional<vmint> expectIntExitResult;      optional<vmint> expectIntExitResult;
41      optional<bool> expectBoolExitResult;      optional<bool> expectBoolExitResult;
42      optional<vmfloat> expectRealExitResult;      optional<vmfloat> expectRealExitResult;
43      optional<String> expectStringExitResult;      optional<String> expectStringExitResult;
44        vector<MetricPrefix_t> expectExitResultUnitPrefix;
45        optional<StdUnit_t> expectExitResultUnit;
46        optional<bool> expectExitResultFinal;
47  };  };
48    
49  static void runScript(const RunScriptOpt& opt) {  static void runScript(const RunScriptOpt& opt) {
# Line 49  static void runScript(const RunScriptOpt Line 55  static void runScript(const RunScriptOpt
55          vm.loadScript(opt.code)          vm.loadScript(opt.code)
56      );      );
57      vector<ParserIssue> errors = parserCtx->errors();      vector<ParserIssue> errors = parserCtx->errors();
58        vector<ParserIssue> warnings = parserCtx->warnings();
59      if (opt.expectParseError) {      if (opt.expectParseError) {
60          TEST_ASSERT(!errors.empty());          TEST_ASSERT(!errors.empty());
61          return;          return;
# Line 58  static void runScript(const RunScriptOpt Line 65  static void runScript(const RunScriptOpt
65          }          }
66          TEST_ASSERT(errors.empty());          TEST_ASSERT(errors.empty());
67      }      }
68        if (opt.expectParseWarning) {
69            TEST_ASSERT(!warnings.empty());
70        } else {
71            for (ParserIssue& wrn : warnings) {
72                wrn.dump();
73            }
74        }
75      TEST_ASSERT(parserCtx->eventHandler(0));      TEST_ASSERT(parserCtx->eventHandler(0));
76      unique_ptr<VMExecContext> execCtx(      unique_ptr<VMExecContext> execCtx(
77          vm.createExecContext(&*parserCtx)          vm.createExecContext(&*parserCtx)
# Line 74  static void runScript(const RunScriptOpt Line 88  static void runScript(const RunScriptOpt
88              VMExpr* resExpr = execCtx->exitResult();              VMExpr* resExpr = execCtx->exitResult();
89              TEST_ASSERT(!resExpr);              TEST_ASSERT(!resExpr);
90          }          }
91            if (opt.expectExitResultIsInt) {
92                VMExpr* resExpr = execCtx->exitResult();
93                TEST_ASSERT(resExpr);
94                TEST_ASSERT(resExpr->exprType() == INT_EXPR);
95            }
96            if (opt.expectExitResultIsReal) {
97                VMExpr* resExpr = execCtx->exitResult();
98                TEST_ASSERT(resExpr);
99                TEST_ASSERT(resExpr->exprType() == REAL_EXPR);
100            }
101          if (opt.expectIntExitResult) {          if (opt.expectIntExitResult) {
102              VMExpr* resExpr = execCtx->exitResult();              VMExpr* resExpr = execCtx->exitResult();
103              TEST_ASSERT(resExpr);              TEST_ASSERT(resExpr);
# Line 102  static void runScript(const RunScriptOpt Line 126  static void runScript(const RunScriptOpt
126              TEST_ASSERT(resExpr->exprType() == STRING_EXPR);              TEST_ASSERT(resExpr->exprType() == STRING_EXPR);
127              TEST_ASSERT(resExpr->asString()->evalStr() == *opt.expectStringExitResult);              TEST_ASSERT(resExpr->asString()->evalStr() == *opt.expectStringExitResult);
128          }          }
129            if (opt.expectExitResultUnit) {
130                VMExpr* resExpr = execCtx->exitResult();
131                TEST_ASSERT(resExpr);
132                VMScalarNumberExpr* numberExpr = resExpr->asScalarNumberExpr();
133                TEST_ASSERT(numberExpr);
134                TEST_ASSERT(numberExpr->unitType() == *opt.expectExitResultUnit);
135            }
136            if (!opt.expectExitResultUnitPrefix.empty()) {
137                VMExpr* resExpr = execCtx->exitResult();
138                TEST_ASSERT(resExpr);
139                VMScalarNumberExpr* numberExpr = resExpr->asScalarNumberExpr();
140                TEST_ASSERT(numberExpr);
141                auto prefixes = opt.expectExitResultUnitPrefix;
142                if (*prefixes.rbegin() != VM_NO_PREFIX)
143                    prefixes.push_back(VM_NO_PREFIX); // VM_NO_PREFIX termination required by unitFactr() call
144                vmfloat expectedFactor = VMUnit::unitFactor(&prefixes[0]);
145                vmfloat actualFactor = numberExpr->unitFactor();
146                if (sizeof(vmfloat) == sizeof(float)) {
147                    TEST_ASSERT(RTMath::fEqual32(expectedFactor, actualFactor));
148                } else {
149                    TEST_ASSERT(RTMath::fEqual64(expectedFactor, actualFactor));
150                }
151            }
152            if (opt.expectExitResultFinal) {
153                VMExpr* resExpr = execCtx->exitResult();
154                TEST_ASSERT(resExpr);
155                VMScalarNumberExpr* numberExpr = resExpr->asScalarNumberExpr();
156                TEST_ASSERT(numberExpr);
157                TEST_ASSERT(numberExpr->isFinal() == *opt.expectExitResultFinal);
158            }
159      }      }
160  }  }
161    
# Line 231  end on Line 285  end on
285          .expectRealExitResult = 6.9          .expectRealExitResult = 6.9
286      });      });
287    
288        // std unit tests ...
289    
290        runScript({
291            .code = R"NKSP_CODE(
292    on init
293      exit(42s)
294    end on
295    )NKSP_CODE",
296            .expectIntExitResult = 42,
297            .expectExitResultUnit = VM_SECOND
298        });
299    
300        runScript({
301            .code = R"NKSP_CODE(
302    on init
303      exit(42Hz)
304    end on
305    )NKSP_CODE",
306            .expectIntExitResult = 42,
307            .expectExitResultUnit = VM_HERTZ
308        });
309    
310        runScript({
311            .code = R"NKSP_CODE(
312    on init
313      exit(42B)
314    end on
315    )NKSP_CODE",
316            .expectIntExitResult = 42,
317            .expectExitResultUnit = VM_BEL
318        });
319    
320        runScript({
321            .code = R"NKSP_CODE(
322    on init
323      exit(42us)
324    end on
325    )NKSP_CODE",
326            .expectIntExitResult = 42,
327            .expectExitResultUnitPrefix = { VM_MICRO },
328            .expectExitResultUnit = VM_SECOND
329        });
330    
331        runScript({
332            .code = R"NKSP_CODE(
333    on init
334      exit(42ms)
335    end on
336    )NKSP_CODE",
337            .expectIntExitResult = 42,
338            .expectExitResultUnitPrefix = { VM_MILLI },
339            .expectExitResultUnit = VM_SECOND
340        });
341    
342        runScript({
343            .code = R"NKSP_CODE(
344    on init
345      exit(42cs)
346    end on
347    )NKSP_CODE",
348            .expectIntExitResult = 42,
349            .expectExitResultUnitPrefix = { VM_CENTI },
350            .expectExitResultUnit = VM_SECOND
351        });
352    
353        runScript({
354            .code = R"NKSP_CODE(
355    on init
356      exit(42ds)
357    end on
358    )NKSP_CODE",
359            .expectIntExitResult = 42,
360            .expectExitResultUnitPrefix = { VM_DECI },
361            .expectExitResultUnit = VM_SECOND
362        });
363    
364        runScript({
365            .code = R"NKSP_CODE(
366    on init
367      exit(42das)
368    end on
369    )NKSP_CODE",
370            .expectIntExitResult = 42,
371            .expectExitResultUnitPrefix = { VM_DECA },
372            .expectExitResultUnit = VM_SECOND
373        });
374    
375        runScript({
376            .code = R"NKSP_CODE(
377    on init
378      exit(42hs)
379    end on
380    )NKSP_CODE",
381            .expectIntExitResult = 42,
382            .expectExitResultUnitPrefix = { VM_HECTO },
383            .expectExitResultUnit = VM_SECOND
384        });
385    
386        runScript({
387            .code = R"NKSP_CODE(
388    on init
389      exit(42ks)
390    end on
391    )NKSP_CODE",
392            .expectIntExitResult = 42,
393            .expectExitResultUnitPrefix = { VM_KILO },
394            .expectExitResultUnit = VM_SECOND
395        });
396    
397        runScript({
398            .code = R"NKSP_CODE(
399    on init
400      exit(42s)
401    end on
402    )NKSP_CODE",
403            .expectIntExitResult = 42,
404            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
405            .expectExitResultUnit = VM_SECOND
406        });
407    
408        runScript({
409            .code = R"NKSP_CODE(
410    on init
411      exit(42uHz)
412    end on
413    )NKSP_CODE",
414            .expectIntExitResult = 42,
415            .expectExitResultUnitPrefix = { VM_MICRO },
416            .expectExitResultUnit = VM_HERTZ
417        });
418    
419        runScript({
420            .code = R"NKSP_CODE(
421    on init
422      exit(42mHz)
423    end on
424    )NKSP_CODE",
425            .expectIntExitResult = 42,
426            .expectExitResultUnitPrefix = { VM_MILLI },
427            .expectExitResultUnit = VM_HERTZ
428        });
429    
430        runScript({
431            .code = R"NKSP_CODE(
432    on init
433      exit(42cHz)
434    end on
435    )NKSP_CODE",
436            .expectIntExitResult = 42,
437            .expectExitResultUnitPrefix = { VM_CENTI },
438            .expectExitResultUnit = VM_HERTZ
439        });
440    
441        runScript({
442            .code = R"NKSP_CODE(
443    on init
444      exit(42dHz)
445    end on
446    )NKSP_CODE",
447            .expectIntExitResult = 42,
448            .expectExitResultUnitPrefix = { VM_DECI },
449            .expectExitResultUnit = VM_HERTZ
450        });
451    
452        runScript({
453            .code = R"NKSP_CODE(
454    on init
455      exit(42daHz)
456    end on
457    )NKSP_CODE",
458            .expectIntExitResult = 42,
459            .expectExitResultUnitPrefix = { VM_DECA },
460            .expectExitResultUnit = VM_HERTZ
461        });
462    
463        runScript({
464            .code = R"NKSP_CODE(
465    on init
466      exit(42hHz)
467    end on
468    )NKSP_CODE",
469            .expectIntExitResult = 42,
470            .expectExitResultUnitPrefix = { VM_HECTO },
471            .expectExitResultUnit = VM_HERTZ
472        });
473    
474        runScript({
475            .code = R"NKSP_CODE(
476    on init
477      exit(42kHz)
478    end on
479    )NKSP_CODE",
480            .expectIntExitResult = 42,
481            .expectExitResultUnitPrefix = { VM_KILO },
482            .expectExitResultUnit = VM_HERTZ
483        });
484    
485        runScript({
486            .code = R"NKSP_CODE(
487    on init
488      exit(42Hz)
489    end on
490    )NKSP_CODE",
491            .expectIntExitResult = 42,
492            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
493            .expectExitResultUnit = VM_HERTZ
494        });
495    
496        runScript({
497            .code = R"NKSP_CODE(
498    on init
499      exit(42uB)
500    end on
501    )NKSP_CODE",
502            .expectIntExitResult = 42,
503            .expectExitResultUnitPrefix = { VM_MICRO },
504            .expectExitResultUnit = VM_BEL
505        });
506    
507        runScript({
508            .code = R"NKSP_CODE(
509    on init
510      exit(42mB)
511    end on
512    )NKSP_CODE",
513            .expectIntExitResult = 42,
514            .expectExitResultUnitPrefix = { VM_MILLI },
515            .expectExitResultUnit = VM_BEL
516        });
517    
518        runScript({
519            .code = R"NKSP_CODE(
520    on init
521      exit(42cB)
522    end on
523    )NKSP_CODE",
524            .expectIntExitResult = 42,
525            .expectExitResultUnitPrefix = { VM_CENTI },
526            .expectExitResultUnit = VM_BEL
527        });
528    
529        runScript({
530            .code = R"NKSP_CODE(
531    on init
532      exit(42dB)
533    end on
534    )NKSP_CODE",
535            .expectIntExitResult = 42,
536            .expectExitResultUnitPrefix = { VM_DECI },
537            .expectExitResultUnit = VM_BEL
538        });
539    
540        runScript({
541            .code = R"NKSP_CODE(
542    on init
543      exit(42daB)
544    end on
545    )NKSP_CODE",
546            .expectIntExitResult = 42,
547            .expectExitResultUnitPrefix = { VM_DECA },
548            .expectExitResultUnit = VM_BEL
549        });
550    
551        runScript({
552            .code = R"NKSP_CODE(
553    on init
554      exit(42hB)
555    end on
556    )NKSP_CODE",
557            .expectIntExitResult = 42,
558            .expectExitResultUnitPrefix = { VM_HECTO },
559            .expectExitResultUnit = VM_BEL
560        });
561    
562        runScript({
563            .code = R"NKSP_CODE(
564    on init
565      exit(42kB)
566    end on
567    )NKSP_CODE",
568            .expectIntExitResult = 42,
569            .expectExitResultUnitPrefix = { VM_KILO },
570            .expectExitResultUnit = VM_BEL
571        });
572    
573        runScript({
574            .code = R"NKSP_CODE(
575    on init
576      exit(42B)
577    end on
578    )NKSP_CODE",
579            .expectIntExitResult = 42,
580            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
581            .expectExitResultUnit = VM_BEL
582        });
583    
584        runScript({
585            .code = R"NKSP_CODE(
586    on init
587      exit(42udB)
588    end on
589    )NKSP_CODE",
590            .expectIntExitResult = 42,
591            .expectExitResultUnitPrefix = { VM_MICRO, VM_DECI },
592            .expectExitResultUnit = VM_BEL
593        });
594    
595        runScript({
596            .code = R"NKSP_CODE(
597    on init
598      exit(42mdB)
599    end on
600    )NKSP_CODE",
601            .expectIntExitResult = 42,
602            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
603            .expectExitResultUnit = VM_BEL
604        });
605    
606        runScript({
607            .code = R"NKSP_CODE(
608    on init
609      exit(42cdB)
610    end on
611    )NKSP_CODE",
612            .expectIntExitResult = 42,
613            .expectExitResultUnitPrefix = { VM_CENTI, VM_DECI },
614            .expectExitResultUnit = VM_BEL
615        });
616    
617        runScript({
618            .code = R"NKSP_CODE(
619    on init
620      exit(42ddB)
621    end on
622    )NKSP_CODE",
623            .expectIntExitResult = 42,
624            .expectExitResultUnitPrefix = { VM_DECI, VM_DECI },
625            .expectExitResultUnit = VM_BEL
626        });
627    
628        runScript({
629            .code = R"NKSP_CODE(
630    on init
631      exit(42dadB)
632    end on
633    )NKSP_CODE",
634            .expectIntExitResult = 42,
635            .expectExitResultUnitPrefix = { VM_DECA, VM_DECI },
636            .expectExitResultUnit = VM_BEL
637        });
638    
639        runScript({
640            .code = R"NKSP_CODE(
641    on init
642      exit(42hdB)
643    end on
644    )NKSP_CODE",
645            .expectIntExitResult = 42,
646            .expectExitResultUnitPrefix = { VM_HECTO, VM_DECI },
647            .expectExitResultUnit = VM_BEL
648        });
649    
650        runScript({
651            .code = R"NKSP_CODE(
652    on init
653      exit(42kdB)
654    end on
655    )NKSP_CODE",
656            .expectIntExitResult = 42,
657            .expectExitResultUnitPrefix = { VM_KILO, VM_DECI },
658            .expectExitResultUnit = VM_BEL
659        });
660    
661        runScript({
662            .code = R"NKSP_CODE(
663    on init
664      declare $foo := 42mdB
665      exit($foo)
666    end on
667    )NKSP_CODE",
668            .expectIntExitResult = 42,
669            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
670            .expectExitResultUnit = VM_BEL
671        });
672    
673        runScript({
674            .code = R"NKSP_CODE(
675    on init
676      exit(3.14s)
677    end on
678    )NKSP_CODE",
679            .expectRealExitResult = 3.14,
680            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
681            .expectExitResultUnit = VM_SECOND
682        });
683    
684        runScript({
685            .code = R"NKSP_CODE(
686    on init
687      exit(3.14us)
688    end on
689    )NKSP_CODE",
690            .expectRealExitResult = 3.14,
691            .expectExitResultUnitPrefix = { VM_MICRO },
692            .expectExitResultUnit = VM_SECOND
693        });
694    
695        runScript({
696            .code = R"NKSP_CODE(
697    on init
698      exit(3.14ms)
699    end on
700    )NKSP_CODE",
701            .expectRealExitResult = 3.14,
702            .expectExitResultUnitPrefix = { VM_MILLI },
703            .expectExitResultUnit = VM_SECOND
704        });
705    
706        runScript({
707            .code = R"NKSP_CODE(
708    on init
709      exit(-0.1B)
710    end on
711    )NKSP_CODE",
712            .expectRealExitResult = -0.1,
713            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
714            .expectExitResultUnit = VM_BEL
715        });
716    
717        runScript({
718            .code = R"NKSP_CODE(
719    on init
720      exit(-0.1dB)
721    end on
722    )NKSP_CODE",
723            .expectRealExitResult = -0.1,
724            .expectExitResultUnitPrefix = { VM_DECI },
725            .expectExitResultUnit = VM_BEL
726        });
727    
728        runScript({
729            .code = R"NKSP_CODE(
730    on init
731      exit(-0.1mdB)
732    end on
733    )NKSP_CODE",
734            .expectRealExitResult = -0.1,
735            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
736            .expectExitResultUnit = VM_BEL
737        });
738    
739        runScript({
740            .code = R"NKSP_CODE(
741    on init
742      declare ~foo := -0.1mdB
743      exit(~foo)
744    end on
745    )NKSP_CODE",
746            .expectRealExitResult = -0.1,
747            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
748            .expectExitResultUnit = VM_BEL
749        });
750    
751        runScript({
752            .code = R"NKSP_CODE(
753    on init
754      declare ~foo := 0.0dB
755      ~foo := -0.1mdB
756      exit(~foo)
757    end on
758    )NKSP_CODE",
759            .expectRealExitResult = -0.1,
760            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
761            .expectExitResultUnit = VM_BEL
762        });
763    
764        runScript({
765            .code = R"NKSP_CODE(
766    on init
767      declare ~foo := 0.0dB
768      ~foo := -0.1Hz
769      exit(~foo)
770    end on
771    )NKSP_CODE",
772            .expectParseError = true // assigning different unit type to a variable is not allowed
773        });
774    
775        // 'final' ('!') operator tests ...
776    
777        runScript({
778            .code = R"NKSP_CODE(
779    on init
780      exit(!42)
781    end on
782    )NKSP_CODE",
783            .expectIntExitResult = 42,
784            .expectExitResultFinal = true
785        });
786    
787        runScript({
788            .code = R"NKSP_CODE(
789    on init
790      exit(42)
791    end on
792    )NKSP_CODE",
793            .expectIntExitResult = 42,
794            .expectExitResultFinal = false
795        });
796    
797        runScript({
798            .code = R"NKSP_CODE(
799    on init
800      declare $foo := !42
801      exit($foo)
802    end on
803    )NKSP_CODE",
804            .expectIntExitResult = 42,
805            .expectExitResultFinal = true
806        });
807    
808        runScript({
809            .code = R"NKSP_CODE(
810    on init
811      declare $foo := 42
812      exit($foo)
813    end on
814    )NKSP_CODE",
815            .expectIntExitResult = 42,
816            .expectExitResultFinal = false
817        });
818    
819        runScript({
820            .code = R"NKSP_CODE(
821    on init
822      declare ~foo := !3.14
823      exit(~foo)
824    end on
825    )NKSP_CODE",
826            .expectRealExitResult = 3.14,
827            .expectExitResultFinal = true
828        });
829    
830        runScript({
831            .code = R"NKSP_CODE(
832    on init
833      declare ~foo := 3.14
834      exit(~foo)
835    end on
836    )NKSP_CODE",
837            .expectRealExitResult = 3.14,
838            .expectExitResultFinal = false
839        });
840    
841        runScript({
842            .code = R"NKSP_CODE(
843    on init
844      declare ~foo := !3.14mdB
845      exit(~foo)
846    end on
847    )NKSP_CODE",
848            .expectRealExitResult = 3.14,
849            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
850            .expectExitResultUnit = VM_BEL,
851            .expectExitResultFinal = true
852        });
853    
854        runScript({
855            .code = R"NKSP_CODE(
856    on init
857      declare ~foo := !0.0mdB
858      ~foo := !3.14mdB
859      exit(~foo)
860    end on
861    )NKSP_CODE",
862            .expectRealExitResult = 3.14,
863            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
864            .expectExitResultUnit = VM_BEL,
865            .expectExitResultFinal = true
866        });
867    
868        runScript({
869            .code = R"NKSP_CODE(
870    on init
871      declare ~foo := !0.0mdB
872      ~foo := 3.14mdB
873      exit(~foo)
874    end on
875    )NKSP_CODE",
876            .expectParseError = true // assigning non-final to a final variable not allowed
877        });
878    
879        runScript({
880            .code = R"NKSP_CODE(
881    on init
882      declare ~foo := 0.0mdB
883      ~foo := !3.14mdB
884      exit(~foo)
885    end on
886    )NKSP_CODE",
887            .expectParseError = true // assigning final to a non-final variable not allowed
888        });
889    
890      #if !SILENT_TEST      #if !SILENT_TEST
891      std::cout << std::endl;      std::cout << std::endl;
892      #endif      #endif
# Line 241  static void testStringConcatOperator() { Line 897  static void testStringConcatOperator() {
897      std::cout << "UNIT TEST: string concatenation (&) operator\n";      std::cout << "UNIT TEST: string concatenation (&) operator\n";
898      #endif      #endif
899    
900        // strings only tests ...
901    
902      runScript({      runScript({
903          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
904  on init  on init
# Line 251  end on Line 909  end on
909          .expectStringExitResult = "foo bar"          .expectStringExitResult = "foo bar"
910      });      });
911    
912        // integer tests ...
913    
914      runScript({      runScript({
915          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
916  on init  on init
# Line 272  end on Line 932  end on
932          .expectStringExitResult = "foo bar 123"          .expectStringExitResult = "foo bar 123"
933      });      });
934    
935        // real number tests ...
936    
937        runScript({
938            .code = R"NKSP_CODE(
939    on init
940      declare @s := "foo" & " bar" & " " & 1.23
941      exit(@s)
942    end on
943    )NKSP_CODE",
944            .expectStringExitResult = "foo bar 1.23"
945        });
946    
947        runScript({
948            .code = R"NKSP_CODE(
949    on init
950      declare ~r := 3.14
951      declare @s := "foo" & " bar" & " " & ~r
952      exit(@s)
953    end on
954    )NKSP_CODE",
955            .expectStringExitResult = "foo bar 3.14"
956        });
957    
958        // std unit tests ...
959    
960        runScript({
961            .code = R"NKSP_CODE(
962    on init
963      declare $i := 500Hz
964      declare @s := "foo" & " bar" & " " & $i
965      exit(@s)
966    end on
967    )NKSP_CODE",
968            .expectStringExitResult = "foo bar 500Hz"
969        });
970    
971        runScript({
972            .code = R"NKSP_CODE(
973    on init
974      declare ~r := 3.14s
975      declare @s := "foo" & " bar" & " " & ~r
976      exit(@s)
977    end on
978    )NKSP_CODE",
979            .expectStringExitResult = "foo bar 3.14s"
980        });
981    
982        runScript({
983            .code = R"NKSP_CODE(
984    on init
985      declare ~r := -22.3mdB
986      declare @s := "foo" & " bar" & " " & ~r
987      exit(@s)
988    end on
989    )NKSP_CODE",
990            .expectStringExitResult = "foo bar -22.3mdB"
991        });
992    
993        runScript({
994            .code = R"NKSP_CODE(
995    on init
996      declare $i := 20us
997      declare @s := "foo" & " bar" & " " & $i
998      exit(@s)
999    end on
1000    )NKSP_CODE",
1001            .expectStringExitResult = "foo bar 20us"
1002        });
1003    
1004        runScript({
1005            .code = R"NKSP_CODE(
1006    on init
1007      declare $i := 20kHz
1008      declare @s := "foo" & " bar" & " " & $i
1009      exit(@s)
1010    end on
1011    )NKSP_CODE",
1012            .expectStringExitResult = "foo bar 20kHz"
1013        });
1014    
1015        runScript({
1016            .code = R"NKSP_CODE(
1017    on init
1018      declare $i := -6dB
1019      declare @s := "foo" & " bar" & " " & $i
1020      exit(@s)
1021    end on
1022    )NKSP_CODE",
1023            .expectStringExitResult = "foo bar -6dB"
1024        });
1025    
1026        runScript({
1027            .code = R"NKSP_CODE(
1028    on init
1029      declare $i := 1us * 1d
1030      declare @s := "foo" & " bar" & " " & $i
1031      exit(@s)
1032    end on
1033    )NKSP_CODE",
1034            .expectStringExitResult = "foo bar 1*10^-7s"
1035        });
1036    
1037        runScript({
1038            .code = R"NKSP_CODE(
1039    on init
1040      declare ~r := 12.4mc
1041      declare @s := "foo" & " bar" & " " & ~r
1042      exit(@s)
1043    end on
1044    )NKSP_CODE",
1045            .expectStringExitResult = "foo bar 12.4mc"
1046        });
1047    
1048      #if !SILENT_TEST      #if !SILENT_TEST
1049      std::cout << std::endl;      std::cout << std::endl;
1050      #endif      #endif
# Line 324  end on Line 1097  end on
1097          .expectRealExitResult = 99.3          .expectRealExitResult = 99.3
1098      });      });
1099    
1100        // std unit tests
1101    
1102        runScript({
1103            .code = R"NKSP_CODE(
1104    on init
1105      declare $foo := -87mdB
1106      exit(-$foo)
1107    end on
1108    )NKSP_CODE",
1109            .expectIntExitResult = 87,
1110            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
1111            .expectExitResultUnit = VM_BEL
1112        });
1113    
1114        // 'final' ('!') operator tests ...
1115    
1116        runScript({
1117            .code = R"NKSP_CODE(
1118    on init
1119      declare $foo := !-87
1120      exit(-$foo)
1121    end on
1122    )NKSP_CODE",
1123            .expectIntExitResult = 87,
1124            .expectExitResultFinal = true
1125        });
1126    
1127        runScript({
1128            .code = R"NKSP_CODE(
1129    on init
1130      declare $foo := -87
1131      exit(-$foo)
1132    end on
1133    )NKSP_CODE",
1134            .expectIntExitResult = 87,
1135            .expectExitResultFinal = false
1136        });
1137    
1138      #if !SILENT_TEST      #if !SILENT_TEST
1139      std::cout << std::endl;      std::cout << std::endl;
1140      #endif      #endif
# Line 392  end on Line 1203  end on
1203          .expectRealExitResult = -1.8          .expectRealExitResult = -1.8
1204      });      });
1205    
1206        // std unit tests ...
1207    
1208        runScript({
1209            .code = R"NKSP_CODE(
1210    on init
1211      exit(42ms + 145ms)
1212    end on
1213    )NKSP_CODE",
1214            .expectIntExitResult = 187,
1215            .expectExitResultUnitPrefix = { VM_MILLI },
1216            .expectExitResultUnit = VM_SECOND
1217        });
1218    
1219        runScript({
1220            .code = R"NKSP_CODE(
1221    on init
1222      exit(1s + 145ms)
1223    end on
1224    )NKSP_CODE",
1225            .expectIntExitResult = 1145,
1226            .expectExitResultUnitPrefix = { VM_MILLI },
1227            .expectExitResultUnit = VM_SECOND
1228        });
1229    
1230        runScript({
1231            .code = R"NKSP_CODE(
1232    on init
1233      exit(42ms + 145)
1234    end on
1235    )NKSP_CODE",
1236            .expectParseError = true // units must match for + operator
1237        });
1238    
1239        runScript({
1240            .code = R"NKSP_CODE(
1241    on init
1242      exit(42 + 145ms)
1243    end on
1244    )NKSP_CODE",
1245            .expectParseError = true // units must match for + operator
1246        });
1247    
1248        runScript({
1249            .code = R"NKSP_CODE(
1250    on init
1251      exit(42Hz + 145s)
1252    end on
1253    )NKSP_CODE",
1254            .expectParseError = true // units must match for + operator
1255        });
1256    
1257        runScript({
1258            .code = R"NKSP_CODE(
1259    on init
1260      exit(42.1ms + 145.3ms)
1261    end on
1262    )NKSP_CODE",
1263            .expectRealExitResult = 187.4,
1264            .expectExitResultUnitPrefix = { VM_MILLI },
1265            .expectExitResultUnit = VM_SECOND
1266        });
1267    
1268        runScript({
1269            .code = R"NKSP_CODE(
1270    on init
1271      exit(1.1s + 145.0ms)
1272    end on
1273    )NKSP_CODE",
1274            .expectRealExitResult = 1245.0,
1275            .expectExitResultUnitPrefix = { VM_MILLI },
1276            .expectExitResultUnit = VM_SECOND
1277        });
1278    
1279        runScript({
1280            .code = R"NKSP_CODE(
1281    on init
1282      exit(42.1ms + 145.3)
1283    end on
1284    )NKSP_CODE",
1285            .expectParseError = true // units must match for + operator
1286        });
1287    
1288        runScript({
1289            .code = R"NKSP_CODE(
1290    on init
1291      exit(42.0 + 145.0ms)
1292    end on
1293    )NKSP_CODE",
1294            .expectParseError = true // units must match for + operator
1295        });
1296    
1297        runScript({
1298            .code = R"NKSP_CODE(
1299    on init
1300      exit(42.0Hz + 145.0s)
1301    end on
1302    )NKSP_CODE",
1303            .expectParseError = true // units must match for + operator
1304        });
1305    
1306        // 'final' ('!') operator tests ...
1307    
1308        runScript({
1309            .code = R"NKSP_CODE(
1310    on init
1311      exit(!4 + !3)
1312    end on
1313    )NKSP_CODE",
1314            .expectIntExitResult = 7,
1315            .expectExitResultFinal = true
1316        });
1317    
1318        runScript({
1319            .code = R"NKSP_CODE(
1320    on init
1321      exit(4 + 3)
1322    end on
1323    )NKSP_CODE",
1324            .expectIntExitResult = 7,
1325            .expectExitResultFinal = false
1326        });
1327    
1328        runScript({
1329            .code = R"NKSP_CODE(
1330    on init
1331      exit(!4.1 + !3.3)
1332    end on
1333    )NKSP_CODE",
1334            .expectRealExitResult = 7.4,
1335            .expectExitResultFinal = true
1336        });
1337    
1338        runScript({
1339            .code = R"NKSP_CODE(
1340    on init
1341      exit(4.1 + 3.3)
1342    end on
1343    )NKSP_CODE",
1344            .expectRealExitResult = 7.4,
1345            .expectExitResultFinal = false
1346        });
1347    
1348      #if !SILENT_TEST      #if !SILENT_TEST
1349      std::cout << std::endl;      std::cout << std::endl;
1350      #endif      #endif
# Line 469  end on Line 1422  end on
1422          .expectRealExitResult = -21.1          .expectRealExitResult = -21.1
1423      });      });
1424    
1425        // std unit tests ...
1426    
1427        runScript({
1428            .code = R"NKSP_CODE(
1429    on init
1430      exit(1000ms - 145ms)
1431    end on
1432    )NKSP_CODE",
1433            .expectIntExitResult = 855,
1434            .expectExitResultUnitPrefix = { VM_MILLI },
1435            .expectExitResultUnit = VM_SECOND
1436        });
1437    
1438        runScript({
1439            .code = R"NKSP_CODE(
1440    on init
1441      exit(1s - 145ms)
1442    end on
1443    )NKSP_CODE",
1444            .expectIntExitResult = 855,
1445            .expectExitResultUnitPrefix = { VM_MILLI },
1446            .expectExitResultUnit = VM_SECOND
1447        });
1448    
1449        runScript({
1450            .code = R"NKSP_CODE(
1451    on init
1452      exit(1s - 145)
1453    end on
1454    )NKSP_CODE",
1455            .expectParseError = true // units must match for - operator
1456        });
1457    
1458        runScript({
1459            .code = R"NKSP_CODE(
1460    on init
1461      exit(1 - 145s)
1462    end on
1463    )NKSP_CODE",
1464            .expectParseError = true // units must match for - operator
1465        });
1466    
1467        runScript({
1468            .code = R"NKSP_CODE(
1469    on init
1470      exit(1ms - 145mB)
1471    end on
1472    )NKSP_CODE",
1473            .expectParseError = true // units must match for - operator
1474        });
1475    
1476        runScript({
1477            .code = R"NKSP_CODE(
1478    on init
1479      exit(1.0ms - 0.1ms)
1480    end on
1481    )NKSP_CODE",
1482            .expectRealExitResult = 0.9,
1483            .expectExitResultUnitPrefix = { VM_MILLI },
1484            .expectExitResultUnit = VM_SECOND
1485        });
1486    
1487        runScript({
1488            .code = R"NKSP_CODE(
1489    on init
1490      exit(1.1s - 106.0ms)
1491    end on
1492    )NKSP_CODE",
1493            .expectRealExitResult = 994.0,
1494            .expectExitResultUnitPrefix = { VM_MILLI },
1495            .expectExitResultUnit = VM_SECOND
1496        });
1497    
1498        runScript({
1499            .code = R"NKSP_CODE(
1500    on init
1501      exit(1100.0ms - 0.106s)
1502    end on
1503    )NKSP_CODE",
1504            .expectRealExitResult = 994.0,
1505            .expectExitResultUnitPrefix = { VM_MILLI },
1506            .expectExitResultUnit = VM_SECOND
1507        });
1508    
1509        runScript({
1510            .code = R"NKSP_CODE(
1511    on init
1512      exit(1.0s - 145.0)
1513    end on
1514    )NKSP_CODE",
1515            .expectParseError = true // units must match for - operator
1516        });
1517    
1518        runScript({
1519            .code = R"NKSP_CODE(
1520    on init
1521      exit(1.0 - 145.0s)
1522    end on
1523    )NKSP_CODE",
1524            .expectParseError = true // units must match for - operator
1525        });
1526    
1527        runScript({
1528            .code = R"NKSP_CODE(
1529    on init
1530      exit(1.0ms - 145.0mB)
1531    end on
1532    )NKSP_CODE",
1533            .expectParseError = true // units must match for - operator
1534        });
1535    
1536        // 'final' ('!') operator tests ...
1537    
1538        runScript({
1539            .code = R"NKSP_CODE(
1540    on init
1541      exit(!5 - !3)
1542    end on
1543    )NKSP_CODE",
1544            .expectIntExitResult = 2,
1545            .expectExitResultFinal = true
1546        });
1547    
1548        runScript({
1549            .code = R"NKSP_CODE(
1550    on init
1551      exit(5 - 3)
1552    end on
1553    )NKSP_CODE",
1554            .expectIntExitResult = 2,
1555            .expectExitResultFinal = false
1556        });
1557    
1558        runScript({
1559            .code = R"NKSP_CODE(
1560    on init
1561      exit(!5.9 - !3.3)
1562    end on
1563    )NKSP_CODE",
1564            .expectRealExitResult = 2.6,
1565            .expectExitResultFinal = true
1566        });
1567    
1568        runScript({
1569            .code = R"NKSP_CODE(
1570    on init
1571      exit(5.9 - 3.3)
1572    end on
1573    )NKSP_CODE",
1574            .expectRealExitResult = 2.6,
1575            .expectExitResultFinal = false
1576        });
1577    
1578      #if !SILENT_TEST      #if !SILENT_TEST
1579      std::cout << std::endl;      std::cout << std::endl;
1580      #endif      #endif
# Line 542  end on Line 1648  end on
1648          .expectParseError = true // mod operator prohibits real numbers ATM          .expectParseError = true // mod operator prohibits real numbers ATM
1649      });      });
1650    
1651        // std unit tests ...
1652    
1653        runScript({
1654            .code = R"NKSP_CODE(
1655    on init
1656      exit(10s mod 8)
1657    end on
1658    )NKSP_CODE",
1659            .expectParseError = true // mod operator prohibits std units ATM
1660        });
1661    
1662        runScript({
1663            .code = R"NKSP_CODE(
1664    on init
1665      exit(10 mod 8s)
1666    end on
1667    )NKSP_CODE",
1668            .expectParseError = true // mod operator prohibits std units ATM
1669        });
1670    
1671        runScript({
1672            .code = R"NKSP_CODE(
1673    on init
1674      exit(10s mod 8s)
1675    end on
1676    )NKSP_CODE",
1677            .expectParseError = true // mod operator prohibits std units ATM
1678        });
1679    
1680        // 'final' ('!') operator tests ...
1681    
1682        runScript({
1683            .code = R"NKSP_CODE(
1684    on init
1685      exit(!10 mod !8)
1686    end on
1687    )NKSP_CODE",
1688            .expectIntExitResult = 2,
1689            .expectExitResultFinal = true
1690        });
1691    
1692        runScript({
1693            .code = R"NKSP_CODE(
1694    on init
1695      exit(10 mod 8)
1696    end on
1697    )NKSP_CODE",
1698            .expectIntExitResult = 2,
1699            .expectExitResultFinal = false
1700        });
1701    
1702      #if !SILENT_TEST      #if !SILENT_TEST
1703      std::cout << std::endl;      std::cout << std::endl;
1704      #endif      #endif
# Line 649  end on Line 1806  end on
1806          .expectParseError = true // mixed int * real forbidden ATM          .expectParseError = true // mixed int * real forbidden ATM
1807      });      });
1808    
1809        // std unit tests ...
1810    
1811        runScript({
1812            .code = R"NKSP_CODE(
1813    on init
1814      exit(10ms * 8)
1815    end on
1816    )NKSP_CODE",
1817            .expectIntExitResult = 80,
1818            .expectExitResultUnitPrefix = { VM_MILLI },
1819            .expectExitResultUnit = VM_SECOND
1820        });
1821    
1822        runScript({
1823            .code = R"NKSP_CODE(
1824    on init
1825      exit(10 * 8ms)
1826    end on
1827    )NKSP_CODE",
1828            .expectIntExitResult = 80,
1829            .expectExitResultUnitPrefix = { VM_MILLI },
1830            .expectExitResultUnit = VM_SECOND
1831        });
1832    
1833        runScript({
1834            .code = R"NKSP_CODE(
1835    on init
1836      exit(10s * 8s)
1837    end on
1838    )NKSP_CODE",
1839            .expectParseError = true // units on both sides not allowed for * ATM
1840        });
1841    
1842        runScript({
1843            .code = R"NKSP_CODE(
1844    on init
1845      exit(10cs * 8d)
1846    end on
1847    )NKSP_CODE",
1848            .expectIntExitResult = 80,
1849            .expectExitResultUnitPrefix = { VM_MILLI },
1850            .expectExitResultUnit = VM_SECOND
1851        });
1852    
1853        runScript({
1854            .code = R"NKSP_CODE(
1855    on init
1856      exit(10m * 8ms)
1857    end on
1858    )NKSP_CODE",
1859            .expectIntExitResult = 80,
1860            .expectExitResultUnitPrefix = { VM_MICRO },
1861            .expectExitResultUnit = VM_SECOND
1862        });
1863    
1864        runScript({
1865            .code = R"NKSP_CODE(
1866    on init
1867      exit(10ms * 8k)
1868    end on
1869    )NKSP_CODE",
1870            .expectIntExitResult = 80,
1871            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
1872            .expectExitResultUnit = VM_SECOND
1873        });
1874    
1875        runScript({
1876            .code = R"NKSP_CODE(
1877    on init
1878      exit(10.1ms * 8.0)
1879    end on
1880    )NKSP_CODE",
1881            .expectRealExitResult = 80.8,
1882            .expectExitResultUnitPrefix = { VM_MILLI },
1883            .expectExitResultUnit = VM_SECOND
1884        });
1885    
1886        runScript({
1887            .code = R"NKSP_CODE(
1888    on init
1889      exit(10.1 * 8.0ms)
1890    end on
1891    )NKSP_CODE",
1892            .expectRealExitResult = 80.8,
1893            .expectExitResultUnitPrefix = { VM_MILLI },
1894            .expectExitResultUnit = VM_SECOND
1895        });
1896    
1897        runScript({
1898            .code = R"NKSP_CODE(
1899    on init
1900      exit(10.0s * 8.0s)
1901    end on
1902    )NKSP_CODE",
1903            .expectParseError = true // units on both sides not allowed for * ATM
1904        });
1905    
1906        runScript({
1907            .code = R"NKSP_CODE(
1908    on init
1909      exit(10.1ds * 8.0c)
1910    end on
1911    )NKSP_CODE",
1912            .expectRealExitResult = 80.8,
1913            .expectExitResultUnitPrefix = { VM_MILLI },
1914            .expectExitResultUnit = VM_SECOND
1915        });
1916    
1917        runScript({
1918            .code = R"NKSP_CODE(
1919    on init
1920      exit(10.1m * 8.0ms)
1921    end on
1922    )NKSP_CODE",
1923            .expectRealExitResult = 80.8,
1924            .expectExitResultUnitPrefix = { VM_MICRO },
1925            .expectExitResultUnit = VM_SECOND
1926        });
1927    
1928        runScript({
1929            .code = R"NKSP_CODE(
1930    on init
1931      exit(10.1m * 8.0ks)
1932    end on
1933    )NKSP_CODE",
1934            .expectRealExitResult = 80.8,
1935            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
1936            .expectExitResultUnit = VM_SECOND
1937        });
1938    
1939        // 'final' ('!') operator tests ...
1940    
1941        runScript({
1942            .code = R"NKSP_CODE(
1943    on init
1944      exit(!10 * !8)
1945    end on
1946    )NKSP_CODE",
1947            .expectIntExitResult = 80,
1948            .expectExitResultFinal = true
1949        });
1950    
1951        runScript({
1952            .code = R"NKSP_CODE(
1953    on init
1954      exit(10 * 8)
1955    end on
1956    )NKSP_CODE",
1957            .expectIntExitResult = 80,
1958            .expectExitResultFinal = false
1959        });
1960    
1961        runScript({
1962            .code = R"NKSP_CODE(
1963    on init
1964      exit(!10 * 8)
1965    end on
1966    )NKSP_CODE",
1967            .expectIntExitResult = 80,
1968            .expectExitResultFinal = true,
1969            .expectParseWarning = true // since final only on one side, result will be final though
1970        });
1971    
1972        runScript({
1973            .code = R"NKSP_CODE(
1974    on init
1975      exit(10 * !8)
1976    end on
1977    )NKSP_CODE",
1978            .expectIntExitResult = 80,
1979            .expectExitResultFinal = true,
1980            .expectParseWarning = true // since final only on one side, result will be final though
1981        });
1982    
1983        runScript({
1984            .code = R"NKSP_CODE(
1985    on init
1986      exit(!10.1 * !8.0)
1987    end on
1988    )NKSP_CODE",
1989            .expectRealExitResult = 80.8,
1990            .expectExitResultFinal = true
1991        });
1992    
1993        runScript({
1994            .code = R"NKSP_CODE(
1995    on init
1996      exit(10.1 * 8.0)
1997    end on
1998    )NKSP_CODE",
1999            .expectRealExitResult = 80.8,
2000            .expectExitResultFinal = false
2001        });
2002    
2003        runScript({
2004            .code = R"NKSP_CODE(
2005    on init
2006      exit(!10.1 * 8.0)
2007    end on
2008    )NKSP_CODE",
2009            .expectRealExitResult = 80.8,
2010            .expectExitResultFinal = true,
2011            .expectParseWarning = true // since final only on one side, result will be final though
2012        });
2013    
2014        runScript({
2015            .code = R"NKSP_CODE(
2016    on init
2017      exit(10.1 * !8.0)
2018    end on
2019    )NKSP_CODE",
2020            .expectRealExitResult = 80.8,
2021            .expectExitResultFinal = true,
2022            .expectParseWarning = true // since final only on one side, result will be final though
2023        });
2024    
2025      #if !SILENT_TEST      #if !SILENT_TEST
2026      std::cout << std::endl;      std::cout << std::endl;
2027      #endif      #endif
# Line 756  end on Line 2129  end on
2129          .expectParseError = true // mixed int / real forbidden ATM          .expectParseError = true // mixed int / real forbidden ATM
2130      });      });
2131    
2132        // std unit tests ...
2133    
2134        runScript({
2135            .code = R"NKSP_CODE(
2136    on init
2137      exit(-27us / 3)
2138    end on
2139    )NKSP_CODE",
2140            .expectIntExitResult = -9,
2141            .expectExitResultUnitPrefix = { VM_MICRO },
2142            .expectExitResultUnit = VM_SECOND
2143        });
2144    
2145        runScript({
2146            .code = R"NKSP_CODE(
2147    on init
2148      exit(-27mdB / 3mdB)
2149    end on
2150    )NKSP_CODE",
2151            .expectIntExitResult = -9,
2152            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
2153            .expectExitResultUnit = VM_NO_UNIT
2154        });
2155    
2156        runScript({
2157            .code = R"NKSP_CODE(
2158    on init
2159      exit(-27s / 3m)
2160    end on
2161    )NKSP_CODE",
2162            .expectIntExitResult = -9,
2163            .expectExitResultUnitPrefix = { VM_KILO },
2164            .expectExitResultUnit = VM_SECOND
2165        });
2166    
2167        runScript({
2168            .code = R"NKSP_CODE(
2169    on init
2170      exit(-27us / 3m)
2171    end on
2172    )NKSP_CODE",
2173            .expectIntExitResult = -9,
2174            .expectExitResultUnitPrefix = { VM_MILLI },
2175            .expectExitResultUnit = VM_SECOND
2176        });
2177    
2178        runScript({
2179            .code = R"NKSP_CODE(
2180    on init
2181      exit(-27 / 3s)
2182    end on
2183    )NKSP_CODE",
2184            .expectParseError = true // illegal unit type arrangement for divisions
2185        });
2186    
2187        runScript({
2188            .code = R"NKSP_CODE(
2189    on init
2190      exit(-27s / 3Hz)
2191    end on
2192    )NKSP_CODE",
2193            .expectParseError = true // unit types are not matching
2194        });
2195    
2196        // 'final' ('!') operator tests ...
2197    
2198        runScript({
2199            .code = R"NKSP_CODE(
2200    on init
2201      exit(!-27 / !3)
2202    end on
2203    )NKSP_CODE",
2204            .expectIntExitResult = -9,
2205            .expectExitResultFinal = true
2206        });
2207    
2208        runScript({
2209            .code = R"NKSP_CODE(
2210    on init
2211      exit(-27 / 3)
2212    end on
2213    )NKSP_CODE",
2214            .expectIntExitResult = -9,
2215            .expectExitResultFinal = false
2216        });
2217    
2218        runScript({
2219            .code = R"NKSP_CODE(
2220    on init
2221      exit(!-27 / 3)
2222    end on
2223    )NKSP_CODE",
2224            .expectIntExitResult = -9,
2225            .expectExitResultFinal = true,
2226            .expectParseWarning = true // final only on one side, result will be final though
2227        });
2228    
2229        runScript({
2230            .code = R"NKSP_CODE(
2231    on init
2232      exit(-27 / !3)
2233    end on
2234    )NKSP_CODE",
2235            .expectIntExitResult = -9,
2236            .expectExitResultFinal = true,
2237            .expectParseWarning = true // final only on one side, result will be final though
2238        });
2239    
2240      #if !SILENT_TEST      #if !SILENT_TEST
2241      std::cout << std::endl;      std::cout << std::endl;
2242      #endif      #endif
# Line 916  end on Line 2397  end on
2397          .expectBoolExitResult = false          .expectBoolExitResult = false
2398      });      });
2399    
2400        // std unit tests ...
2401    
2402        runScript({
2403            .code = R"NKSP_CODE(
2404    on init
2405      exit(13ms < 14ms)
2406    end on
2407    )NKSP_CODE",
2408            .expectBoolExitResult = true
2409        });
2410    
2411        runScript({
2412            .code = R"NKSP_CODE(
2413    on init
2414      exit(14ms < 13ms)
2415    end on
2416    )NKSP_CODE",
2417            .expectBoolExitResult = false
2418        });
2419    
2420        runScript({
2421            .code = R"NKSP_CODE(
2422    on init
2423      exit(1s < 990ms)
2424    end on
2425    )NKSP_CODE",
2426            .expectBoolExitResult = false
2427        });
2428    
2429        runScript({
2430            .code = R"NKSP_CODE(
2431    on init
2432      exit(990ms < 1s)
2433    end on
2434    )NKSP_CODE",
2435            .expectBoolExitResult = true
2436        });
2437    
2438        runScript({
2439            .code = R"NKSP_CODE(
2440    on init
2441      exit(1000ms < 1s)
2442    end on
2443    )NKSP_CODE",
2444            .expectBoolExitResult = false
2445        });
2446    
2447        runScript({
2448            .code = R"NKSP_CODE(
2449    on init
2450      exit(1s < 1000ms)
2451    end on
2452    )NKSP_CODE",
2453            .expectBoolExitResult = false
2454        });
2455    
2456        runScript({
2457            .code = R"NKSP_CODE(
2458    on init
2459      exit(1s < 1)
2460    end on
2461    )NKSP_CODE",
2462            .expectParseError = true // units on both sides must match
2463        });
2464    
2465        runScript({
2466            .code = R"NKSP_CODE(
2467    on init
2468      exit(1 < 1s)
2469    end on
2470    )NKSP_CODE",
2471            .expectParseError = true // units on both sides must match
2472        });
2473    
2474        runScript({
2475            .code = R"NKSP_CODE(
2476    on init
2477      exit(1Hz < 1B)
2478    end on
2479    )NKSP_CODE",
2480            .expectParseError = true // units on both sides must match
2481        });
2482    
2483        runScript({
2484            .code = R"NKSP_CODE(
2485    on init
2486      exit(13.0ms < 13.1ms)
2487    end on
2488    )NKSP_CODE",
2489            .expectBoolExitResult = true
2490        });
2491    
2492        runScript({
2493            .code = R"NKSP_CODE(
2494    on init
2495      exit(13.1ms < 13.0ms)
2496    end on
2497    )NKSP_CODE",
2498            .expectBoolExitResult = false
2499        });
2500    
2501        runScript({
2502            .code = R"NKSP_CODE(
2503    on init
2504      exit(0.9s < 600.0ms)
2505    end on
2506    )NKSP_CODE",
2507            .expectBoolExitResult = false
2508        });
2509    
2510        runScript({
2511            .code = R"NKSP_CODE(
2512    on init
2513      exit(600.0ms < 0.9s)
2514    end on
2515    )NKSP_CODE",
2516            .expectBoolExitResult = true
2517        });
2518    
2519        runScript({
2520            .code = R"NKSP_CODE(
2521    on init
2522      exit(5.1kHz < 5100.0Hz)
2523    end on
2524    )NKSP_CODE",
2525            .expectBoolExitResult = false
2526        });
2527    
2528        runScript({
2529            .code = R"NKSP_CODE(
2530    on init
2531      exit(5100.0Hz < 5.1kHz)
2532    end on
2533    )NKSP_CODE",
2534            .expectBoolExitResult = false
2535        });
2536    
2537        runScript({
2538            .code = R"NKSP_CODE(
2539    on init
2540      exit(1.0Hz < 1.1)
2541    end on
2542    )NKSP_CODE",
2543            .expectParseError = true // units on both sides must match
2544        });
2545    
2546        runScript({
2547            .code = R"NKSP_CODE(
2548    on init
2549      exit(1.2 < 1.34mdB)
2550    end on
2551    )NKSP_CODE",
2552            .expectParseError = true // units on both sides must match
2553        });
2554    
2555        runScript({
2556            .code = R"NKSP_CODE(
2557    on init
2558      exit(9.23us < 3.14kHz)
2559    end on
2560    )NKSP_CODE",
2561            .expectParseError = true // units on both sides must match
2562        });
2563    
2564        // 'final' ('!') operator tests ...
2565        // (should always yield in false for relation operators)
2566    
2567        runScript({
2568            .code = R"NKSP_CODE(
2569    on init
2570      exit(!-4 < !3)
2571    end on
2572    )NKSP_CODE",
2573            .expectBoolExitResult = true,
2574            .expectExitResultFinal = false
2575        });
2576    
2577        runScript({
2578            .code = R"NKSP_CODE(
2579    on init
2580      exit(-4 < 3)
2581    end on
2582    )NKSP_CODE",
2583            .expectBoolExitResult = true,
2584            .expectExitResultFinal = false
2585        });
2586    
2587      #if !SILENT_TEST      #if !SILENT_TEST
2588      std::cout << std::endl;      std::cout << std::endl;
2589      #endif      #endif
# Line 1076  end on Line 2744  end on
2744          .expectBoolExitResult = true          .expectBoolExitResult = true
2745      });      });
2746    
2747        // std unit tests ...
2748    
2749        runScript({
2750            .code = R"NKSP_CODE(
2751    on init
2752      exit(13ms > 14ms)
2753    end on
2754    )NKSP_CODE",
2755            .expectBoolExitResult = false
2756        });
2757    
2758        runScript({
2759            .code = R"NKSP_CODE(
2760    on init
2761      exit(14ms > 13ms)
2762    end on
2763    )NKSP_CODE",
2764            .expectBoolExitResult = true
2765        });
2766    
2767        runScript({
2768            .code = R"NKSP_CODE(
2769    on init
2770      exit(1s > 990ms)
2771    end on
2772    )NKSP_CODE",
2773            .expectBoolExitResult = true
2774        });
2775    
2776        runScript({
2777            .code = R"NKSP_CODE(
2778    on init
2779      exit(990ms > 1s)
2780    end on
2781    )NKSP_CODE",
2782            .expectBoolExitResult = false
2783        });
2784    
2785        runScript({
2786            .code = R"NKSP_CODE(
2787    on init
2788      exit(1000ms > 1s)
2789    end on
2790    )NKSP_CODE",
2791            .expectBoolExitResult = false
2792        });
2793    
2794        runScript({
2795            .code = R"NKSP_CODE(
2796    on init
2797      exit(1s > 1000ms)
2798    end on
2799    )NKSP_CODE",
2800            .expectBoolExitResult = false
2801        });
2802    
2803        runScript({
2804            .code = R"NKSP_CODE(
2805    on init
2806      exit(1s > 1)
2807    end on
2808    )NKSP_CODE",
2809            .expectParseError = true // units on both sides must match
2810        });
2811    
2812        runScript({
2813            .code = R"NKSP_CODE(
2814    on init
2815      exit(1 > 1s)
2816    end on
2817    )NKSP_CODE",
2818            .expectParseError = true // units on both sides must match
2819        });
2820    
2821        runScript({
2822            .code = R"NKSP_CODE(
2823    on init
2824      exit(1Hz > 1B)
2825    end on
2826    )NKSP_CODE",
2827            .expectParseError = true // units on both sides must match
2828        });
2829    
2830        runScript({
2831            .code = R"NKSP_CODE(
2832    on init
2833      exit(13.0ms > 13.1ms)
2834    end on
2835    )NKSP_CODE",
2836            .expectBoolExitResult = false
2837        });
2838    
2839        runScript({
2840            .code = R"NKSP_CODE(
2841    on init
2842      exit(13.1ms > 13.0ms)
2843    end on
2844    )NKSP_CODE",
2845            .expectBoolExitResult = true
2846        });
2847    
2848        runScript({
2849            .code = R"NKSP_CODE(
2850    on init
2851      exit(0.9s > 600.0ms)
2852    end on
2853    )NKSP_CODE",
2854            .expectBoolExitResult = true
2855        });
2856    
2857        runScript({
2858            .code = R"NKSP_CODE(
2859    on init
2860      exit(600.0ms > 0.9s)
2861    end on
2862    )NKSP_CODE",
2863            .expectBoolExitResult = false
2864        });
2865    
2866        runScript({
2867            .code = R"NKSP_CODE(
2868    on init
2869      exit(5.1kHz > 5100.0Hz)
2870    end on
2871    )NKSP_CODE",
2872            .expectBoolExitResult = false
2873        });
2874    
2875        runScript({
2876            .code = R"NKSP_CODE(
2877    on init
2878      exit(5100.0Hz > 5.1kHz)
2879    end on
2880    )NKSP_CODE",
2881            .expectBoolExitResult = false
2882        });
2883    
2884        runScript({
2885            .code = R"NKSP_CODE(
2886    on init
2887      exit(1.0Hz > 1.1)
2888    end on
2889    )NKSP_CODE",
2890            .expectParseError = true // units on both sides must match
2891        });
2892    
2893        runScript({
2894            .code = R"NKSP_CODE(
2895    on init
2896      exit(1.2 > 1.34mdB)
2897    end on
2898    )NKSP_CODE",
2899            .expectParseError = true // units on both sides must match
2900        });
2901    
2902        runScript({
2903            .code = R"NKSP_CODE(
2904    on init
2905      exit(9.23us > 3.14kHz)
2906    end on
2907    )NKSP_CODE",
2908            .expectParseError = true // units on both sides must match
2909        });
2910    
2911        // 'final' ('!') operator tests ...
2912        // (should always yield in false for relation operators)
2913    
2914        runScript({
2915            .code = R"NKSP_CODE(
2916    on init
2917      exit(!-4 > !3)
2918    end on
2919    )NKSP_CODE",
2920            .expectBoolExitResult = false,
2921            .expectExitResultFinal = false
2922        });
2923    
2924        runScript({
2925            .code = R"NKSP_CODE(
2926    on init
2927      exit(-4 > 3)
2928    end on
2929    )NKSP_CODE",
2930            .expectBoolExitResult = false,
2931            .expectExitResultFinal = false
2932        });
2933    
2934      #if !SILENT_TEST      #if !SILENT_TEST
2935      std::cout << std::endl;      std::cout << std::endl;
2936      #endif      #endif
# Line 1308  end on Line 3163  end on
3163          .expectBoolExitResult = true          .expectBoolExitResult = true
3164      });      });
3165    
3166        // std unit tests ...
3167    
3168        runScript({
3169            .code = R"NKSP_CODE(
3170    on init
3171      exit(13ms <= 14ms)
3172    end on
3173    )NKSP_CODE",
3174            .expectBoolExitResult = true
3175        });
3176    
3177        runScript({
3178            .code = R"NKSP_CODE(
3179    on init
3180      exit(14ms <= 13ms)
3181    end on
3182    )NKSP_CODE",
3183            .expectBoolExitResult = false
3184        });
3185    
3186        runScript({
3187            .code = R"NKSP_CODE(
3188    on init
3189      exit(1s <= 990ms)
3190    end on
3191    )NKSP_CODE",
3192            .expectBoolExitResult = false
3193        });
3194    
3195        runScript({
3196            .code = R"NKSP_CODE(
3197    on init
3198      exit(990ms <= 1s)
3199    end on
3200    )NKSP_CODE",
3201            .expectBoolExitResult = true
3202        });
3203    
3204        runScript({
3205            .code = R"NKSP_CODE(
3206    on init
3207      exit(1000ms <= 1s)
3208    end on
3209    )NKSP_CODE",
3210            .expectBoolExitResult = true
3211        });
3212    
3213        runScript({
3214            .code = R"NKSP_CODE(
3215    on init
3216      exit(1s <= 1000ms)
3217    end on
3218    )NKSP_CODE",
3219            .expectBoolExitResult = true
3220        });
3221    
3222        runScript({
3223            .code = R"NKSP_CODE(
3224    on init
3225      exit(1s <= 1)
3226    end on
3227    )NKSP_CODE",
3228            .expectParseError = true // units on both sides must match
3229        });
3230    
3231        runScript({
3232            .code = R"NKSP_CODE(
3233    on init
3234      exit(1 <= 1s)
3235    end on
3236    )NKSP_CODE",
3237            .expectParseError = true // units on both sides must match
3238        });
3239    
3240        runScript({
3241            .code = R"NKSP_CODE(
3242    on init
3243      exit(1Hz <= 1B)
3244    end on
3245    )NKSP_CODE",
3246            .expectParseError = true // units on both sides must match
3247        });
3248    
3249        runScript({
3250            .code = R"NKSP_CODE(
3251    on init
3252      exit(13.0ms <= 13.1ms)
3253    end on
3254    )NKSP_CODE",
3255            .expectBoolExitResult = true
3256        });
3257    
3258        runScript({
3259            .code = R"NKSP_CODE(
3260    on init
3261      exit(13.1ms <= 13.0ms)
3262    end on
3263    )NKSP_CODE",
3264            .expectBoolExitResult = false
3265        });
3266    
3267        runScript({
3268            .code = R"NKSP_CODE(
3269    on init
3270      exit(0.9s <= 600.0ms)
3271    end on
3272    )NKSP_CODE",
3273            .expectBoolExitResult = false
3274        });
3275    
3276        runScript({
3277            .code = R"NKSP_CODE(
3278    on init
3279      exit(600.0ms <= 0.9s)
3280    end on
3281    )NKSP_CODE",
3282            .expectBoolExitResult = true
3283        });
3284    
3285        runScript({
3286            .code = R"NKSP_CODE(
3287    on init
3288      exit(5.1kHz <= 5100.0Hz)
3289    end on
3290    )NKSP_CODE",
3291            .expectBoolExitResult = true
3292        });
3293    
3294        runScript({
3295            .code = R"NKSP_CODE(
3296    on init
3297      exit(5100.0Hz <= 5.1kHz)
3298    end on
3299    )NKSP_CODE",
3300            .expectBoolExitResult = true
3301        });
3302    
3303        runScript({
3304            .code = R"NKSP_CODE(
3305    on init
3306      exit(1.0Hz <= 1.1)
3307    end on
3308    )NKSP_CODE",
3309            .expectParseError = true // units on both sides must match
3310        });
3311    
3312        runScript({
3313            .code = R"NKSP_CODE(
3314    on init
3315      exit(1.2 <= 1.34mdB)
3316    end on
3317    )NKSP_CODE",
3318            .expectParseError = true // units on both sides must match
3319        });
3320    
3321        runScript({
3322            .code = R"NKSP_CODE(
3323    on init
3324      exit(9.23us <= 3.14kHz)
3325    end on
3326    )NKSP_CODE",
3327            .expectParseError = true // units on both sides must match
3328        });
3329    
3330        // 'final' ('!') operator tests ...
3331        // (should always yield in false for relation operators)
3332    
3333        runScript({
3334            .code = R"NKSP_CODE(
3335    on init
3336      exit(!-4 <= !3)
3337    end on
3338    )NKSP_CODE",
3339            .expectBoolExitResult = true,
3340            .expectExitResultFinal = false
3341        });
3342    
3343        runScript({
3344            .code = R"NKSP_CODE(
3345    on init
3346      exit(-4 <= 3)
3347    end on
3348    )NKSP_CODE",
3349            .expectBoolExitResult = true,
3350            .expectExitResultFinal = false
3351        });
3352    
3353      #if !SILENT_TEST      #if !SILENT_TEST
3354      std::cout << std::endl;      std::cout << std::endl;
3355      #endif      #endif
# Line 1558  end on Line 3600  end on
3600          .expectBoolExitResult = true          .expectBoolExitResult = true
3601      });      });
3602    
3603        // std unit tests ...
3604    
3605        runScript({
3606            .code = R"NKSP_CODE(
3607    on init
3608      exit(13ms >= 14ms)
3609    end on
3610    )NKSP_CODE",
3611            .expectBoolExitResult = false
3612        });
3613    
3614        runScript({
3615            .code = R"NKSP_CODE(
3616    on init
3617      exit(14ms >= 13ms)
3618    end on
3619    )NKSP_CODE",
3620            .expectBoolExitResult = true
3621        });
3622    
3623        runScript({
3624            .code = R"NKSP_CODE(
3625    on init
3626      exit(1s >= 990ms)
3627    end on
3628    )NKSP_CODE",
3629            .expectBoolExitResult = true
3630        });
3631    
3632        runScript({
3633            .code = R"NKSP_CODE(
3634    on init
3635      exit(990ms >= 1s)
3636    end on
3637    )NKSP_CODE",
3638            .expectBoolExitResult = false
3639        });
3640    
3641        runScript({
3642            .code = R"NKSP_CODE(
3643    on init
3644      exit(1000ms >= 1s)
3645    end on
3646    )NKSP_CODE",
3647            .expectBoolExitResult = true
3648        });
3649    
3650        runScript({
3651            .code = R"NKSP_CODE(
3652    on init
3653      exit(1s >= 1000ms)
3654    end on
3655    )NKSP_CODE",
3656            .expectBoolExitResult = true
3657        });
3658    
3659        runScript({
3660            .code = R"NKSP_CODE(
3661    on init
3662      exit(1s >= 1)
3663    end on
3664    )NKSP_CODE",
3665            .expectParseError = true // units on both sides must match
3666        });
3667    
3668        runScript({
3669            .code = R"NKSP_CODE(
3670    on init
3671      exit(1 >= 1s)
3672    end on
3673    )NKSP_CODE",
3674            .expectParseError = true // units on both sides must match
3675        });
3676    
3677        runScript({
3678            .code = R"NKSP_CODE(
3679    on init
3680      exit(1Hz >= 1B)
3681    end on
3682    )NKSP_CODE",
3683            .expectParseError = true // units on both sides must match
3684        });
3685    
3686        runScript({
3687            .code = R"NKSP_CODE(
3688    on init
3689      exit(13.0ms >= 13.1ms)
3690    end on
3691    )NKSP_CODE",
3692            .expectBoolExitResult = false
3693        });
3694    
3695        runScript({
3696            .code = R"NKSP_CODE(
3697    on init
3698      exit(13.1ms >= 13.0ms)
3699    end on
3700    )NKSP_CODE",
3701            .expectBoolExitResult = true
3702        });
3703    
3704        runScript({
3705            .code = R"NKSP_CODE(
3706    on init
3707      exit(0.9s >= 600.0ms)
3708    end on
3709    )NKSP_CODE",
3710            .expectBoolExitResult = true
3711        });
3712    
3713        runScript({
3714            .code = R"NKSP_CODE(
3715    on init
3716      exit(600.0ms >= 0.9s)
3717    end on
3718    )NKSP_CODE",
3719            .expectBoolExitResult = false
3720        });
3721    
3722        runScript({
3723            .code = R"NKSP_CODE(
3724    on init
3725      exit(5.1kHz >= 5100.0Hz)
3726    end on
3727    )NKSP_CODE",
3728            .expectBoolExitResult = true
3729        });
3730    
3731        runScript({
3732            .code = R"NKSP_CODE(
3733    on init
3734      exit(5100.0Hz >= 5.1kHz)
3735    end on
3736    )NKSP_CODE",
3737            .expectBoolExitResult = true
3738        });
3739    
3740        runScript({
3741            .code = R"NKSP_CODE(
3742    on init
3743      exit(1.0Hz >= 1.1)
3744    end on
3745    )NKSP_CODE",
3746            .expectParseError = true // units on both sides must match
3747        });
3748    
3749        runScript({
3750            .code = R"NKSP_CODE(
3751    on init
3752      exit(1.2 >= 1.34mdB)
3753    end on
3754    )NKSP_CODE",
3755            .expectParseError = true // units on both sides must match
3756        });
3757    
3758        runScript({
3759            .code = R"NKSP_CODE(
3760    on init
3761      exit(9.23us >= 3.14kHz)
3762    end on
3763    )NKSP_CODE",
3764            .expectParseError = true // units on both sides must match
3765        });
3766    
3767        // 'final' ('!') operator tests ...
3768        // (should always yield in false for relation operators)
3769    
3770        runScript({
3771            .code = R"NKSP_CODE(
3772    on init
3773      exit(!-4 >= !3)
3774    end on
3775    )NKSP_CODE",
3776            .expectBoolExitResult = false,
3777            .expectExitResultFinal = false
3778        });
3779    
3780        runScript({
3781            .code = R"NKSP_CODE(
3782    on init
3783      exit(-4 >= 3)
3784    end on
3785    )NKSP_CODE",
3786            .expectBoolExitResult = false,
3787            .expectExitResultFinal = false
3788        });
3789    
3790      #if !SILENT_TEST      #if !SILENT_TEST
3791      std::cout << std::endl;      std::cout << std::endl;
3792      #endif      #endif
# Line 1653  end on Line 3882  end on
3882          .expectBoolExitResult = false          .expectBoolExitResult = false
3883      });      });
3884    
3885        // deal with inaccuracy of float point
3886        runScript({
3887            .code = R"NKSP_CODE(
3888    on init
3889      declare ~a := 0.165
3890      declare ~b := 0.185
3891      declare ~x := 0.1
3892      declare ~y := 0.25
3893      exit(~a + ~b = ~x + ~y) { both sides should actually be 0.35, they slightly deviate both though }
3894    end on
3895    )NKSP_CODE",
3896            .expectBoolExitResult = true // our implementation of real number equal comparison should take care about floating point tolerance
3897        });
3898    
3899        // deal with inaccuracy of float point
3900        runScript({
3901            .code = R"NKSP_CODE(
3902    on init
3903      declare ~a := 0.166
3904      declare ~b := 0.185
3905      declare ~x := 0.1
3906      declare ~y := 0.25
3907      exit(~a + ~b = ~x + ~y) { left side approx. 0.351, right side approx. 0.35 }
3908    end on
3909    )NKSP_CODE",
3910            .expectBoolExitResult = false
3911        });
3912    
3913      // mixed type tests ...      // mixed type tests ...
3914    
3915      runScript({      runScript({
# Line 1691  end on Line 3948  end on
3948          .expectBoolExitResult = false          .expectBoolExitResult = false
3949      });      });
3950    
3951        // std unit tests ...
3952    
3953        runScript({
3954            .code = R"NKSP_CODE(
3955    on init
3956      exit(13ms = 14ms)
3957    end on
3958    )NKSP_CODE",
3959            .expectBoolExitResult = false
3960        });
3961    
3962        runScript({
3963            .code = R"NKSP_CODE(
3964    on init
3965      exit(14ms = 13ms)
3966    end on
3967    )NKSP_CODE",
3968            .expectBoolExitResult = false
3969        });
3970    
3971        runScript({
3972            .code = R"NKSP_CODE(
3973    on init
3974      exit(1s = 1ms)
3975    end on
3976    )NKSP_CODE",
3977            .expectBoolExitResult = false
3978        });
3979    
3980        runScript({
3981            .code = R"NKSP_CODE(
3982    on init
3983      exit(1ms = 1s)
3984    end on
3985    )NKSP_CODE",
3986            .expectBoolExitResult = false
3987        });
3988    
3989        runScript({
3990            .code = R"NKSP_CODE(
3991    on init
3992      exit(3.14kHz = 3140Hz)
3993    end on
3994    )NKSP_CODE",
3995            .expectBoolExitResult = true
3996        });
3997    
3998        runScript({
3999            .code = R"NKSP_CODE(
4000    on init
4001      exit(3140Hz = 3.14kHz)
4002    end on
4003    )NKSP_CODE",
4004            .expectBoolExitResult = true
4005        });
4006    
4007        runScript({
4008            .code = R"NKSP_CODE(
4009    on init
4010      exit(1s = 1)
4011    end on
4012    )NKSP_CODE",
4013            .expectParseError = true // units on both sides must match
4014        });
4015    
4016        runScript({
4017            .code = R"NKSP_CODE(
4018    on init
4019      exit(1 = 1s)
4020    end on
4021    )NKSP_CODE",
4022            .expectParseError = true // units on both sides must match
4023        });
4024    
4025        runScript({
4026            .code = R"NKSP_CODE(
4027    on init
4028      exit(1Hz = 1B)
4029    end on
4030    )NKSP_CODE",
4031            .expectParseError = true // units on both sides must match
4032        });
4033    
4034        // 'final' ('!') operator tests ...
4035        // (should always yield in false for relation operators)
4036    
4037        runScript({
4038            .code = R"NKSP_CODE(
4039    on init
4040      exit(!-4 = !3)
4041    end on
4042    )NKSP_CODE",
4043            .expectBoolExitResult = false,
4044            .expectExitResultFinal = false
4045        });
4046    
4047        runScript({
4048            .code = R"NKSP_CODE(
4049    on init
4050      exit(-4 = 3)
4051    end on
4052    )NKSP_CODE",
4053            .expectBoolExitResult = false,
4054            .expectExitResultFinal = false
4055        });
4056    
4057      #if !SILENT_TEST      #if !SILENT_TEST
4058      std::cout << std::endl;      std::cout << std::endl;
4059      #endif      #endif
# Line 1777  end on Line 4140  end on
4140          .expectBoolExitResult = true          .expectBoolExitResult = true
4141      });      });
4142    
4143        // deal with inaccuracy of float point
4144        runScript({
4145            .code = R"NKSP_CODE(
4146    on init
4147      declare ~a := 0.165
4148      declare ~b := 0.185
4149      declare ~x := 0.1
4150      declare ~y := 0.25
4151            exit(~a + ~b # ~x + ~y) { both sides should actually be 0.35, they slightly deviate both though }
4152    end on
4153    )NKSP_CODE",
4154            .expectBoolExitResult = false // our implementation of real number unequal comparison should take care about floating point tolerance
4155        });
4156    
4157        // deal with inaccuracy of float point
4158        runScript({
4159            .code = R"NKSP_CODE(
4160    on init
4161      declare ~a := 0.166
4162      declare ~b := 0.185
4163      declare ~x := 0.1
4164      declare ~y := 0.25
4165            exit(~a + ~b # ~x + ~y) { left side approx. 0.351, right side approx. 0.35 }
4166    end on
4167    )NKSP_CODE",
4168            .expectBoolExitResult = true
4169        });
4170    
4171      // mixed type tests ...      // mixed type tests ...
4172    
4173      runScript({      runScript({
# Line 1815  end on Line 4206  end on
4206          .expectBoolExitResult = true          .expectBoolExitResult = true
4207      });      });
4208    
4209        // std unit tests ...
4210    
4211        runScript({
4212            .code = R"NKSP_CODE(
4213    on init
4214      exit(13ms # 14ms)
4215    end on
4216    )NKSP_CODE",
4217            .expectBoolExitResult = true
4218        });
4219    
4220        runScript({
4221            .code = R"NKSP_CODE(
4222    on init
4223      exit(14ms # 13ms)
4224    end on
4225    )NKSP_CODE",
4226            .expectBoolExitResult = true
4227        });
4228    
4229        runScript({
4230            .code = R"NKSP_CODE(
4231    on init
4232      exit(1s # 1ms)
4233    end on
4234    )NKSP_CODE",
4235            .expectBoolExitResult = true
4236        });
4237    
4238        runScript({
4239            .code = R"NKSP_CODE(
4240    on init
4241      exit(1ms # 1s)
4242    end on
4243    )NKSP_CODE",
4244            .expectBoolExitResult = true
4245        });
4246    
4247        runScript({
4248            .code = R"NKSP_CODE(
4249    on init
4250      exit(3.14kHz # 3140Hz)
4251    end on
4252    )NKSP_CODE",
4253            .expectBoolExitResult = false
4254        });
4255    
4256        runScript({
4257            .code = R"NKSP_CODE(
4258    on init
4259      exit(3140Hz # 3.14kHz)
4260    end on
4261    )NKSP_CODE",
4262            .expectBoolExitResult = false
4263        });
4264    
4265        runScript({
4266            .code = R"NKSP_CODE(
4267    on init
4268      exit(1s # 1)
4269    end on
4270    )NKSP_CODE",
4271            .expectParseError = true // units on both sides must match
4272        });
4273    
4274        runScript({
4275            .code = R"NKSP_CODE(
4276    on init
4277      exit(1 # 1s)
4278    end on
4279    )NKSP_CODE",
4280            .expectParseError = true // units on both sides must match
4281        });
4282    
4283        runScript({
4284            .code = R"NKSP_CODE(
4285    on init
4286      exit(1Hz # 1B)
4287    end on
4288    )NKSP_CODE",
4289            .expectParseError = true // units on both sides must match
4290        });
4291    
4292        // 'final' ('!') operator tests ...
4293        // (should always yield in false for relation operators)
4294    
4295        runScript({
4296            .code = R"NKSP_CODE(
4297    on init
4298      exit(!-4 # !3)
4299    end on
4300    )NKSP_CODE",
4301            .expectBoolExitResult = true,
4302            .expectExitResultFinal = false
4303        });
4304    
4305        runScript({
4306            .code = R"NKSP_CODE(
4307    on init
4308      exit(-4 # 3)
4309    end on
4310    )NKSP_CODE",
4311            .expectBoolExitResult = true,
4312            .expectExitResultFinal = false
4313        });
4314    
4315      #if !SILENT_TEST      #if !SILENT_TEST
4316      std::cout << std::endl;      std::cout << std::endl;
4317      #endif      #endif
# Line 1914  end on Line 4411  end on
4411          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4412      });      });
4413    
4414        // std unit tests ...
4415        // (not allowed for this operator)
4416    
4417        runScript({
4418            .code = R"NKSP_CODE(
4419    on init
4420      exit(1s and 0)
4421    end on
4422    )NKSP_CODE",
4423            .expectParseError = true // std units not allowed for this operator
4424        });
4425    
4426        runScript({
4427            .code = R"NKSP_CODE(
4428    on init
4429      exit(0 and 1s)
4430    end on
4431    )NKSP_CODE",
4432            .expectParseError = true // std units not allowed for this operator
4433        });
4434    
4435        // 'final' ('!') operator tests ...
4436    
4437        runScript({
4438            .code = R"NKSP_CODE(
4439    on init
4440      exit(!0 and !0)
4441    end on
4442    )NKSP_CODE",
4443            .expectExitResultFinal = true
4444        });
4445    
4446        runScript({
4447            .code = R"NKSP_CODE(
4448    on init
4449      exit(0 and 0)
4450    end on
4451    )NKSP_CODE",
4452            .expectExitResultFinal = false
4453        });
4454    
4455      #if !SILENT_TEST      #if !SILENT_TEST
4456      std::cout << std::endl;      std::cout << std::endl;
4457      #endif      #endif
# Line 2013  end on Line 4551  end on
4551          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4552      });      });
4553    
4554        // std unit tests ...
4555        // (not allowed for this operator)
4556    
4557        runScript({
4558            .code = R"NKSP_CODE(
4559    on init
4560      exit(1s or 0)
4561    end on
4562    )NKSP_CODE",
4563            .expectParseError = true // std units not allowed for this operator
4564        });
4565    
4566        runScript({
4567            .code = R"NKSP_CODE(
4568    on init
4569      exit(0 or 1s)
4570    end on
4571    )NKSP_CODE",
4572            .expectParseError = true // std units not allowed for this operator
4573        });
4574    
4575        // 'final' ('!') operator tests ...
4576    
4577        runScript({
4578            .code = R"NKSP_CODE(
4579    on init
4580      exit(!0 or !0)
4581    end on
4582    )NKSP_CODE",
4583            .expectExitResultFinal = true
4584        });
4585    
4586        runScript({
4587            .code = R"NKSP_CODE(
4588    on init
4589      exit(0 or 0)
4590    end on
4591    )NKSP_CODE",
4592            .expectExitResultFinal = false
4593        });
4594    
4595      #if !SILENT_TEST      #if !SILENT_TEST
4596      std::cout << std::endl;      std::cout << std::endl;
4597      #endif      #endif
# Line 2064  end on Line 4643  end on
4643          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4644      });      });
4645    
4646        // std unit tests ...
4647        // (not allowed for this operator)
4648    
4649        runScript({
4650            .code = R"NKSP_CODE(
4651    on init
4652      exit(not 1s)
4653    end on
4654    )NKSP_CODE",
4655            .expectParseError = true // std units not allowed for this operator
4656        });
4657    
4658        // 'final' ('!') operator tests ...
4659    
4660        runScript({
4661            .code = R"NKSP_CODE(
4662    on init
4663      exit(not !1)
4664    end on
4665    )NKSP_CODE",
4666            .expectExitResultFinal = true
4667        });
4668    
4669        runScript({
4670            .code = R"NKSP_CODE(
4671    on init
4672      exit(not 1)
4673    end on
4674    )NKSP_CODE",
4675            .expectExitResultFinal = false
4676        });
4677    
4678      #if !SILENT_TEST      #if !SILENT_TEST
4679      std::cout << std::endl;      std::cout << std::endl;
4680      #endif      #endif
# Line 2127  end on Line 4738  end on
4738          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4739      });      });
4740    
4741        // std unit tests ...
4742        // (not allowed for this operator)
4743    
4744        runScript({
4745            .code = R"NKSP_CODE(
4746    on init
4747      exit(1s .and. 1)
4748    end on
4749    )NKSP_CODE",
4750            .expectParseError = true // std units not allowed for this operator
4751        });
4752    
4753        runScript({
4754            .code = R"NKSP_CODE(
4755    on init
4756      exit(1 .and. 1s)
4757    end on
4758    )NKSP_CODE",
4759            .expectParseError = true // std units not allowed for this operator
4760        });
4761    
4762        // 'final' ('!') operator tests ...
4763    
4764        runScript({
4765            .code = R"NKSP_CODE(
4766    on init
4767      exit(!43 .and. !142)
4768    end on
4769    )NKSP_CODE",
4770            .expectIntExitResult = 10,
4771            .expectExitResultFinal = true
4772        });
4773    
4774        runScript({
4775            .code = R"NKSP_CODE(
4776    on init
4777      exit(43 .and. 142)
4778    end on
4779    )NKSP_CODE",
4780            .expectIntExitResult = 10,
4781            .expectExitResultFinal = false
4782        });
4783    
4784      #if !SILENT_TEST      #if !SILENT_TEST
4785      std::cout << std::endl;      std::cout << std::endl;
4786      #endif      #endif
# Line 2199  end on Line 4853  end on
4853          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4854      });      });
4855    
4856        // std unit tests ...
4857        // (not allowed for this operator)
4858    
4859        runScript({
4860            .code = R"NKSP_CODE(
4861    on init
4862      exit(1s .or. 1)
4863    end on
4864    )NKSP_CODE",
4865            .expectParseError = true // std units not allowed for this operator
4866        });
4867    
4868        runScript({
4869            .code = R"NKSP_CODE(
4870    on init
4871      exit(1 .or. 1s)
4872    end on
4873    )NKSP_CODE",
4874            .expectParseError = true // std units not allowed for this operator
4875        });
4876    
4877        // 'final' ('!') operator tests ...
4878    
4879        runScript({
4880            .code = R"NKSP_CODE(
4881    on init
4882      exit(!43 .or. !142)
4883    end on
4884    )NKSP_CODE",
4885            .expectIntExitResult = 175,
4886            .expectExitResultFinal = true
4887        });
4888    
4889        runScript({
4890            .code = R"NKSP_CODE(
4891    on init
4892      exit(43 .or. 142)
4893    end on
4894    )NKSP_CODE",
4895            .expectIntExitResult = 175,
4896            .expectExitResultFinal = false
4897        });
4898    
4899      #if !SILENT_TEST      #if !SILENT_TEST
4900      std::cout << std::endl;      std::cout << std::endl;
4901      #endif      #endif
# Line 2259  end on Line 4956  end on
4956          .expectParseError = true // real numbers not allowed for this operator          .expectParseError = true // real numbers not allowed for this operator
4957      });      });
4958    
4959        // std unit tests ...
4960        // (not allowed for this operator)
4961    
4962        runScript({
4963            .code = R"NKSP_CODE(
4964    on init
4965      exit(.not. 1s)
4966    end on
4967    )NKSP_CODE",
4968            .expectParseError = true // std units not allowed for this operator
4969        });
4970    
4971        // 'final' ('!') operator tests ...
4972    
4973        runScript({
4974            .code = R"NKSP_CODE(
4975    on init
4976      exit(.not. !0)
4977    end on
4978    )NKSP_CODE",
4979            .expectIntExitResult = -1,
4980            .expectExitResultFinal = true
4981        });
4982    
4983        runScript({
4984            .code = R"NKSP_CODE(
4985    on init
4986      exit(.not. 0)
4987    end on
4988    )NKSP_CODE",
4989            .expectIntExitResult = -1,
4990            .expectExitResultFinal = false
4991        });
4992    
4993      #if !SILENT_TEST      #if !SILENT_TEST
4994      std::cout << std::endl;      std::cout << std::endl;
4995      #endif      #endif
# Line 2345  end on Line 5076  end on
5076          .expectRealExitResult = 20.8          .expectRealExitResult = 20.8
5077      });      });
5078    
5079        // std unit tests ...
5080    
5081        runScript({
5082            .code = R"NKSP_CODE(
5083    on init
5084      exit(4 * (2us + 3us) + 7ms)
5085    end on
5086    )NKSP_CODE",
5087            .expectIntExitResult = 7020,
5088            .expectExitResultUnitPrefix = { VM_MICRO },
5089            .expectExitResultUnit = VM_SECOND
5090        });
5091    
5092        runScript({
5093            .code = R"NKSP_CODE(
5094    on init
5095      declare $a := 4
5096      declare $c := 3us
5097      exit($a * (2us + $c) + 7ms)
5098    end on
5099    )NKSP_CODE",
5100            .expectIntExitResult = 7020,
5101            .expectExitResultUnitPrefix = { VM_MICRO },
5102            .expectExitResultUnit = VM_SECOND
5103        });
5104    
5105        runScript({
5106            .code = R"NKSP_CODE(
5107    on init
5108      declare $a := 4
5109      declare $b := 2us
5110      declare $c := 3us
5111      exit($a * ($b + $c) + 7ms)
5112    end on
5113    )NKSP_CODE",
5114            .expectIntExitResult = 7020,
5115            .expectExitResultUnitPrefix = { VM_MICRO },
5116            .expectExitResultUnit = VM_SECOND
5117        });
5118    
5119        runScript({
5120            .code = R"NKSP_CODE(
5121    on init
5122      declare $a := 4
5123      declare $b := 2us
5124      declare $c := 3us
5125      declare $d := 7ms
5126      exit($a * ($b + $c) + 7ms)
5127    end on
5128    )NKSP_CODE",
5129            .expectIntExitResult = 7020,
5130            .expectExitResultUnitPrefix = { VM_MICRO },
5131            .expectExitResultUnit = VM_SECOND
5132        });
5133    
5134        runScript({
5135            .code = R"NKSP_CODE(
5136    on init
5137      declare $c := 3us
5138      declare $a := 4
5139      declare $d := 7ms
5140      declare $b := 2us
5141      exit($a * ($b + $c) + 7ms)
5142    end on
5143    )NKSP_CODE",
5144            .expectIntExitResult = 7020,
5145            .expectExitResultUnitPrefix = { VM_MICRO },
5146            .expectExitResultUnit = VM_SECOND
5147        });
5148    
5149        runScript({
5150            .code = R"NKSP_CODE(
5151    on init
5152      exit(4.0 * (2.0mdB + 3.2mdB) / 2.0)
5153    end on
5154    )NKSP_CODE",
5155            .expectRealExitResult = 10.4,
5156            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
5157            .expectExitResultUnit = VM_BEL
5158        });
5159    
5160        runScript({
5161            .code = R"NKSP_CODE(
5162    on init
5163      declare ~a := 2.0mdB
5164      declare ~b := 3.2mdB
5165      exit(4.0 * (~a + ~b) / 2.0)
5166    end on
5167    )NKSP_CODE",
5168            .expectRealExitResult = 10.4,
5169            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
5170            .expectExitResultUnit = VM_BEL
5171        });
5172    
5173        runScript({
5174            .code = R"NKSP_CODE(
5175    on init
5176      declare ~b := 3.2mdB
5177      declare ~a := 2.0mdB
5178      exit(4.0 * (~a + ~b) / 2.0)
5179    end on
5180    )NKSP_CODE",
5181            .expectRealExitResult = 10.4,
5182            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
5183            .expectExitResultUnit = VM_BEL
5184        });
5185    
5186        runScript({
5187            .code = R"NKSP_CODE(
5188    on init
5189      declare ~a := 4.0
5190      declare ~b := 2.0mdB
5191      declare ~c := 3.2mdB
5192      declare ~d := 2.0
5193      exit((~a * (~b + ~c) / ~d) + 1.1mdB)
5194    end on
5195    )NKSP_CODE",
5196            .expectRealExitResult = 11.5,
5197            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
5198            .expectExitResultUnit = VM_BEL
5199        });
5200    
5201        runScript({
5202            .code = R"NKSP_CODE(
5203    on init
5204      declare ~c := 3.2mdB
5205      declare ~a := 4.0
5206      declare ~d := 2.0
5207      declare ~b := 2.0mdB
5208      exit(~a * (~b + ~c) / ~d + 1.1mdB)
5209    end on
5210    )NKSP_CODE",
5211            .expectRealExitResult = 11.5,
5212            .expectExitResultUnitPrefix = { VM_MILLI, VM_DECI },
5213            .expectExitResultUnit = VM_BEL
5214        });
5215    
5216        // 'final' ('!') operator tests ...
5217    
5218        runScript({
5219            .code = R"NKSP_CODE(
5220    on init
5221      declare $a := 4
5222      declare $b := !2us
5223      declare $c := 3us
5224      declare $d := 7ms
5225      exit($a * ($b + $c) + 7ms)
5226    end on
5227    )NKSP_CODE",
5228            .expectIntExitResult = 7020,
5229            .expectExitResultUnitPrefix = { VM_MICRO },
5230            .expectExitResultUnit = VM_SECOND,
5231            .expectExitResultFinal = true,
5232            .expectParseWarning = true // only one operand is defined as 'final', result will be final though
5233        });
5234    
5235        runScript({
5236            .code = R"NKSP_CODE(
5237    on init
5238      declare $a := 4
5239      declare $b := 2us
5240      declare $c := !3us
5241      declare $d := 7ms
5242      exit($a * ($b + $c) + 7ms)
5243    end on
5244    )NKSP_CODE",
5245            .expectIntExitResult = 7020,
5246            .expectExitResultUnitPrefix = { VM_MICRO },
5247            .expectExitResultUnit = VM_SECOND,
5248            .expectExitResultFinal = true,
5249            .expectParseWarning = true // only one operand is defined as 'final', result will be final though
5250        });
5251    
5252      #if !SILENT_TEST      #if !SILENT_TEST
5253      std::cout << std::endl;      std::cout << std::endl;
5254      #endif      #endif
# Line 2409  end on Line 5313  end on
5313      runScript({      runScript({
5314          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5315  on init  on init
5316    declare $foo := min(1.0, 2.0)    declare ~foo := min(1.0, 2.0)
5317    exit($foo)    exit(~foo)
5318  end on  end on
5319  )NKSP_CODE",  )NKSP_CODE",
5320          .expectRealExitResult = 1.0          .expectRealExitResult = 1.0
# Line 2419  end on Line 5323  end on
5323      runScript({      runScript({
5324          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5325  on init  on init
5326    declare $foo := min(-30.0, 4.0)    declare ~foo := min(-30.0, 4.0)
5327    exit($foo)    exit(~foo)
5328  end on  end on
5329  )NKSP_CODE",  )NKSP_CODE",
5330          .expectRealExitResult = -30.0          .expectRealExitResult = -30.0
# Line 2429  end on Line 5333  end on
5333      runScript({      runScript({
5334          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5335  on init  on init
5336    declare $foo := min(1.1, 1.13)    declare ~foo := min(1.1, 1.13)
5337    exit($foo)    exit(~foo)
5338  end on  end on
5339  )NKSP_CODE",  )NKSP_CODE",
5340          .expectRealExitResult = 1.1          .expectRealExitResult = 1.1
# Line 2439  end on Line 5343  end on
5343      runScript({      runScript({
5344          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5345  on init  on init
5346    declare $foo := min(1.13, 1.1)    declare ~foo := min(1.13, 1.1)
5347    exit($foo)    exit(~foo)
5348  end on  end on
5349  )NKSP_CODE",  )NKSP_CODE",
5350          .expectRealExitResult = 1.1          .expectRealExitResult = 1.1
# Line 2451  end on Line 5355  end on
5355      runScript({      runScript({
5356          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5357  on init  on init
5358    declare $foo := min(1, 1.16)    declare ~foo := min(1, 1.16)
5359      exit(~foo)
5360    end on
5361    )NKSP_CODE",
5362            .expectRealExitResult = 1.0,
5363            .expectParseWarning = true // min() warns if data types of arguments not matching
5364        });
5365    
5366        runScript({
5367            .code = R"NKSP_CODE(
5368    on init
5369      declare ~foo := min(-3.92, 9)
5370      exit(~foo)
5371    end on
5372    )NKSP_CODE",
5373            .expectRealExitResult = -3.92,
5374            .expectParseWarning = true // min() warns if data types of arguments not matching
5375        });
5376    
5377        // std unit tests ...
5378    
5379        runScript({
5380            .code = R"NKSP_CODE(
5381    on init
5382      declare $foo := min(30ms,4s)
5383    exit($foo)    exit($foo)
5384  end on  end on
5385  )NKSP_CODE",  )NKSP_CODE",
5386          .expectRealExitResult = 1.0          .expectIntExitResult = 30,
5387            .expectExitResultUnitPrefix = { VM_MILLI },
5388            .expectExitResultUnit = VM_SECOND,
5389      });      });
5390    
5391      runScript({      runScript({
5392          .code = R"NKSP_CODE(          .code = R"NKSP_CODE(
5393  on init  on init
5394    declare $foo := min(-3.92, 9)    declare $foo := min(4s,30ms)
5395    exit($foo)    exit($foo)
5396  end on  end on
5397  )NKSP_CODE",  )NKSP_CODE",
5398          .expectRealExitResult = -3.92          .expectIntExitResult = 30,
5399            .expectExitResultUnitPrefix = { VM_MILLI },
5400            .expectExitResultUnit = VM_SECOND,
5401        });
5402    
5403        runScript({
5404            .code = R"NKSP_CODE(
5405    on init
5406      declare $foo := min(-30mdB,-4dB)
5407      exit($foo)
5408    end on
5409    )NKSP_CODE",
5410            .expectIntExitResult = -4,
5411            .expectExitResultUnitPrefix = { VM_DECI },
5412            .expectExitResultUnit = VM_BEL,
5413        });
5414    
5415        runScript({
5416            .code = R"NKSP_CODE(
5417    on init
5418      declare $foo := min(-4dB,-30mdB)
5419      exit($foo)
5420    end on
5421    )NKSP_CODE",
5422            .expectIntExitResult = -4,
5423            .expectExitResultUnitPrefix = { VM_DECI },
5424            .expectExitResultUnit = VM_BEL,
5425        });
5426    
5427        runScript({
5428            .code = R"NKSP_CODE(
5429    on init
5430      declare $foo := min(-4s,-30Hz)
5431      exit($foo)
5432    end on
5433    )NKSP_CODE",
5434            .expectParseError = true // min() requires arguments to have same unit type
5435        });
5436    
5437        runScript({
5438            .code = R"NKSP_CODE(
5439    on init
5440      declare $foo := min(-4s,-30)
5441      exit($foo)
5442    end on
5443    )NKSP_CODE",
5444            .expectParseError = true // min() requires arguments to have same unit type
5445        });
5446    
5447        runScript({
5448            .code = R"NKSP_CODE(
5449    on init
5450      declare $foo := min(-4,-30s)
5451      exit($foo)
5452    end on
5453    )NKSP_CODE",
5454            .expectParseError = true // min() requires arguments to have same unit type
5455        });
5456    
5457        runScript({
5458            .code = R"NKSP_CODE(
5459    on init
5460      declare ~foo := min(0.9s,1.0s)
5461      exit(~foo)
5462    end on
5463    )NKSP_CODE",
5464            .expectRealExitResult = 0.9,
5465            .expectExitResultUnitPrefix = { VM_NO_PREFIX },
5466            .expectExitResultUnit = VM_SECOND,
5467        });
5468    
5469        // 'final' ('!') operator tests ...
5470    
5471        runScript({
5472            .code = R"NKSP_CODE(
5473    on init
5474      declare $foo := min(!30,!4)
5475      exit($foo)
5476    end on
5477    )NKSP_CODE",
5478            .expectIntExitResult = 4,
5479            .expectExitResultFinal = true
5480        });
5481    
5482        runScript({
5483            .code = R"NKSP_CODE(
5484    on init
5485      declare $foo := min(30,4)
5486      exit($foo)
5487    end on
5488    )NKSP_CODE",
5489            .expectIntExitResult = 4,
5490            .expectExitResultFinal = false
5491        });
5492    
5493        runScript({
5494            .code = R"NKSP_CODE(
5495    on init
5496      declare $foo := min(30,!4)
5497      exit($foo)
5498    end on
5499    )NKSP_CODE",
5500            .expectIntExitResult = 4,
5501            .expectExitResultFinal = true,
5502            .expectParseWarning = true // min() warns if only one argument is 'final'
5503        });
5504    
5505        runScript({
5506            .code = R"NKSP_CODE(
5507    on init
5508      declare $foo := min(!30,4)
5509      exit($foo)
5510    end on
5511    )NKSP_CODE",
5512            .expectIntExitResult = 4,
5513            .expectExitResultFinal = true,
5514            .expectParseWarning = true // min() warns if only one argument is 'final'
5515        });
5516    
5517        runScript({
5518            .code = R"NKSP_CODE(
5519    on init
5520      declare ~foo := min(!12.1,!12.2)
5521      exit(~foo)
5522    end on
5523    )NKSP_CODE",
5524            .expectRealExitResult = 12.1,
5525            .expectExitResultFinal = true
5526        });
5527    
5528        runScript({
5529            .code = R"NKSP_CODE(
5530    on init
5531      declare ~foo := min(12.1,12.2)
5532      exit(~foo)
5533    end on
5534    )NKSP_CODE",
5535            .expectRealExitResult = 12.1,
5536            .expectExitResultFinal = false
5537        });
5538    
5539        runScript({
5540     &nb