@@ -41,12 +41,15 @@ import ComponentRef = NFComponentRef;
4141import Binding = NFBinding ;
4242import NFComponent.Component ;
4343import Type = NFType ;
44+ import Dimension = NFDimension ;
4445
4546protected
4647import Ceval = NFCeval ;
4748import MetaModelica.Dangerous.* ;
4849import RangeIterator = NFRangeIterator ;
4950import ElementSource ;
51+ import ModelicaExternalC ;
52+ import System ;
5053
5154encapsulated package ReplTree
5255 import BaseAvlTree ;
@@ -80,6 +83,18 @@ function evaluate
8083 input Function fn;
8184 input list< Expression > args;
8285 output Expression result;
86+ algorithm
87+ if Function . isExternal(fn) then
88+ result := evaluateExternal(fn, args);
89+ else
90+ result := evaluateNormal(fn, args);
91+ end if ;
92+ end evaluate;
93+
94+ function evaluateNormal
95+ input Function fn;
96+ input list< Expression > args;
97+ output Expression result;
8398protected
8499 list< Statement > fn_body;
85100 list< Binding > bindings;
@@ -119,7 +134,33 @@ algorithm
119134 end try ;
120135
121136 Pointer . update(call_counter, call_count - 1 );
122- end evaluate;
137+ end evaluateNormal;
138+
139+ function evaluateExternal
140+ input Function fn;
141+ input list< Expression > args;
142+ output Expression result;
143+ protected
144+ String name, lang;
145+ ComponentRef output_ref;
146+ Option < SCode . Annotation > ann;
147+ algorithm
148+ Sections . EXTERNAL (name = name, outputRef = output_ref, language = lang, ann = ann) :=
149+ Class . getSections(InstNode . getClass(fn. node));
150+
151+ if lang == "builtin" then
152+ // Functions defined as 'external "builtin"', delegate to Ceval.
153+ result := Ceval . evalBuiltinCall(fn, args, NFCeval . EvalTarget . IGNORE_ERRORS ());
154+ elseif isKnownExternalFunc(name, ann) then
155+ // External functions that we know how to evaluate without generating code.
156+ result := evaluateKnownExternal(name, args);
157+ else
158+ // External functions that we would need to generate code for and execute.
159+ Error . assertion(false , getInstanceName() +
160+ ": evaluation of userdefined external functions not yet implemented" , sourceInfo());
161+ fail();
162+ end if ;
163+ end evaluateExternal;
123164
124165protected
125166
@@ -489,5 +530,182 @@ algorithm
489530 end while ;
490531end evaluateWhile;
491532
533+ function isKnownExternalFunc
534+ input String name;
535+ input Option < SCode . Annotation > ann;
536+ output Boolean isKnown;
537+ algorithm
538+ if isKnownLibrary(ann) then
539+ isKnown := true ;
540+ else
541+ isKnown := match name
542+ case "OpenModelica_regex" then true ;
543+ else false ;
544+ end match;
545+ end if ;
546+ end isKnownExternalFunc;
547+
548+ function isKnownLibrary
549+ input Option < SCode . Annotation > extAnnotation;
550+ output Boolean isKnown;
551+ protected
552+ SCode . Annotation ann;
553+ Absyn . Exp exp;
554+ algorithm
555+ if isSome(extAnnotation) then
556+ SOME (ann) := extAnnotation;
557+
558+ try
559+ isKnown := isKnownLibraryExp(SCode . getNamedAnnotation(ann, "Library" ));
560+ else
561+ isKnown := false ;
562+ end try ;
563+ else
564+ isKnown := false ;
565+ end if ;
566+ end isKnownLibrary;
567+
568+ function isKnownLibraryExp
569+ input Absyn . Exp exp;
570+ output Boolean isKnown;
571+ algorithm
572+ isKnown := match exp
573+ case Absyn . STRING ("ModelicaExternalC" ) then true ;
574+ case Absyn . ARRAY () then List . exist(exp. arrayExp, isKnownLibraryExp);
575+ else false ;
576+ end match;
577+ end isKnownLibraryExp;
578+
579+ constant list< String > FILE_TYPE_NAMES = {"NoFile" , "RegularFile" , "Directory" , "SpecialFile" };
580+ constant Absyn . Path FILE_TYPE_PATH = Absyn . Path . QUALIFIED ("Modelica" ,
581+ Absyn . Path . QUALIFIED ("Utilities" , Absyn . Path . QUALIFIED ("Types" , Absyn . Path . IDENT ("FileType" ))));
582+ constant Type FILE_TYPE_TYPE = Type . ENUMERATION (FILE_TYPE_PATH , FILE_TYPE_NAMES );
583+
584+ constant list< Expression > FILE_TYPE_LITERALS = {
585+ Expression . ENUM_LITERAL (FILE_TYPE_TYPE , "NoFile" , 1 ),
586+ Expression . ENUM_LITERAL (FILE_TYPE_TYPE , "RegularFile" , 2 ),
587+ Expression . ENUM_LITERAL (FILE_TYPE_TYPE , "Directory" , 3 ),
588+ Expression . ENUM_LITERAL (FILE_TYPE_TYPE , "SpecialFile" , 4 )
589+ };
590+
591+ constant list< String > COMPARE_NAMES = {"Less" , "Equal" , "Greater" };
592+ constant Absyn . Path COMPARE_PATH = Absyn . Path . QUALIFIED ("Modelica" ,
593+ Absyn . Path . QUALIFIED ("Utilities" , Absyn . Path . QUALIFIED ("Types" , Absyn . Path . IDENT ("Compare" ))));
594+ constant Type COMPARE_TYPE = Type . ENUMERATION (COMPARE_PATH , COMPARE_NAMES );
595+
596+ constant list< Expression > COMPARE_LITERALS = {
597+ Expression . ENUM_LITERAL (COMPARE_TYPE , "Less" , 1 ),
598+ Expression . ENUM_LITERAL (COMPARE_TYPE , "Equal" , 2 ),
599+ Expression . ENUM_LITERAL (COMPARE_TYPE , "Greater" , 3 )
600+ };
601+
602+ function evaluateKnownExternal
603+ input String name;
604+ input list< Expression > args;
605+ output Expression result;
606+ algorithm
607+ result := match (name, args)
608+ local
609+ String s1, s2;
610+ Integer i, i2;
611+ Boolean b;
612+ Real r;
613+
614+ case ("ModelicaInternal_countLines" , {Expression . STRING (s1)})
615+ then Expression . INTEGER (ModelicaExternalC . Streams_countLines (s1));
616+
617+ case ("ModelicaInternal_fullPathName" , {Expression . STRING (s1)})
618+ then Expression . STRING (ModelicaExternalC . File_fullPathName (s1));
619+
620+ case ("ModelicaInternal_print" , {Expression . STRING (s1), Expression . STRING (s2)})
621+ algorithm
622+ ModelicaExternalC . Streams_print (s1, s2);
623+ then
624+ Expression . INTEGER (0 );
625+
626+ case ("ModelicaInternal_readLine" , {Expression . STRING (s1), Expression . INTEGER (i)})
627+ algorithm
628+ (s1, b) := ModelicaExternalC . Streams_readLine (s1, i);
629+ then
630+ Expression . TUPLE (Type . TUPLE ({Type . STRING (), Type . BOOLEAN ()}, NONE ()),
631+ {Expression . STRING (s1), Expression . BOOLEAN (b)});
632+
633+ case ("ModelicaInternal_stat" , {Expression . STRING (s1)})
634+ algorithm
635+ i := ModelicaExternalC . File_stat (s1);
636+ then
637+ listGet(FILE_TYPE_LITERALS , i);
638+
639+ case ("ModelicaStreams_closeFile" , {Expression . STRING (s1)})
640+ algorithm
641+ ModelicaExternalC . Streams_close (s1);
642+ then
643+ Expression . INTEGER (0 );
644+
645+ case ("ModelicaString_compare" , {Expression . STRING (s1), Expression . STRING (s2), Expression . BOOLEAN (b)})
646+ algorithm
647+ i := ModelicaExternalC . Strings_compare (s1, s2, b);
648+ then
649+ listGet(COMPARE_LITERALS , i);
650+
651+ case ("ModelicaStrings_length" , {Expression . STRING (s1)})
652+ then Expression . INTEGER (stringLength(s1));
653+
654+ case ("ModelicaStrings_scanReal" , {Expression . STRING (s1), Expression . INTEGER (i), Expression . BOOLEAN (b)})
655+ algorithm
656+ (i, r) := ModelicaExternalC . Strings_advanced_scanReal (s1, i, b);
657+ then
658+ Expression . TUPLE (Type . TUPLE ({Type . INTEGER (), Type . BOOLEAN ()}, NONE ()),
659+ {Expression . INTEGER (i), Expression . REAL (r)});
660+
661+ case ("ModelicaStrings_skipWhiteSpace" , {Expression . STRING (s1), Expression . INTEGER (i)})
662+ then Expression . INTEGER (ModelicaExternalC . Strings_advanced_skipWhiteSpace (s1, i));
663+
664+ case ("ModelicaStrings_substring" , {Expression . STRING (s1), Expression . INTEGER (i), Expression . INTEGER (i2)})
665+ then Expression . STRING (System . substring(s1, i, i2));
666+
667+ case ("OpenModelica_regex" , _) then evaluateOpenModelicaRegex(args);
668+
669+ else
670+ algorithm
671+ Error . assertion(false , getInstanceName() + ": failed to evaluate " + name, sourceInfo());
672+ then
673+ fail();
674+ end match;
675+ end evaluateKnownExternal;
676+
677+ function evaluateOpenModelicaRegex
678+ input list< Expression > args;
679+ output Expression result;
680+ protected
681+ Integer n, i;
682+ String str, re;
683+ Boolean extended, insensitive;
684+ list< String > strs;
685+ list< Expression > expl;
686+ Type strs_ty;
687+ Expression strs_exp;
688+ algorithm
689+ result := match args
690+ case {Expression . STRING (str), Expression . STRING (re), Expression . INTEGER (i),
691+ Expression . BOOLEAN (extended), Expression . BOOLEAN (insensitive)}
692+ algorithm
693+ (n, strs) := System . regex(str, re, i, extended, insensitive);
694+ expl := list(Expression . STRING (s) for s in strs);
695+ strs_ty := Type . ARRAY (Type . STRING (), {Dimension . fromInteger(i)});
696+ strs_exp := Expression . ARRAY (strs_ty, expl);
697+ then
698+ Expression . TUPLE (Type . TUPLE ({Type . INTEGER (), strs_ty}, NONE ()),
699+ {Expression . INTEGER (n), strs_exp});
700+
701+ else
702+ algorithm
703+ Error . assertion(false , getInstanceName() + " failed on OpenModelica_regex" +
704+ List . toString(args, Expression . toString, "" , "(" , ", " , ")" , true ), sourceInfo());
705+ then
706+ fail();
707+ end match;
708+ end evaluateOpenModelicaRegex;
709+
492710annotation(__OpenModelica_Interface= "frontend" );
493711end NFEvalFunction ;
0 commit comments