Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit ace473c

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Add evalution of known external functions.
Belonging to [master]: - #2409
1 parent bc4b3e1 commit ace473c

File tree

2 files changed

+230
-1
lines changed

2 files changed

+230
-1
lines changed

Compiler/NFFrontEnd/NFClass.mo

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,17 @@ uniontype Class
175175
end match;
176176
end initExpandedClass;
177177

178+
function getSections
179+
input Class cls;
180+
output Sections sections;
181+
algorithm
182+
sections := match cls
183+
case INSTANCED_CLASS() then cls.sections;
184+
case TYPED_DERIVED() then getSections(InstNode.getClass(cls.baseClass));
185+
else Sections.EMPTY();
186+
end match;
187+
end getSections;
188+
178189
function setSections
179190
input Sections sections;
180191
input output Class cls;

Compiler/NFFrontEnd/NFEvalFunction.mo

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,15 @@ import ComponentRef = NFComponentRef;
4141
import Binding = NFBinding;
4242
import NFComponent.Component;
4343
import Type = NFType;
44+
import Dimension = NFDimension;
4445

4546
protected
4647
import Ceval = NFCeval;
4748
import MetaModelica.Dangerous.*;
4849
import RangeIterator = NFRangeIterator;
4950
import ElementSource;
51+
import ModelicaExternalC;
52+
import System;
5053

5154
encapsulated 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;
8398
protected
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

124165
protected
125166

@@ -489,5 +530,182 @@ algorithm
489530
end while;
490531
end 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+
492710
annotation(__OpenModelica_Interface="frontend");
493711
end NFEvalFunction;

0 commit comments

Comments
 (0)