From 07e8590f254ca586d3e0ac37e1fe33a3721716ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Mon, 10 Aug 2020 13:13:38 +0200 Subject: [PATCH] [NF] Detect recursive bindings during evaluation. --- OMCompiler/Compiler/NFFrontEnd/NFBinding.mo | 5 +++++ OMCompiler/Compiler/NFFrontEnd/NFCeval.mo | 14 +++++++++++++ .../flattening/modelica/scodeinst/Makefile | 1 + .../modelica/scodeinst/RecursiveConstants1.mo | 20 +++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 testsuite/flattening/modelica/scodeinst/RecursiveConstants1.mo diff --git a/OMCompiler/Compiler/NFFrontEnd/NFBinding.mo b/OMCompiler/Compiler/NFFrontEnd/NFBinding.mo index b2bb6da194f..240c9a955cf 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFBinding.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFBinding.mo @@ -105,6 +105,11 @@ public list errors; end INVALID_BINDING; + record EVALUATING_BINDING + "Used by the constant evaluation to detect recursive bindings." + Binding binding; + end EVALUATING_BINDING; + public function fromAbsyn input Option bindingExp; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFCeval.mo b/OMCompiler/Compiler/NFFrontEnd/NFCeval.mo index b66c8fd2fb1..e1485879409 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFCeval.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFCeval.mo @@ -65,6 +65,7 @@ import TypeCheck = NFTypeCheck; import ExpandExp = NFExpandExp; import ElementSource; import Flags; +import Prefixes = NFPrefixes; public uniontype EvalTarget @@ -399,6 +400,11 @@ algorithm if binding.evaluated then exp := binding.bindingExp; else + // Mark the binding as currently being evaluated, to detect loops due + // to mutually dependent constants/parameters. + comp := Component.setBinding(Binding.EVALUATING_BINDING(binding), comp); + InstNode.updateComponent(comp, node); + exp := evalExp_impl(binding.bindingExp, target); binding.bindingExp := exp; @@ -417,6 +423,14 @@ algorithm then (defaultExp, false); + case Binding.EVALUATING_BINDING() + algorithm + Error.addSourceMessage(Error.CIRCULAR_PARAM, + {InstNode.name(node), Prefixes.variabilityString(Component.variability(comp))}, + InstNode.info(node)); + then + fail(); + else algorithm Error.addInternalError(getInstanceName() + " failed on untyped binding", sourceInfo()); diff --git a/testsuite/flattening/modelica/scodeinst/Makefile b/testsuite/flattening/modelica/scodeinst/Makefile index 9d6a1ca4d1e..3066957f91c 100644 --- a/testsuite/flattening/modelica/scodeinst/Makefile +++ b/testsuite/flattening/modelica/scodeinst/Makefile @@ -734,6 +734,7 @@ RecordConstructor2.mo \ RecordExtends1.mo \ RecordExtends2.mo \ RecordUnknownDim1.mo \ +RecursiveConstants1.mo \ RecursiveExtends1.mo \ RecursiveExtends3.mo \ RecursiveInst1.mo \ diff --git a/testsuite/flattening/modelica/scodeinst/RecursiveConstants1.mo b/testsuite/flattening/modelica/scodeinst/RecursiveConstants1.mo new file mode 100644 index 00000000000..5186fa770ae --- /dev/null +++ b/testsuite/flattening/modelica/scodeinst/RecursiveConstants1.mo @@ -0,0 +1,20 @@ +// name: RecursiveConstants1 +// keywords: +// status: incorrect +// cflags: -d=newInst +// + +model RecursiveConstants1 + constant Real x = y; + constant Real y = x; +end RecursiveConstants1; + +// Result: +// Error processing file: RecursiveConstants1.mo +// [flattening/modelica/scodeinst/RecursiveConstants1.mo:9:3-9:22:writable] Error: Variable 'y' has a cyclic dependency and has variability constant. +// +// # Error encountered! Exiting... +// # Please check the error message and the flags. +// +// Execution failed! +// endResult