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

Commit be0ab4e

Browse files
NF partial support for synchronous operators
- Added state machine related operators ("initialState", "transition","activeState", "ticksInState","timeInState") - Added several synchronous operators ("previous", "hold", "subSample", "superSample")
1 parent 8184464 commit be0ab4e

File tree

2 files changed

+251
-4
lines changed

2 files changed

+251
-4
lines changed

Compiler/NFFrontEnd/NFFunc.mo

Lines changed: 241 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,11 @@ algorithm
140140
SCode.COMMENT(NONE(), NONE()),
141141
NONE(),
142142
info), scope);
143-
144143
fakeComponent := Inst.instComponent(fakeComponent, scope, InstNode.parent(classNode));
145144

146145
// we need something better than this as this will type the function twice
147146
fakeComponent := Typing.typeComponent(fakeComponent);
148147
(classNode, classType) := Typing.typeClass(classNode);
149-
150148
// see if the class is a builtin function (including definitions in the ModelicaBuiltin.mo), record or normal function
151149

152150
// is builtin function defined in ModelicaBuiltin.mo
@@ -163,7 +161,6 @@ algorithm
163161

164162
// is normal function call
165163
(typedExp, ty, variability) := typeNormalFunction(functionName, functionArgs, prefix, classNode, classType, cls, scope, info);
166-
167164
end typeFunctionCall;
168165

169166
function getFunctionInputs
@@ -519,7 +516,19 @@ algorithm
519516
"cat",
520517
"rem",
521518
"actualStream",
522-
"inStream"});
519+
"inStream",
520+
// TODO Clock
521+
"previous",
522+
"hold",
523+
"subSample",
524+
"superSample",
525+
// TODO sample, shiftSample, backSample, noClock
526+
"initialState",
527+
"transition",
528+
"activeState",
529+
"ticksInState",
530+
"timeInState"
531+
});
523532
then
524533
b;
525534

@@ -745,6 +754,118 @@ algorithm
745754
then
746755
(typedExp, ty, vr);
747756

