From 3048851a8ff43dec570e1b5a84067181f23d4a2f Mon Sep 17 00:00:00 2001 From: Adrian Pop Date: Wed, 19 Sep 2018 06:20:16 +0200 Subject: [PATCH] all synchronous features except state machines should work (ticket:5127) - do not constant evaluate impure functions - better fix for sample that requires no patching of NFModelicaBuiltin.mo Belonging to [master]: - OpenModelica/OMCompiler#2667 --- Compiler/FFrontEnd/FBuiltin.mo | 53 ++---- Compiler/FrontEnd/NFSCodeDependency.mo | 9 +- Compiler/NFFrontEnd/NFCall.mo | 20 +++ Compiler/NFFrontEnd/NFCeval.mo | 5 +- Compiler/NFFrontEnd/NFExpression.mo | 205 ++++++++++++++++++++++- Compiler/NFFrontEnd/NFModelicaBuiltin.mo | 31 ++-- 6 files changed, 263 insertions(+), 60 deletions(-) diff --git a/Compiler/FFrontEnd/FBuiltin.mo b/Compiler/FFrontEnd/FBuiltin.mo index 69cc31d420..c97c4f4e32 100644 --- a/Compiler/FFrontEnd/FBuiltin.mo +++ b/Compiler/FFrontEnd/FBuiltin.mo @@ -362,7 +362,7 @@ algorithm (initialProgram,initialSCodeProgram) := matchcontinue () local - list,tuple>> assocLst; + list>> assocLst; list classes,classes1,classes2; Absyn.Program p; SCode.Program sp; @@ -374,60 +374,56 @@ algorithm case () equation assocLst = getGlobalRoot(Global.builtinIndex); - ((p,sp)) = Util.assoc((Flags.getConfigEnum(Flags.GRAMMAR), Config.getLanguageStandard()), assocLst); + ((p,sp)) = Util.assoc(Flags.getConfigEnum(Flags.GRAMMAR), assocLst); then (p,sp); case () equation true = intEq(Flags.getConfigEnum(Flags.GRAMMAR), Flags.METAMODELICA); Error.assertionOrAddSourceMessage(System.regularFileExists(fileModelica),Error.FILE_NOT_FOUND_ERROR,{fileModelica},Absyn.dummyInfo); Error.assertionOrAddSourceMessage(System.regularFileExists(fileMetaModelica),Error.FILE_NOT_FOUND_ERROR,{fileMetaModelica},Absyn.dummyInfo); - Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = - patchSample(Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA)); + Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); Absyn.PROGRAM(classes=classes2,within_=Absyn.TOP()) = Parser.parsebuiltin(fileMetaModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); classes = listAppend(classes1,classes2); p = Absyn.PROGRAM(classes,Absyn.TOP()); (p as Absyn.PROGRAM(classes=classes)) = MetaUtil.createMetaClassesInProgram(p); sp = List.map(classes, SCodeUtil.translateClass); assocLst = getGlobalRoot(Global.builtinIndex); - setGlobalRoot(Global.builtinIndex, ((Flags.METAMODELICA, Config.getLanguageStandard()), (p,sp))::assocLst); + setGlobalRoot(Global.builtinIndex, (Flags.METAMODELICA,(p,sp))::assocLst); then (p,sp); case () equation true = intEq(Flags.getConfigEnum(Flags.GRAMMAR), Flags.PARMODELICA); Error.assertionOrAddSourceMessage(System.regularFileExists(fileModelica),Error.FILE_NOT_FOUND_ERROR,{fileModelica},Absyn.dummyInfo); Error.assertionOrAddSourceMessage(System.regularFileExists(fileParModelica),Error.FILE_NOT_FOUND_ERROR,{fileParModelica},Absyn.dummyInfo); - Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = - patchSample(Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA)); + Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); Absyn.PROGRAM(classes=classes2,within_=Absyn.TOP()) = Parser.parsebuiltin(fileParModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); classes = listAppend(classes1,classes2); p = Absyn.PROGRAM(classes,Absyn.TOP()); sp = List.map(classes, SCodeUtil.translateClass); assocLst = getGlobalRoot(Global.builtinIndex); - setGlobalRoot(Global.builtinIndex, ((Flags.PARMODELICA,Config.getLanguageStandard()), (p,sp))::assocLst); + setGlobalRoot(Global.builtinIndex, (Flags.PARMODELICA,(p,sp))::assocLst); then (p,sp); case () equation true = intEq(Flags.getConfigEnum(Flags.GRAMMAR), Flags.MODELICA) or intEq(Flags.getConfigEnum(Flags.GRAMMAR), Flags.OPTIMICA); Error.assertionOrAddSourceMessage(System.regularFileExists(fileModelica),Error.FILE_NOT_FOUND_ERROR,{fileModelica},Absyn.dummyInfo); - (p as Absyn.PROGRAM(classes=classes)) = - patchSample(Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA)); + (p as Absyn.PROGRAM(classes=classes)) = Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); sp = List.map(classes, SCodeUtil.translateClass); assocLst = getGlobalRoot(Global.builtinIndex); - setGlobalRoot(Global.builtinIndex, ((Flags.MODELICA, Config.getLanguageStandard()), (p,sp))::assocLst); + setGlobalRoot(Global.builtinIndex, (Flags.MODELICA,(p,sp))::assocLst); then (p,sp); case () equation true = intEq(Flags.getConfigEnum(Flags.GRAMMAR), Flags.PDEMODELICA); Error.assertionOrAddSourceMessage(System.regularFileExists(fileModelica),Error.FILE_NOT_FOUND_ERROR,{fileModelica},Absyn.dummyInfo); Error.assertionOrAddSourceMessage(System.regularFileExists(filePDEModelica),Error.FILE_NOT_FOUND_ERROR,{filePDEModelica},Absyn.dummyInfo); - Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = - patchSample(Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA)); + Absyn.PROGRAM(classes=classes1,within_=Absyn.TOP()) = Parser.parsebuiltin(fileModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); Absyn.PROGRAM(classes=classes2,within_=Absyn.TOP()) = Parser.parsebuiltin(filePDEModelica,"UTF-8","",NONE(),acceptedGram=Flags.METAMODELICA); classes = listAppend(classes1,classes2); p = Absyn.PROGRAM(classes,Absyn.TOP()); sp = List.map(classes, SCodeUtil.translateClass); assocLst = getGlobalRoot(Global.builtinIndex); - setGlobalRoot(Global.builtinIndex, ((Flags.PDEMODELICA, Config.getLanguageStandard()), (p,sp))::assocLst); + setGlobalRoot(Global.builtinIndex, (Flags.PDEMODELICA,(p,sp))::assocLst); then (p,sp); else @@ -437,35 +433,6 @@ algorithm end matchcontinue; end getInitialFunctions; -protected function patchSample -"patch sample definition if --std < 3.3" - input output Absyn.Program p; -protected - list classes; - Absyn.Within w; -algorithm - if not Config.synchronousFeaturesAllowed() then - Absyn.PROGRAM(classes, w) := p; - classes := List.map(classes, samplePatch); - p := Absyn.PROGRAM(classes, w); - end if; -end patchSample; - -protected function samplePatch - input Absyn.Class inCls; - output Absyn.Class outCls; -protected - Absyn.Class c; - Option cmt; - list functionNames; -algorithm - outCls := match(inCls) - case c as Absyn.CLASS(name="sample", body = Absyn.OVERLOAD(functionNames, cmt)) - then Absyn.setClassBody(c, Absyn.OVERLOAD({listHead(functionNames),listHead(functionNames)}, cmt)); - else inCls; - end match; -end samplePatch; - public function initialGraph "The initial environment where instantiation takes place is built up using this function. It creates an empty environment and adds diff --git a/Compiler/FrontEnd/NFSCodeDependency.mo b/Compiler/FrontEnd/NFSCodeDependency.mo index 001ba4127b..5c98d84864 100644 --- a/Compiler/FrontEnd/NFSCodeDependency.mo +++ b/Compiler/FrontEnd/NFSCodeDependency.mo @@ -45,6 +45,7 @@ public import NFSCodeEnv; public type Env = NFSCodeEnv.Env; +protected import Config; protected import Debug; protected import Error; protected import Flags; @@ -579,8 +580,12 @@ algorithm // Other cases which doesn't need to be analysed. case (SCode.ENUMERATION(), _, _, _, _) then (); case (SCode.OVERLOAD(pathLst = paths), _, _, _, _) - equation - List.map2_0(paths,analyseClass,inEnv,inInfo); + algorithm + if not Config.synchronousFeaturesAllowed() and Absyn.pathFirstIdent(listHead(paths)) == "OMC_NO_CLOCK" then + List.map2_0({listHead(paths)},analyseClass,inEnv,inInfo); + else + List.map2_0(paths,analyseClass,inEnv,inInfo); + end if; then (); case (SCode.PDER(), _, _, _, _) then (); diff --git a/Compiler/NFFrontEnd/NFCall.mo b/Compiler/NFFrontEnd/NFCall.mo index 835971a30f..8d1ca6ce2a 100644 --- a/Compiler/NFFrontEnd/NFCall.mo +++ b/Compiler/NFFrontEnd/NFCall.mo @@ -477,6 +477,16 @@ uniontype Call end match; end isExternal; + function isImpure + input Call call; + output Boolean isImpure; + algorithm + isImpure := match call + case TYPED_CALL() then Function.isImpure(call.fn); + else false; + end match; + end isImpure; + function isRecordConstructor input Call call; output Boolean isConstructor; @@ -1203,6 +1213,16 @@ protected then Type.arrayElementType(Expression.typeOf(Expression.unbox(listHead(args)))); case Absyn.IDENT("previous") then Expression.typeOf(Expression.unbox(listHead(args))); + case Absyn.IDENT("shiftSample") + then Expression.typeOf(Expression.unbox(listHead(args))); + case Absyn.IDENT("backSample") + then Expression.typeOf(Expression.unbox(listHead(args))); + case Absyn.IDENT("hold") + then Expression.typeOf(Expression.unbox(listHead(args))); + case Absyn.IDENT("superSample") + then Expression.typeOf(Expression.unbox(listHead(args))); + case Absyn.IDENT("subSample") + then Expression.typeOf(Expression.unbox(listHead(args))); else algorithm Error.assertion(false, getInstanceName() + ": unhandled case for " + diff --git a/Compiler/NFFrontEnd/NFCeval.mo b/Compiler/NFFrontEnd/NFCeval.mo index ad8e4ca59f..ceb4bbd63a 100644 --- a/Compiler/NFFrontEnd/NFCeval.mo +++ b/Compiler/NFFrontEnd/NFCeval.mo @@ -173,7 +173,10 @@ algorithm exp; case Expression.CALL() - then evalCall(exp.call, target); + then + if Call.isImpure(exp.call) // do NOT evaluate impure calls! + then exp + else evalCall(exp.call, target); case Expression.SIZE(dimIndex = SOME(exp1)) algorithm diff --git a/Compiler/NFFrontEnd/NFExpression.mo b/Compiler/NFFrontEnd/NFExpression.mo index bcc5d0767b..a1b9e936fd 100644 --- a/Compiler/NFFrontEnd/NFExpression.mo +++ b/Compiler/NFFrontEnd/NFExpression.mo @@ -87,6 +87,40 @@ public Expression solverMethod " string type "; end SOLVER_CLOCK; + function compare + input ClockKind ck1; + input ClockKind ck2; + output Integer comp; + algorithm + comp := match (ck1, ck2) + local + Expression i1, ic1, r1, c1, si1, sm1, i2, ic2, r2, c2, si2, sm2; + case (INFERRED_CLOCK(), INFERRED_CLOCK()) then 0; + case (INTEGER_CLOCK(i1, r1),INTEGER_CLOCK(i2, r2)) + algorithm + comp := Expression.compare(i1, i2); + if (comp == 0) then + comp := Expression.compare(r1, r2); + end if; + then comp; + case (REAL_CLOCK(i1), REAL_CLOCK(i2)) then Expression.compare(i1, i2); + case (BOOLEAN_CLOCK(c1, si1), BOOLEAN_CLOCK(c2, si2)) + algorithm + comp := Expression.compare(c1, c2); + if (comp == 0) then + comp := Expression.compare(si1, si2); + end if; + then comp; + case (SOLVER_CLOCK(c1, sm2), SOLVER_CLOCK(c2, sm1)) + algorithm + comp := Expression.compare(c1, c2); + if (comp == 0) then + comp := Expression.compare(sm1, sm2); + end if; + then comp; + end match; + end compare; + function toDAE input ClockKind ick; output DAE.ClockKind ock; @@ -376,6 +410,7 @@ public Operator op; Call c; list subs; + ClockKind clk1, clk2; case INTEGER() algorithm @@ -401,6 +436,12 @@ public then Util.boolCompare(exp1.value, b); + case CLKCONST(clk1) + algorithm + CLKCONST(clk2) := exp2; + then + ClockKind.compare(clk1, clk2); + case CREF() algorithm CREF(cref = cr) := exp2; @@ -618,6 +659,7 @@ public case STRING() then Type.STRING(); case BOOLEAN() then Type.BOOLEAN(); case ENUM_LITERAL() then exp.ty; + case CLKCONST() then Type.CLOCK(); case CREF() then exp.ty; case ARRAY() then exp.ty; case RANGE() then exp.ty; @@ -1475,6 +1517,41 @@ public local Expression e1, e2, e3, e4; + case CLKCONST(ClockKind.INTEGER_CLOCK(e1, e2)) + algorithm + e3 := map(e1, func); + e4 := map(e2, func); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.INTEGER_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.REAL_CLOCK(e1)) + algorithm + e2 := map(e1, func); + then + if referenceEq(e1, e2) + then exp + else CLKCONST(ClockKind.REAL_CLOCK(e2)); + + case CLKCONST(ClockKind.BOOLEAN_CLOCK(e1, e2)) + algorithm + e3 := map(e1, func); + e4 := map(e2, func); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.BOOLEAN_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2)) + algorithm + e3 := map(e1, func); + e4 := map(e2, func); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.SOLVER_CLOCK(e3, e4)); + case CREF() then CREF(exp.ty, mapCref(exp.cref, func)); case ARRAY() then ARRAY(exp.ty, list(map(e, func) for e in exp.elements)); case MATRIX() then MATRIX(list(list(map(e, func) for e in row) for row in exp.elements)); @@ -1752,6 +1829,41 @@ public local Expression e1, e2, e3, e4; + case CLKCONST(ClockKind.INTEGER_CLOCK(e1, e2)) + algorithm + e3 := func(e1); + e4 := func(e2); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.INTEGER_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.REAL_CLOCK(e1)) + algorithm + e2 := func(e1); + then + if referenceEq(e1, e2) + then exp + else CLKCONST(ClockKind.REAL_CLOCK(e2)); + + case CLKCONST(ClockKind.BOOLEAN_CLOCK(e1, e2)) + algorithm + e3 := func(e1); + e4 := func(e2); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.BOOLEAN_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2)) + algorithm + e3 := func(e1); + e4 := func(e2); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.SOLVER_CLOCK(e3, e4)); + case CREF() then CREF(exp.ty, mapCrefShallow(exp.cref, func)); case ARRAY() then ARRAY(exp.ty, list(func(e) for e in exp.elements)); case MATRIX() then MATRIX(list(list(func(e) for e in row) for row in exp.elements)); @@ -2061,7 +2173,34 @@ public algorithm result := match exp local - Expression e; + Expression e, e1, e2; + + case CLKCONST(ClockKind.INTEGER_CLOCK(e1, e2)) + algorithm + result := fold(e1, func, arg); + result := fold(e2, func, result); + then + result; + + case CLKCONST(ClockKind.REAL_CLOCK(e1)) + algorithm + result := fold(e1, func, arg); + then + result; + + case CLKCONST(ClockKind.BOOLEAN_CLOCK(e1, e2)) + algorithm + result := fold(e1, func, arg); + result := fold(e2, func, result); + then + result; + + case CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2)) + algorithm + result := fold(e1, func, arg); + result := fold(e2, func, result); + then + result; case CREF() then foldCref(exp.cref, func, arg); case ARRAY() then foldList(exp.elements, func, arg); @@ -2260,7 +2399,34 @@ public algorithm () := match exp local - Expression e; + Expression e, e1, e2; + + case CLKCONST(ClockKind.INTEGER_CLOCK(e1, e2)) + algorithm + apply(e1, func); + apply(e2, func); + then + (); + + case CLKCONST(ClockKind.REAL_CLOCK(e1)) + algorithm + apply(e1, func); + then + (); + + case CLKCONST(ClockKind.BOOLEAN_CLOCK(e1, e2)) + algorithm + apply(e1, func); + apply(e2, func); + then + (); + + case CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2)) + algorithm + apply(e1, func); + apply(e2, func); + then + (); case CREF() algorithm applyCref(exp.cref, func); then (); case ARRAY() algorithm applyList(exp.elements, func); then (); @@ -2480,6 +2646,41 @@ public Call call; list subs; + case CLKCONST(ClockKind.INTEGER_CLOCK(e1, e2)) + algorithm + (e3, arg) := mapFold(e1, func, arg); + (e4, arg) := mapFold(e2, func, arg); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.INTEGER_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.REAL_CLOCK(e1)) + algorithm + (e2, arg) := mapFold(e1, func, arg); + then + if referenceEq(e1, e2) + then exp + else CLKCONST(ClockKind.REAL_CLOCK(e2)); + + case CLKCONST(ClockKind.BOOLEAN_CLOCK(e1, e2)) + algorithm + (e3, arg) := mapFold(e1, func, arg); + (e4, arg) := mapFold(e2, func, arg); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.BOOLEAN_CLOCK(e3, e4)); + + case CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2)) + algorithm + (e3, arg) := mapFold(e1, func, arg); + (e4, arg) := mapFold(e2, func, arg); + then + if referenceEq(e1, e3) and referenceEq(e2, e4) + then exp + else CLKCONST(ClockKind.SOLVER_CLOCK(e3, e4)); + case CREF() algorithm (cr, arg) := mapFoldCref(exp.cref, func, arg); diff --git a/Compiler/NFFrontEnd/NFModelicaBuiltin.mo b/Compiler/NFFrontEnd/NFModelicaBuiltin.mo index ea2674c587..f21426ef94 100644 --- a/Compiler/NFFrontEnd/NFModelicaBuiltin.mo +++ b/Compiler/NFFrontEnd/NFModelicaBuiltin.mo @@ -540,25 +540,33 @@ end OMC_NO_CLOCK; package OMC_CLOCK impure function sample "Overloaded operator to either trigger time events or to convert between continuous-time and clocked-time representation" input T u; - input Clock c = Clock(); + input Clock c = OpenModelica.Internal.inferredClock(); output T o; external "builtin"; - annotation(Documentation(info=" + annotation(version="Modelica 3.3", Documentation(info=" See sample() ")); end sample; end OMC_CLOCK; -function shiftSample "First activation of clock is shifted in time" +function shiftSample "First activation of clock is shifted in time" + input T u; + parameter input Integer shiftCounter(min = 0); + parameter input Integer resolution(min = 1) = 1; + output T c; external "builtin"; - annotation(Documentation(info=" + annotation(__OpenModelica_UnboxArguments=true, version="Modelica 3.3", Documentation(info=" See shiftSample() ")); end shiftSample; -function backSample "First activation of clock is shifted in time before activation of u" +function backSample "First activation of clock is shifted in time before activation of u" + input T u; + parameter input Integer backCounter(min = 0); + parameter input Integer resolution(min = 1) = 1; + output T c; external "builtin"; - annotation(Documentation(info=" + annotation(__OpenModelica_UnboxArguments=true, version="Modelica 3.3", Documentation(info=" See backSample() ")); end backSample; @@ -875,16 +883,15 @@ package OMC_ARGS end interval; end OMC_ARGS; - function subSample = $overload(OpenModelica.Internal.subSampleExpression, OpenModelica.Internal.subSampleClock) "Conversion from faster clock to slower clock" - annotation(version="Modelica 3.3", Documentation(info=" + annotation(__OpenModelica_UnboxArguments=true, version="Modelica 3.3", Documentation(info=" See subSample() ")); function superSample = $overload(OpenModelica.Internal.superSampleExpression, OpenModelica.Internal.superSampleClock) "Conversion from slower clock to faster clock" - annotation(version="Modelica 3.3", Documentation(info=" + annotation(__OpenModelica_UnboxArguments=true, version="Modelica 3.3", Documentation(info=" See superSample() ")); @@ -989,20 +996,20 @@ package Internal "Contains internal implementations, e.g. overloaded builtin fun function rationalClock input Integer intervalCounter(min=0); - parameter input Integer resolution(unit="Hz", min=1)=1; + parameter input Integer resolution(min = 1) = 1; output Clock c; external "builtin"; end rationalClock; function realClock - input Real interval(unit="s", min=0); + input Real interval(unit="s", min = 0); output Clock c; external "builtin"; end realClock; function booleanClock input Boolean condition; - input Real startInterval=0.0; + input Real startInterval = 0.0; output Clock c; external "builtin"; end booleanClock;