757+
case (Absyn.CREF_IDENT(name = "previous"), Absyn.FUNCTIONARGS(args = {aexp1}))
758+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
759+
algorithm
760+
// TODO? Check that aexp1 is a Component Expression (MLS 3.3, Section 16.2.3) or parameter expression
761+
(dexp1, ty, vr) := Typing.typeExp(aexp1, scope, info);
762+
// create the typed call
763+
typedExp := Expression.makeBuiltinCall("previous", {dexp1}, ty, true);
764+
then
765+
(typedExp, ty, vr);
766+
767+
case (Absyn.CREF_IDENT(name = "hold"), Absyn.FUNCTIONARGS(args = {aexp1}))
768+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
769+
algorithm
770+
// TODO? Check that aexp1 is a Component Expression (MLS 3.3, Section 16.2.3) or parameter expression
771+
(dexp1, ty, vr) := Typing.typeExp(aexp1, scope, info);
772+
// create the typed call
773+
typedExp := Expression.makeBuiltinCall("hold", {dexp1}, ty, true);
774+
then
775+
(typedExp, ty, vr);
776+
777+
// subSample(u)/superSample(u), subSample(u, factor)/superSample(u, factor)
778+
case (Absyn.CREF_IDENT(name = fnName), Absyn.FUNCTIONARGS(args = afargs))
779+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33) and
780+
listMember(fnName, {"subSample", "superSample"}) and
781+
(listLength(afargs) == 1 or listLength(afargs) == 2)
782+
algorithm
783+
if listLength(afargs) == 1 then
784+
aexp1 := listHead(afargs);
785+
// Create default argument factor=0
786+
dexp2 := Expression.INTEGER(0);
787+
else
788+
{aexp1, aexp2} := afargs;
789+
(dexp2, ty2, vr2) := Typing.typeExp(aexp2, scope, info);
790+
Type.INTEGER() := ty2;
791+
// TODO FIXME check if vr2 is a parameter expressions
792+
// TODO FIXME (evaluate) and check if factor >= 0
793+
end if;
794+
(dexp1, ty, vr) := Typing.typeExp(aexp1, scope, info);
795+
796+
// create the typed call
797+
typedExp := Expression.makeBuiltinCall(fnName, {dexp1, dexp2}, ty, true);
798+
then
799+
(typedExp, ty, vr);
800+
801+
// initialState(state)
802+
case (Absyn.CREF_IDENT(name = "initialState"), Absyn.FUNCTIONARGS(args = {aexp1}))
803+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
804+
algorithm
805+
(dexp1, ty1, vr) := Typing.typeExp(aexp1, scope, info);
806+
807+
// MLS 3.3 requires a 'block' instance as argument aexp1.
808+
// Checking here for 'complex' types is too broad, but convenient
809+
Error.assertionOrAddSourceMessage(Type.isComplex(ty1),Error.WRONG_TYPE_OR_NO_OF_ARGS,
810+
{"initialState(" + Expression.toString(dexp1) + "), Argument needs to be a block instance.",
811+
Absyn.pathString(InstNode.path(scope))}, info);
812+
813+
ty := Type.NORETCALL();
814+
815+
// create the typed call
816+
typedExp := Expression.makeBuiltinCall("initialState", {dexp1}, ty, true);
817+
then
818+
(typedExp, ty, vr);
819+
820+
// transition(from, to, condition, immediate=true, reset=true, synchronize=false, priority=1)
821+
case (Absyn.CREF_IDENT(name = "transition"), _)
822+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
823+
then
824+
elabBuiltinTransition(functionName, functionArgs, prefix, classNode, classType, cls, scope, info);
825+
826+
// activeState(state)
827+
case (Absyn.CREF_IDENT(name = "activeState"), Absyn.FUNCTIONARGS(args = {aexp1}))
828+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
829+
algorithm
830+
(dexp1, ty1, vr) := Typing.typeExp(aexp1, scope, info);
831+
832+
// MLS 3.3 requires a 'block' instance as argument aexp1.
833+
// Checking here for 'complex' types is too broad, but convenient
834+
Error.assertionOrAddSourceMessage(Type.isComplex(ty1),Error.WRONG_TYPE_OR_NO_OF_ARGS,
835+
{"activeState(" + Expression.toString(dexp1) + "), Argument needs to be a block instance.",
836+
Absyn.pathString(InstNode.path(scope))}, info);
837+
838+
ty := Type.BOOLEAN();
839+
840+
// create the typed call
841+
typedExp := Expression.makeBuiltinCall("activeState", {dexp1}, ty, true);
842+
then
843+
(typedExp, ty, vr);
844+
845+
// ticksInState()
846+
case (Absyn.CREF_IDENT(name = "ticksInState"), Absyn.FUNCTIONARGS(args = {}))
847+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
848+
algorithm
849+
ty := Type.INTEGER();
850+
vr := DAE.C_VAR();
851+
// create the typed call
852+
typedExp := Expression.makeBuiltinCall("ticksInState", {}, ty, true);
853+
then
854+
(typedExp, ty, vr);
855+
856+
// timeInState()
857+
case (Absyn.CREF_IDENT(name = "timeInState"), Absyn.FUNCTIONARGS(args = {}))
858+
guard intGe(Flags.getConfigEnum(Flags.LANGUAGE_STANDARD), 33)
859+
algorithm
860+
ty := Type.REAL();
861+
vr := DAE.C_VAR();
862+
// create the typed call
863+
typedExp := Expression.makeBuiltinCall("timeInState", {}, ty, true);
864+
then
865+
(typedExp, ty, vr);
866+
867+
868+
748869
/* adrpo: adapt these to the new structures, see above
749870
case (Absyn.CREF_IDENT(name = "product"), Absyn.FUNCTIONARGS(args = afargs))
750871
equation
@@ -910,6 +1031,122 @@ algorithm
9101031
end matchcontinue;
9111032
end typeBuiltinFunctionCall;
9121033

1034+
1035+
protected function elabBuiltinTransition
1036+
"elaborate the builtin operator
1037+
transition(from, to, condition, immediate=true, reset=true, synchronize=false, priority=1)"
1038+
input Absyn.ComponentRef functionName;
1039+
input Absyn.FunctionArgs functionArgs;
1040+
input Prefix prefix;
1041+
input InstNode classNode;
1042+
input Type classType;
1043+
input SCode.Element cls;
1044+
input InstNode scope;
1045+
input SourceInfo info;
1046+
output Expression typedExp;
1047+
output Type ty;
1048+
output DAE.Const variability;
1049+
protected
1050+
list<Absyn.Exp> afargs;
1051+
list<Absyn.NamedArg> anamed_args;
1052+
Absyn.Ident argName;
1053+
Absyn.Exp argValue;
1054+
array<Absyn.Exp> argExps = listArray({Absyn.STRING("from_NoDefault"), Absyn.STRING("to_NoDefault"), Absyn.STRING("condition_NoDefault"), Absyn.BOOL(true), Absyn.BOOL(true), Absyn.BOOL(false), Absyn.INTEGER(1)});
1055+
array<Absyn.Exp> afargsArray;
1056+
Expression dexp1, dexp2, dexp3, dexp4, dexp5, dexp6, dexp7;
1057+
Type ty1, ty2, ty3, ty4, ty5, ty6, ty7;
1058+
DAE.Const vr1, vr2, vr3, vr4, vr5, vr6, vr7;
1059+
String str;
1060+
Integer afargsLen;
1061+
algorithm
1062+
Absyn.FUNCTIONARGS(args=afargs, argNames=anamed_args) := functionArgs;
1063+
afargsArray := listArray(afargs);
1064+
afargsLen := listLength(afargs);
1065+
1066+
for i in 1:afargsLen loop
1067+
argExps := arrayUpdate(argExps, i, arrayGet(afargsArray,i));
1068+
end for;
1069+
1070+
for anamed in anamed_args loop
1071+
Absyn.NAMEDARG(argName, argValue) := anamed;
1072+
if argName == "from" and afargsLen < 1 then arrayUpdate(argExps, 1, argValue);
1073+
elseif argName == "to" and afargsLen < 2 then arrayUpdate(argExps, 2, argValue);
1074+
elseif argName == "condition" and afargsLen < 3 then arrayUpdate(argExps, 3, argValue);
1075+
elseif argName == "immediate" and afargsLen < 4 then arrayUpdate(argExps, 4, argValue);
1076+
elseif argName == "reset" and afargsLen < 5 then arrayUpdate(argExps, 5, argValue);
1077+
elseif argName == "synchronize" and afargsLen < 6 then arrayUpdate(argExps, 6, argValue);
1078+
elseif argName == "priority" and afargsLen < 7 then arrayUpdate(argExps, 7, argValue);
1079+
else
1080+
Error.addSourceMessageAndFail(Error.NO_SUCH_ARGUMENT,
1081+
{"transition(" + argName + "=" + Dump.dumpExpStr(argValue) + "), no such argument or conflict with unnamed arguments",
1082+
Absyn.pathString(InstNode.path(scope))}, info);
1083+
end if;
1084+
end for;
1085+
1086+
// check if first 3 mandatory arguments have been provided
1087+
for i in 1:3 loop
1088+
() := match arrayGet(argExps, i)
1089+
case Absyn.STRING(str)
1090+
algorithm
1091+
Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS,
1092+
{"transition(from, to, condition, immediate=true, reset=true, synchronize=false, priority=1), missing " + intString(i) + ". argument",
1093+
Absyn.pathString(InstNode.path(scope))}, info);
1094+
then fail();
1095+
else then ();
1096+
end match;
1097+
end for;
1098+
1099+
(dexp1, ty1, vr1) := Typing.typeExp(arrayGet(argExps,1), scope, info);
1100+
(dexp2, ty2, vr2) := Typing.typeExp(arrayGet(argExps,2), scope, info);
1101+
// MLS 3.3 requires a 'block' instances as argument 1 and 2.
1102+
// Checking here for 'complex' types is too broad, but convenient
1103+
Error.assertionOrAddSourceMessage(Type.isComplex(ty1),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1104+
{"transition(" + Expression.toString(dexp1) + ", ...), Argument needs to be a block instance.",
1105+
Absyn.pathString(InstNode.path(scope))}, info);
1106+
Error.assertionOrAddSourceMessage(Type.isComplex(ty2),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1107+
{"transition(..., " + Expression.toString(dexp2) + ", ...), Argument needs to be a block instance.",
1108+
Absyn.pathString(InstNode.path(scope))}, info);
1109+
1110+
// TODO check that variability of arguments below are parameter or constant
1111+
1112+
(dexp3, ty3, vr3) := Typing.typeExp(arrayGet(argExps,3), scope, info);
1113+
Error.assertionOrAddSourceMessage(Type.isBoolean(ty3),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1114+
{"transition(..., " + Expression.toString(dexp3) + ", ...), Argument needs to be of type Boolean.",
1115+
Absyn.pathString(InstNode.path(scope))}, info);
1116+
1117+
(dexp4, ty4, vr4) := Typing.typeExp(arrayGet(argExps,4), scope, info);
1118+
Error.assertionOrAddSourceMessage(Type.isBoolean(ty4),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1119+
{"transition(..., " + Expression.toString(dexp4) + ", ...), Argument needs to be of type Boolean.",
1120+
Absyn.pathString(InstNode.path(scope))}, info);
1121+
1122+
// Error.assertionOrAddSourceMessage(Types.isParameterOrConstant(vr4),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1123+
// {"transition(..., " + Expression.toString(dexp4) + ", ...), Argument needs to be of type Boolean.",
1124+
// Absyn.pathString(InstNode.path(scope))}, info);
1125+
1126+
(dexp5, ty5, vr5) := Typing.typeExp(arrayGet(argExps,5), scope, info);
1127+
Error.assertionOrAddSourceMessage(Type.isBoolean(ty5),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1128+
{"transition(..., " + Expression.toString(dexp5) + ", ...), Argument needs to be of type Boolean.",
1129+
Absyn.pathString(InstNode.path(scope))}, info);
1130+
1131+
(dexp6, ty6, vr6) := Typing.typeExp(arrayGet(argExps,6), scope, info);
1132+
Error.assertionOrAddSourceMessage(Type.isBoolean(ty6),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1133+
{"transition(..., " + Expression.toString(dexp6) + ", ...), Argument needs to be of type Boolean.",
1134+
Absyn.pathString(InstNode.path(scope))}, info);
1135+
1136+
(dexp7, ty7, vr7) := Typing.typeExp(arrayGet(argExps,7), scope, info);
1137+
// TODO check that "priority" argument is >= 1
1138+
Error.assertionOrAddSourceMessage(Type.isInteger(ty7),Error.WRONG_TYPE_OR_NO_OF_ARGS,
1139+
{"transition(..., " + Expression.toString(dexp7) + ", ...), Argument needs to be of type Integer.",
1140+
Absyn.pathString(InstNode.path(scope))}, info);
1141+
1142+
1143+
ty := Type.NORETCALL();
1144+
// create the typed call
1145+
typedExp := Expression.makeBuiltinCall("transition", {dexp1, dexp2, dexp3, dexp4, dexp5, dexp6, dexp7}, ty, true);
1146+
variability := DAE.C_UNKNOWN();
1147+
end elabBuiltinTransition;
1148+
1149+
9131150
function getFunctionAttributes
9141151
input InstNode funcNode;
9151152
output DAE.FunctionAttributes attr;

Compiler/NFFrontEnd/NFType.mo

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ public
178178
end match;
179179
end isEnumeration;
180180

181+
function isComplex
182+
input Type ty;
183+
output Boolean isComplex;
184+
algorithm
185+
isComplex := match ty
186+
case COMPLEX() then true;
187+
else false;
188+
end match;
189+
end isComplex;
190+
181191
function isScalarArray
182192
input Type ty;
183193
output Boolean isScalar;

0 commit comments

Comments
 (0)